Allow connections to be restarted, catch SIGHUP

This commit is contained in:
Trevor Slocum 2016-09-15 23:12:25 -07:00
parent 5f2275700d
commit 691aa1c1ba
3 changed files with 95 additions and 44 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
.idea
*.iml
*.db
*.sh
AnonIRCd
anonircd
anonircd.conf

View File

@ -23,10 +23,10 @@ import (
"sync"
"time"
"github.com/BurntSushi/toml"
irc "gopkg.in/sorcix/irc.v2"
"log"
"os"
"os/signal"
"syscall"
)
var anonymous = irc.Prefix{"Anonymous", "Anon", "IRC"}
@ -41,11 +41,6 @@ _| _| _| _| _|_| _| _| _|_|_| _| _| _|_|_|
`
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
type Config struct {
SSLCert string
SSLKey string
}
type Pair struct {
Key string
Value int
@ -85,13 +80,16 @@ func randomIdentifier() string {
func main() {
rand.Seed(time.Now().UTC().UnixNano())
var config Config
if _, err := os.Stat("anonircd.conf"); err == nil {
if _, err := toml.DecodeFile("anonircd.conf", &config); err != nil {
log.Fatalf("Failed to read anonircd.conf: %v", err)
}
}
server := Server{&Config{}, time.Now().Unix(), make(map[string]*Client), make(map[string]*Channel), make(chan bool, 1), make(chan bool, 1), new(sync.RWMutex)}
server.loadConfig()
sighup := make(chan os.Signal, 1)
signal.Notify(sighup,
syscall.SIGHUP)
go func() {
_ = <-sighup
server.reload()
}()
server := Server{&config, time.Now().Unix(), make(map[string]*Client), make(map[string]*Channel), new(sync.RWMutex)}
server.listen()
}

112
server.go
View File

@ -10,17 +10,27 @@ import (
"time"
"crypto/tls"
"github.com/BurntSushi/toml"
irc "gopkg.in/sorcix/irc.v2"
"math/rand"
"os"
"reflect"
)
type Config struct {
SSLCert string
SSLKey string
}
type Server struct {
config *Config
created int64
clients map[string]*Client
channels map[string]*Channel
restartplain chan bool
restartssl chan bool
*sync.RWMutex
}
@ -358,12 +368,12 @@ func (s *Server) handleRead(c *Client) {
c.conn.SetDeadline(time.Now().Add(300 * time.Second))
msg, err := s.clients[c.identifier].reader.Decode()
if err != nil {
fmt.Println("Unable to read from client:", err)
log.Println("Unable to read from client:", err)
s.partAllChannels(c.identifier)
return
}
if msg.Command != irc.PING && msg.Command != irc.PONG {
fmt.Println(c.identifier, "<-", fmt.Sprintf("%s", msg))
log.Println(c.identifier, "<-", fmt.Sprintf("%s", msg))
}
if msg.Command == irc.CAP && len(msg.Params) > 0 && len(msg.Params[0]) > 0 && msg.Params[0] == irc.CAP_LS {
c.writebuffer <- &irc.Message{&anonirc, irc.CAP, []string{msg.Params[0], "userhost-in-names"}}
@ -480,7 +490,7 @@ func (s *Server) handleWrite(c *Client) {
}
if msg.Command != irc.PING && msg.Command != irc.PONG {
fmt.Println(c.identifier, "->", msg)
log.Println(c.identifier, "->", msg)
}
c.writer.Encode(msg)
}
@ -508,45 +518,70 @@ func (s *Server) handleConnection(conn net.Conn, ssl bool) {
}
func (s *Server) listenPlain() {
listen, err := net.Listen("tcp", ":6667")
if err != nil {
log.Fatalf("Failed to listen: %v", err)
}
defer listen.Close()
for {
conn, err := listen.Accept()
listen, err := net.Listen("tcp", ":6667")
if err != nil {
fmt.Println("Error accepting connection:", err)
log.Println("Failed to listen: %v", err)
time.Sleep(1 * time.Minute)
continue
}
go s.handleConnection(conn, false)
log.Println("Listening on 6667")
accept:
for {
select {
case _ = <-s.restartplain:
break accept
default:
conn, err := listen.Accept()
if err != nil {
log.Println("Error accepting connection:", err)
continue
}
go s.handleConnection(conn, true)
}
}
listen.Close()
}
}
func (s *Server) listenSSL() {
if s.config.SSLCert == "" {
return // SSL is disabled
}
cert, err := tls.LoadX509KeyPair(s.config.SSLCert, s.config.SSLKey)
if err != nil {
log.Fatalf("Failed to load SSL certificate: %v", err)
}
listen, err := tls.Listen("tcp", ":6697", &tls.Config{Certificates: []tls.Certificate{cert}})
if err != nil {
log.Fatalf("Failed to listen: %v", err)
}
defer listen.Close()
for {
conn, err := listen.Accept()
if s.config.SSLCert == "" {
time.Sleep(1 * time.Minute)
return // SSL is disabled
}
cert, err := tls.LoadX509KeyPair(s.config.SSLCert, s.config.SSLKey)
if err != nil {
fmt.Println("Error accepting connection:", err)
log.Println("Failed to load SSL certificate: %v", err)
time.Sleep(1 * time.Minute)
continue
}
go s.handleConnection(conn, true)
listen, err := tls.Listen("tcp", ":6697", &tls.Config{Certificates: []tls.Certificate{cert}})
if err != nil {
log.Println("Failed to listen: %v", err)
time.Sleep(1 * time.Minute)
continue
}
log.Println("Listening on +6697")
accept:
for {
select {
case _ = <-s.restartssl:
break accept
default:
conn, err := listen.Accept()
if err != nil {
log.Println("Error accepting connection:", err)
continue
}
go s.handleConnection(conn, true)
}
}
listen.Close()
}
}
@ -559,6 +594,23 @@ func (s *Server) pingClients() {
}
}
func (s *Server) loadConfig() {
s.Lock()
if _, err := os.Stat("anonircd.conf"); err == nil {
if _, err := toml.DecodeFile("anonircd.conf", &s.config); err != nil {
log.Fatalf("Failed to read anonircd.conf: %v", err)
}
}
s.Unlock()
}
func (s *Server) reload() {
log.Println("Reloading configuration")
s.loadConfig()
s.restartplain <- true
s.restartssl <- true
}
func (s *Server) listen() {
go s.listenPlain()
go s.listenSSL()