...
This commit is contained in:
parent
d21b5cccfe
commit
4dff342b70
46
client.go
46
client.go
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
34
handlers.go
34
handlers.go
|
@ -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")
|
||||||
|
|
|
@ -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)))
|
||||||
|
|
28
server.go
28
server.go
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue