2012-04-07 20:44:59 +02:00
|
|
|
package irc
|
|
|
|
|
|
|
|
import (
|
|
|
|
"log"
|
|
|
|
"net"
|
2012-04-18 07:21:41 +02:00
|
|
|
"time"
|
2012-04-07 20:44:59 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type Server struct {
|
2012-12-13 08:27:17 +01:00
|
|
|
hostname string
|
|
|
|
ctime time.Time
|
|
|
|
name string
|
|
|
|
recv chan<- Message
|
|
|
|
password string
|
|
|
|
nicks map[string]*Client
|
|
|
|
channels map[string]*Channel
|
2012-04-18 03:16:57 +02:00
|
|
|
}
|
|
|
|
|
2012-04-18 07:11:35 +02:00
|
|
|
func NewServer(name string) *Server {
|
2012-12-13 08:27:17 +01:00
|
|
|
recv := make(chan Message)
|
2012-12-09 21:51:50 +01:00
|
|
|
server := &Server{
|
|
|
|
ctime: time.Now(),
|
|
|
|
name: name,
|
|
|
|
recv: recv,
|
|
|
|
nicks: make(map[string]*Client),
|
|
|
|
channels: make(map[string]*Channel),
|
|
|
|
}
|
2012-12-09 07:54:58 +01:00
|
|
|
go func() {
|
|
|
|
for m := range recv {
|
2012-12-13 08:27:17 +01:00
|
|
|
m.Client().atime = time.Now()
|
|
|
|
m.Handle(server, m.Client())
|
2012-12-09 07:54:58 +01:00
|
|
|
}
|
|
|
|
}()
|
2012-04-18 03:16:57 +02:00
|
|
|
return server
|
2012-04-07 20:44:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Server) Listen(addr string) {
|
|
|
|
listener, err := net.Listen("tcp", addr)
|
|
|
|
if err != nil {
|
2012-04-08 08:32:08 +02:00
|
|
|
log.Fatal("Server.Listen: ", err)
|
2012-04-07 20:44:59 +02:00
|
|
|
}
|
|
|
|
|
2012-12-09 07:54:58 +01:00
|
|
|
s.hostname = LookupHostname(listener.Addr())
|
|
|
|
log.Print("Server.Listen: listening on ", addr)
|
|
|
|
|
2012-04-07 20:44:59 +02:00
|
|
|
for {
|
|
|
|
conn, err := listener.Accept()
|
|
|
|
if err != nil {
|
2012-04-08 08:32:08 +02:00
|
|
|
log.Print("Server.Listen: ", err)
|
2012-04-07 20:44:59 +02:00
|
|
|
continue
|
|
|
|
}
|
2012-12-09 07:54:58 +01:00
|
|
|
log.Print("Server.Listen: accepted ", conn.RemoteAddr())
|
2012-12-13 08:27:17 +01:00
|
|
|
go NewClient(s, conn)
|
2012-12-09 07:54:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Server) GetOrMakeChannel(name string) *Channel {
|
|
|
|
channel := s.channels[name]
|
|
|
|
|
|
|
|
if channel == nil {
|
|
|
|
channel = NewChannel(s, name)
|
|
|
|
s.channels[name] = channel
|
|
|
|
}
|
|
|
|
|
|
|
|
return channel
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send a message to clients of channels fromClient is a member.
|
|
|
|
func (s *Server) SendToInterestedClients(fromClient *Client, reply Reply) {
|
2012-12-13 08:27:17 +01:00
|
|
|
|
|
|
|
clients := make(ClientSet)
|
2012-12-09 21:51:50 +01:00
|
|
|
clients[fromClient] = true
|
2012-12-09 07:54:58 +01:00
|
|
|
for channel := range fromClient.channels {
|
|
|
|
for client := range channel.members {
|
|
|
|
clients[client] = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for client := range clients {
|
|
|
|
client.send <- reply
|
2012-04-07 20:44:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-09 07:54:58 +01:00
|
|
|
// server functionality
|
|
|
|
|
|
|
|
func (s *Server) ChangeNick(c *Client, newNick string) {
|
|
|
|
if s.nicks[newNick] != nil {
|
|
|
|
c.send <- ErrNickNameInUse(s, newNick)
|
|
|
|
return
|
2012-04-09 16:57:55 +02:00
|
|
|
}
|
2012-12-13 08:27:17 +01:00
|
|
|
s.SendToInterestedClients(c, RplNick(c, newNick))
|
2012-12-09 07:54:58 +01:00
|
|
|
|
|
|
|
if c.nick != "" {
|
|
|
|
delete(s.nicks, c.nick)
|
|
|
|
}
|
2012-12-12 08:34:41 +01:00
|
|
|
s.nicks[newNick] = c
|
2012-12-09 21:51:50 +01:00
|
|
|
c.nick = newNick
|
|
|
|
|
|
|
|
s.tryRegister(c)
|
2012-12-09 07:54:58 +01:00
|
|
|
}
|
|
|
|
|
2012-12-09 21:51:50 +01:00
|
|
|
func (s *Server) UserLogin(c *Client, user string, realName string) {
|
2012-12-09 07:54:58 +01:00
|
|
|
if c.username != "" {
|
|
|
|
c.send <- ErrAlreadyRegistered(s)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
c.username, c.realname = user, realName
|
2012-12-09 21:51:50 +01:00
|
|
|
s.tryRegister(c)
|
2012-12-09 07:54:58 +01:00
|
|
|
}
|
|
|
|
|
2012-12-09 21:51:50 +01:00
|
|
|
func (s *Server) tryRegister(c *Client) {
|
2012-12-12 07:34:22 +01:00
|
|
|
if !c.registered && c.HasNick() && c.HasUser() && (s.password == "" || c.serverPass) {
|
2012-12-09 07:54:58 +01:00
|
|
|
c.registered = true
|
|
|
|
c.send <- RplWelcome(s, c)
|
|
|
|
c.send <- RplYourHost(s, c)
|
|
|
|
c.send <- RplCreated(s)
|
|
|
|
c.send <- RplMyInfo(s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Server) Quit(c *Client, message string) {
|
|
|
|
for channel := range c.channels {
|
|
|
|
channel.Part(c, message)
|
|
|
|
}
|
|
|
|
delete(s.nicks, c.nick)
|
2012-12-13 08:27:17 +01:00
|
|
|
s.SendToInterestedClients(c, RplQuit(c, message))
|
2012-12-09 07:54:58 +01:00
|
|
|
c.conn.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Server) ChangeUserMode(c *Client, modes []string) {
|
|
|
|
for _, mode := range modes {
|
2012-12-10 05:24:53 +01:00
|
|
|
switch mode {
|
|
|
|
case "+w":
|
|
|
|
c.wallOps = true
|
|
|
|
case "-w":
|
|
|
|
c.wallOps = false
|
2012-12-09 07:54:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
c.send <- RplUModeIs(s, c)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Server) Id() string {
|
|
|
|
return s.hostname
|
2012-04-07 20:44:59 +02:00
|
|
|
}
|
2012-12-13 08:27:17 +01:00
|
|
|
|
|
|
|
func (s *Server) DeleteChannel(channel *Channel) {
|
|
|
|
delete(s.channels, channel.name)
|
|
|
|
}
|