This commit is contained in:
an 2017-08-22 07:23:30 +02:00
parent d21b5cccfe
commit 4dff342b70
5 changed files with 91 additions and 26 deletions

View File

@ -3,7 +3,7 @@
package ircd package ircd
import ( import (
"bufio" "bytes"
"fmt" "fmt"
"io" "io"
"net" "net"
@ -119,7 +119,7 @@ func (cl *RemoteClient) Destroy() {
func (cl *RemoteClient) dispatcher() { func (cl *RemoteClient) dispatcher() {
for { for {
time.Sleep(1 * time.Millisecond) time.Sleep(10 * time.Millisecond)
if cl.isClosed { if cl.isClosed {
return return
} }
@ -140,34 +140,56 @@ func (cl *RemoteClient) dispatcher() {
} }
} }
func (cl *RemoteClient) connReader() { /*func (cl *RemoteClient) pinger() {
input := bufio.NewReader(cl.conn)
for { for {
time.Sleep(30 * time.Second)
if cl.isClosed {
return
}
cl.writeLine("PING %s", cl.server.host)
}
}*/
func (cl *RemoteClient) connReader() {
for {
time.Sleep(10 * time.Millisecond)
buf := make([]byte, 4096)
if cl.isClosed { if cl.isClosed {
xlog.Debug("connReader: exiting") xlog.Debug("connReader: exiting")
return return
} }
s, err := input.ReadString('\n') cl.conn.SetReadDeadline(time.Now().Add(time.Second * 5))
n, err := cl.conn.Read(buf)
if err == io.EOF { if err == io.EOF {
xlog.Info("connReader: Connection closed by peer") xlog.Info("connReader: Connection closed by peer")
cl.server.DelClient(cl) cl.server.DelClient(cl)
return return
} }
if err != nil { if err != nil {
xlog.Error("connReader: %s", err.Error()) continue
cl.server.DelClient(cl) }
return raw := buf[:n]
raw = bytes.Replace(raw, []byte("\r\n"), []byte("\n"), -1)
raw = bytes.Replace(raw, []byte("\r"), []byte("\n"), -1)
lines := bytes.Split(raw, []byte("\n"))
for _, line := range lines {
if len(line) > 0 {
cl.handleCmd(string(line))
}
} }
s = strings.Trim(s, "\r\n")
cl.handleCmd(s)
} }
} }
func (cl *RemoteClient) connWriter() { func (cl *RemoteClient) connWriter() {
for line := range cl.writeq { for line := range cl.writeq {
time.Sleep(10 * time.Millisecond)
if cl.isClosed {
return
}
written := 0 written := 0
bytes := []byte(line + "\r\n") bytes := []byte(line + "\r\n")
for written < len(line) { for written < len(line) {
cl.conn.SetWriteDeadline(time.Now().Add(time.Second * 5))
n, err := cl.conn.Write(bytes[written:]) n, err := cl.conn.Write(bytes[written:])
if err == io.EOF { if err == io.EOF {
xlog.Info("connWriter: Connection closed by peer") xlog.Info("connWriter: Connection closed by peer")
@ -185,6 +207,10 @@ func (cl *RemoteClient) connWriter() {
} }
func (cl *RemoteClient) writeMsg(msg *irc.Message) { func (cl *RemoteClient) writeMsg(msg *irc.Message) {
clid := strings.ToLower(msg.Pre)
if _, exists := cl.server.clients[clid]; exists {
msg.Pre = msg.Pre + "!" + msg.Pre + "@" + cl.server.clHosts[clid]
}
cl.writeLine(msg.String()) cl.writeLine(msg.String())
} }

View File

@ -3,6 +3,7 @@
package ircd package ircd
import ( import (
"fmt"
"strings" "strings"
"code.dnix.de/an/irc" "code.dnix.de/an/irc"
@ -25,8 +26,10 @@ var svCommandHooks = map[string]commandHook{
"TOPIC": {handleCmdTopic, 1, false, ""}, "TOPIC": {handleCmdTopic, 1, false, ""},
"KICK": {handleCmdKick, 2, false, ""}, "KICK": {handleCmdKick, 2, false, ""},
"NAMES": {handleCmdNames, 1, false, ""}, "NAMES": {handleCmdNames, 1, false, ""},
"WHO": {handleCmdWho, 1, false, ""},
"WHOIS": {handleCmdWhois, 0, false, ""}, "WHOIS": {handleCmdWhois, 0, false, ""},
"PING": {handleCmdPing, 1, false, ""}, "PING": {handleCmdPing, 1, false, ""},
"PONG": {handleCmdPong, 0, false, ""},
"REHASH": {handleCmdRehash, 0, false, "ao"}, "REHASH": {handleCmdRehash, 0, false, "ao"},
"KILL": {handleCmdKill, 0, false, "ao"}, "KILL": {handleCmdKill, 0, false, "ao"},
/* /*
@ -235,14 +238,43 @@ func handleCmdNames(sv *Server, msg *irc.Message) {
sv.channelNames(msg.Pre, chid) sv.channelNames(msg.Pre, chid)
} }
func handleCmdWho(sv *Server, msg *irc.Message) {
clid := strings.ToLower(msg.Args[0])
if _, exists := sv.clients[clid]; exists {
// :irc.dnix.de 352 Anydin #northbrigade webuser369 -anon/guest irc.dnix.de webuser36968 H :0 webuser36968
sv.sendReply(msg.Pre, RPL_WHOREPLY,
fmt.Sprintf("* %s %s %s %s %s%s", clid, sv.clHosts[clid], sv.host, clid, "H", ""), "0 "+msg.Args[0])
}
sv.sendReply(msg.Pre, RPL_ENDOFWHO, clid, "End of /WHO list.")
}
func handleCmdWhois(sv *Server, msg *irc.Message) { func handleCmdWhois(sv *Server, msg *irc.Message) {
sv.sendReply(msg.Pre, RPL_WHOISUSER, "nick user host *", "real name") clid := strings.ToLower(msg.Args[0])
if _, exists := sv.clients[clid]; !exists {
sv.sendReply(msg.Pre, ERR_NOSUCHNICK, clid, "No such nick")
return
}
sv.sendReply(msg.Pre, RPL_WHOISUSER, fmt.Sprintf("%s %s %s *", clid, clid, sv.clHosts[clid]), msg.Args[0])
m, isoper := sv.opers[clid]
if isoper {
if m == "a" {
sv.sendReply(msg.Pre, RPL_WHOISOPERATOR, clid, "is a server administrator")
}
if m == "o" {
sv.sendReply(msg.Pre, RPL_WHOISOPERATOR, clid, "is a server operator")
}
}
sv.sendReply(msg.Pre, RPL_ENDOFWHOIS, "", "End of /WHOIS list")
} }
func handleCmdPing(sv *Server, msg *irc.Message) { func handleCmdPing(sv *Server, msg *irc.Message) {
sv.sendReply(msg.Pre, "PONG", msg.Args[0], "") sv.sendReply(msg.Pre, "PONG", msg.Args[0], "")
} }
func handleCmdPong(sv *Server, msg *irc.Message) {
}
func handleCmdRehash(sv *Server, msg *irc.Message) { func handleCmdRehash(sv *Server, msg *irc.Message) {
sv.loadConfig() sv.loadConfig()
sv.sendReply(msg.Pre, RPL_REHASHING, "", "Rehashing") sv.sendReply(msg.Pre, RPL_REHASHING, "", "Rehashing")

View File

@ -58,7 +58,7 @@ func monitoringRun(sv *Server) {
func monitoringUpdater(sv *Server) { func monitoringUpdater(sv *Server) {
for { for {
time.Sleep(5 * time.Second) time.Sleep(10 * time.Second)
gaugeGoroutinesRunning.Set(float64(runtime.NumGoroutine())) gaugeGoroutinesRunning.Set(float64(runtime.NumGoroutine()))
gaugePacketsTransferred.Set(sv.packetsTransferred) gaugePacketsTransferred.Set(sv.packetsTransferred)
gaugeConnectionsCurrent.Set(float64(len(sv.clients))) gaugeConnectionsCurrent.Set(float64(len(sv.clients)))

View File

@ -46,6 +46,7 @@ type Server struct {
clients map[string]Client clients map[string]Client
clModes map[string]string clModes map[string]string
clHosts map[string]string
services map[string]*Service services map[string]*Service
@ -59,7 +60,7 @@ type Server struct {
packetsTransferred float64 packetsTransferred float64
connectionsCount float64 connectionsCount float64
authCallback func(name, pass string) bool authCallback func(name, pass string) (string, bool)
} }
func NewServer(configPath, software, version string) *Server { func NewServer(configPath, software, version string) *Server {
@ -76,6 +77,7 @@ func NewServer(configPath, software, version string) *Server {
sv.clients = make(map[string]Client) sv.clients = make(map[string]Client)
sv.clModes = make(map[string]string) sv.clModes = make(map[string]string)
sv.clHosts = make(map[string]string)
sv.services = make(map[string]*Service, 0) sv.services = make(map[string]*Service, 0)
@ -98,11 +100,11 @@ func NewServer(configPath, software, version string) *Server {
nicks, _ := sv.config.GetString("control", "a") nicks, _ := sv.config.GetString("control", "a")
for _, nick := range strings.Split(nicks, ",") { for _, nick := range strings.Split(nicks, ",") {
sv.opers[nick] = "a" sv.opers[strings.ToLower(nick)] = "a"
} }
nicks, _ = sv.config.GetString("control", "o") nicks, _ = sv.config.GetString("control", "o")
for _, nick := range strings.Split(nicks, ",") { for _, nick := range strings.Split(nicks, ",") {
sv.opers[nick] = "o" sv.opers[strings.ToLower(nick)] = "o"
} }
sv.packetsTransferred = 0 sv.packetsTransferred = 0
@ -111,7 +113,7 @@ func NewServer(configPath, software, version string) *Server {
return sv return sv
} }
func (sv *Server) SetAuthCallback(authCB func(name, pass string) bool) { func (sv *Server) SetAuthCallback(authCB func(name, pass string) (string, bool)) {
sv.authCallback = authCB sv.authCallback = authCB
} }
@ -232,7 +234,7 @@ func (sv *Server) dispatcher() (err error) {
case cl := <-sv.delq: case cl := <-sv.delq:
sv.delClient(cl) sv.delClient(cl)
default: default:
time.Sleep(100 * time.Microsecond) time.Sleep(10 * time.Millisecond)
} }
} }
return return
@ -258,7 +260,15 @@ func (sv *Server) addClient(cl Client) {
xlog.Info("Client registration failed: '%s' (client exists)", clid) xlog.Info("Client registration failed: '%s' (client exists)", clid)
return return
} }
if !sv.authCallback(cl.Name(), cl.Password()) { if host, success := sv.authCallback(cl.Name(), cl.Password()); success {
sv.clients[clid] = cl
sv.clHosts[clid] = host
sv.sendLogon(cl.Name())
cl.Register(true)
sv.cluster.Subscribe(clid, sv.remoteq)
xlog.Info("Client registered: '%s'", clid)
xlog.Info("Server has %d client(s)", len(sv.clients))
} else {
cl.Receive(irc.M(sv.host, ERR_PASSWDMISMATCH, "", "Password incorrect")) cl.Receive(irc.M(sv.host, ERR_PASSWDMISMATCH, "", "Password incorrect"))
go func() { go func() {
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
@ -267,12 +277,6 @@ func (sv *Server) addClient(cl Client) {
xlog.Info("Client registration failed: '%s' (wrong password)", clid) xlog.Info("Client registration failed: '%s' (wrong password)", clid)
return return
} }
sv.clients[clid] = cl
sv.sendLogon(cl.Name())
cl.Register(true)
sv.cluster.Subscribe(clid, sv.remoteq)
xlog.Info("Client registered: '%s'", clid)
xlog.Info("Server has %d client(s)", len(sv.clients))
} }
func (sv *Server) delClient(cl Client) { func (sv *Server) delClient(cl Client) {

View File

@ -23,6 +23,9 @@ func (svc *Service) Run() {
go svc.dispatcher() go svc.dispatcher()
} }
func (svc *Service) Stop() {
}
func (svc *Service) Dispatch(msg *irc.Message) { func (svc *Service) Dispatch(msg *irc.Message) {
svc.recvq <- msg svc.recvq <- msg
} }
@ -33,13 +36,13 @@ func (svc *Service) Handler(cmd string, fn func(*irc.Message)) {
func (svc *Service) dispatcher() { func (svc *Service) dispatcher() {
for { for {
time.Sleep(10 * time.Millisecond)
select { select {
case msg := <-svc.recvq: case msg := <-svc.recvq:
if fn, exists := sv.handlers[msg.Pre]; exists { if fn, exists := svc.handlers[msg.Pre]; exists {
fn(msg) fn(msg)
} }
default: default:
time.Sleep(100 * time.Microsecond)
} }
} }
return return