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
import (
"bufio"
"bytes"
"fmt"
"io"
"net"
@ -119,7 +119,7 @@ func (cl *RemoteClient) Destroy() {
func (cl *RemoteClient) dispatcher() {
for {
time.Sleep(1 * time.Millisecond)
time.Sleep(10 * time.Millisecond)
if cl.isClosed {
return
}
@ -140,34 +140,56 @@ func (cl *RemoteClient) dispatcher() {
}
}
func (cl *RemoteClient) connReader() {
input := bufio.NewReader(cl.conn)
/*func (cl *RemoteClient) pinger() {
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 {
xlog.Debug("connReader: exiting")
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 {
xlog.Info("connReader: Connection closed by peer")
cl.server.DelClient(cl)
return
}
if err != nil {
xlog.Error("connReader: %s", err.Error())
cl.server.DelClient(cl)
return
continue
}
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() {
for line := range cl.writeq {
time.Sleep(10 * time.Millisecond)
if cl.isClosed {
return
}
written := 0
bytes := []byte(line + "\r\n")
for written < len(line) {
cl.conn.SetWriteDeadline(time.Now().Add(time.Second * 5))
n, err := cl.conn.Write(bytes[written:])
if err == io.EOF {
xlog.Info("connWriter: Connection closed by peer")
@ -185,6 +207,10 @@ func (cl *RemoteClient) connWriter() {
}
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())
}

View File

@ -3,6 +3,7 @@
package ircd
import (
"fmt"
"strings"
"code.dnix.de/an/irc"
@ -25,8 +26,10 @@ var svCommandHooks = map[string]commandHook{
"TOPIC": {handleCmdTopic, 1, false, ""},
"KICK": {handleCmdKick, 2, false, ""},
"NAMES": {handleCmdNames, 1, false, ""},
"WHO": {handleCmdWho, 1, false, ""},
"WHOIS": {handleCmdWhois, 0, false, ""},
"PING": {handleCmdPing, 1, false, ""},
"PONG": {handleCmdPong, 0, false, ""},
"REHASH": {handleCmdRehash, 0, false, "ao"},
"KILL": {handleCmdKill, 0, false, "ao"},
/*
@ -235,14 +238,43 @@ func handleCmdNames(sv *Server, msg *irc.Message) {
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) {
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) {
sv.sendReply(msg.Pre, "PONG", msg.Args[0], "")
}
func handleCmdPong(sv *Server, msg *irc.Message) {
}
func handleCmdRehash(sv *Server, msg *irc.Message) {
sv.loadConfig()
sv.sendReply(msg.Pre, RPL_REHASHING, "", "Rehashing")

View File

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

View File

@ -46,6 +46,7 @@ type Server struct {
clients map[string]Client
clModes map[string]string
clHosts map[string]string
services map[string]*Service
@ -59,7 +60,7 @@ type Server struct {
packetsTransferred float64
connectionsCount float64
authCallback func(name, pass string) bool
authCallback func(name, pass string) (string, bool)
}
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.clModes = make(map[string]string)
sv.clHosts = make(map[string]string)
sv.services = make(map[string]*Service, 0)
@ -98,11 +100,11 @@ func NewServer(configPath, software, version string) *Server {
nicks, _ := sv.config.GetString("control", "a")
for _, nick := range strings.Split(nicks, ",") {
sv.opers[nick] = "a"
sv.opers[strings.ToLower(nick)] = "a"
}
nicks, _ = sv.config.GetString("control", "o")
for _, nick := range strings.Split(nicks, ",") {
sv.opers[nick] = "o"
sv.opers[strings.ToLower(nick)] = "o"
}
sv.packetsTransferred = 0
@ -111,7 +113,7 @@ func NewServer(configPath, software, version string) *Server {
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
}
@ -232,7 +234,7 @@ func (sv *Server) dispatcher() (err error) {
case cl := <-sv.delq:
sv.delClient(cl)
default:
time.Sleep(100 * time.Microsecond)
time.Sleep(10 * time.Millisecond)
}
}
return
@ -258,7 +260,15 @@ func (sv *Server) addClient(cl Client) {
xlog.Info("Client registration failed: '%s' (client exists)", clid)
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"))
go func() {
time.Sleep(5 * time.Second)
@ -267,12 +277,6 @@ func (sv *Server) addClient(cl Client) {
xlog.Info("Client registration failed: '%s' (wrong password)", clid)
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) {

View File

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