You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

server.go 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. package irc
  2. import (
  3. "crypto/rand"
  4. "crypto/tls"
  5. "encoding/binary"
  6. "fmt"
  7. "log"
  8. "net"
  9. "time"
  10. )
  11. type Server struct {
  12. channels ChannelNameMap
  13. commands chan<- Command
  14. ctime time.Time
  15. hostname string
  16. name string
  17. operators map[string]string
  18. password string
  19. clients ClientNameMap
  20. }
  21. func NewServer(config *Config) *Server {
  22. commands := make(chan Command)
  23. server := &Server{
  24. channels: make(ChannelNameMap),
  25. clients: make(ClientNameMap),
  26. commands: commands,
  27. ctime: time.Now(),
  28. name: config.Name,
  29. operators: make(map[string]string),
  30. password: config.Password,
  31. }
  32. for _, opConf := range config.Operators {
  33. server.operators[opConf.Name] = opConf.Password
  34. }
  35. go server.receiveCommands(commands)
  36. for _, listenerConf := range config.Listeners {
  37. go server.listen(listenerConf)
  38. }
  39. return server
  40. }
  41. func (server *Server) receiveCommands(commands <-chan Command) {
  42. for command := range commands {
  43. if DEBUG_SERVER {
  44. log.Printf("%s → %s : %s", command.Client(), server, command)
  45. }
  46. client := command.Client()
  47. client.Touch()
  48. if !client.serverPass {
  49. if server.password == "" {
  50. client.serverPass = true
  51. } else if _, ok := command.(*PassCommand); !ok {
  52. client.Reply(ErrPasswdMismatch(server))
  53. client.Destroy()
  54. return
  55. }
  56. }
  57. command.HandleServer(server)
  58. }
  59. }
  60. func newListener(config ListenerConfig) (net.Listener, error) {
  61. if config.IsTLS() {
  62. certificate, err := tls.LoadX509KeyPair(config.Certificate, config.Key)
  63. if err != nil {
  64. return nil, err
  65. }
  66. return tls.Listen("tcp", config.Address, &tls.Config{
  67. Certificates: []tls.Certificate{certificate},
  68. PreferServerCipherSuites: true,
  69. MinVersion: tls.VersionTLS12,
  70. })
  71. }
  72. return net.Listen("tcp", config.Address)
  73. }
  74. func (s *Server) listen(config ListenerConfig) {
  75. listener, err := newListener(config)
  76. if err != nil {
  77. log.Fatal("Server.Listen: ", err)
  78. }
  79. s.hostname = LookupHostname(listener.Addr())
  80. log.Print("Server.Listen: listening on ", config.Address)
  81. for {
  82. conn, err := listener.Accept()
  83. if err != nil {
  84. log.Print("Server.Accept: ", err)
  85. continue
  86. }
  87. if DEBUG_SERVER {
  88. log.Print("Server.Accept: ", conn.RemoteAddr())
  89. }
  90. NewClient(s, conn)
  91. }
  92. }
  93. func (s *Server) GetOrMakeChannel(name string) *Channel {
  94. channel := s.channels[name]
  95. if channel == nil {
  96. channel = NewChannel(s, name)
  97. s.channels[name] = channel
  98. }
  99. return channel
  100. }
  101. func (s *Server) GenerateGuestNick() string {
  102. bytes := make([]byte, 8)
  103. for {
  104. _, err := rand.Read(bytes)
  105. if err != nil {
  106. panic(err)
  107. }
  108. randInt, n := binary.Uvarint(bytes)
  109. if n <= 0 {
  110. continue // TODO handle error
  111. }
  112. nick := fmt.Sprintf("guest%d", randInt)
  113. if s.clients[nick] == nil {
  114. return nick
  115. }
  116. }
  117. }
  118. // server functionality
  119. func (s *Server) tryRegister(c *Client) {
  120. if !c.registered && c.HasNick() && c.HasUsername() {
  121. c.registered = true
  122. replies := []Reply{
  123. RplWelcome(s, c),
  124. RplYourHost(s),
  125. RplCreated(s),
  126. RplMyInfo(s),
  127. }
  128. for _, reply := range replies {
  129. c.Reply(reply)
  130. }
  131. }
  132. }
  133. func (s *Server) Id() string {
  134. return s.name
  135. }
  136. func (s *Server) String() string {
  137. return s.name
  138. }
  139. func (s *Server) Nick() string {
  140. return s.Id()
  141. }
  142. //
  143. // commands
  144. //
  145. func (m *UnknownCommand) HandleServer(s *Server) {
  146. m.Client().Reply(ErrUnknownCommand(s, m.command))
  147. }
  148. func (m *PingCommand) HandleServer(s *Server) {
  149. m.Client().Reply(RplPong(s, m.Client()))
  150. }
  151. func (m *PongCommand) HandleServer(s *Server) {
  152. // no-op
  153. }
  154. func (m *PassCommand) HandleServer(s *Server) {
  155. if s.password != m.password {
  156. m.Client().Reply(ErrPasswdMismatch(s))
  157. m.Client().Destroy()
  158. return
  159. }
  160. m.Client().serverPass = true
  161. // no reply?
  162. }
  163. func (m *NickCommand) HandleServer(s *Server) {
  164. c := m.Client()
  165. if s.clients[m.nickname] != nil {
  166. c.Reply(ErrNickNameInUse(s, m.nickname))
  167. return
  168. }
  169. if !c.HasNick() {
  170. c.nick = m.nickname
  171. }
  172. reply := RplNick(c, m.nickname)
  173. for iclient := range c.InterestedClients() {
  174. iclient.Reply(reply)
  175. }
  176. s.clients.Remove(c)
  177. c.nick = m.nickname
  178. s.clients.Add(c)
  179. s.tryRegister(c)
  180. }
  181. func (m *UserMsgCommand) HandleServer(s *Server) {
  182. c := m.Client()
  183. if c.registered {
  184. c.Reply(ErrAlreadyRegistered(s))
  185. return
  186. }
  187. c.username, c.realname = m.user, m.realname
  188. s.tryRegister(c)
  189. }
  190. func (m *QuitCommand) HandleServer(s *Server) {
  191. c := m.Client()
  192. s.clients.Remove(c)
  193. for channel := range c.channels {
  194. channel.members.Remove(c)
  195. }
  196. c.Reply(RplError(s, c))
  197. c.Destroy()
  198. reply := RplQuit(c, m.message)
  199. for client := range c.InterestedClients() {
  200. client.Reply(reply)
  201. }
  202. }
  203. func (m *JoinCommand) HandleServer(s *Server) {
  204. c := m.Client()
  205. if m.zero {
  206. cmd := &PartCommand{}
  207. cmd.SetClient(c)
  208. for channel := range c.channels {
  209. channel.commands <- cmd
  210. }
  211. return
  212. }
  213. for name := range m.channels {
  214. s.GetOrMakeChannel(name).commands <- m
  215. }
  216. }
  217. func (m *PartCommand) HandleServer(s *Server) {
  218. for _, chname := range m.channels {
  219. channel := s.channels[chname]
  220. if channel == nil {
  221. m.Client().Reply(ErrNoSuchChannel(s, channel.name))
  222. continue
  223. }
  224. channel.commands <- m
  225. }
  226. }
  227. func (m *TopicCommand) HandleServer(s *Server) {
  228. channel := s.channels[m.channel]
  229. if channel == nil {
  230. m.Client().Reply(ErrNoSuchChannel(s, m.channel))
  231. return
  232. }
  233. channel.commands <- m
  234. }
  235. func (m *PrivMsgCommand) HandleServer(s *Server) {
  236. if m.TargetIsChannel() {
  237. channel := s.channels[m.target]
  238. if channel == nil {
  239. m.Client().Reply(ErrNoSuchChannel(s, m.target))
  240. return
  241. }
  242. channel.commands <- m
  243. return
  244. }
  245. target := s.clients[m.target]
  246. if target == nil {
  247. m.Client().Reply(ErrNoSuchNick(s, m.target))
  248. return
  249. }
  250. target.Reply(RplPrivMsg(m.Client(), target, m.message))
  251. }
  252. func (m *ModeCommand) HandleServer(s *Server) {
  253. client := m.Client()
  254. if client.Nick() == m.nickname {
  255. for _, change := range m.changes {
  256. if change.mode == Invisible {
  257. switch change.op {
  258. case Add:
  259. client.invisible = true
  260. case Remove:
  261. client.invisible = false
  262. }
  263. }
  264. }
  265. client.Reply(RplUModeIs(s, client))
  266. return
  267. }
  268. client.Reply(ErrUsersDontMatch(client))
  269. }
  270. func (m *WhoisCommand) HandleServer(server *Server) {
  271. client := m.Client()
  272. // TODO implement target query
  273. if m.target != "" {
  274. client.Reply(ErrNoSuchServer(server, m.target))
  275. return
  276. }
  277. for _, mask := range m.masks {
  278. // TODO implement wildcard matching
  279. mclient := server.clients[mask]
  280. if mclient != nil {
  281. client.Reply(RplWhoisUser(server, mclient))
  282. }
  283. }
  284. client.Reply(RplEndOfWhois(server))
  285. }
  286. func (msg *ChannelModeCommand) HandleServer(server *Server) {
  287. client := msg.Client()
  288. channel := server.channels[msg.channel]
  289. if channel == nil {
  290. client.Reply(ErrNoSuchChannel(server, msg.channel))
  291. return
  292. }
  293. channel.commands <- msg
  294. }
  295. func whoChannel(client *Client, server *Server, channel *Channel) {
  296. for member := range channel.members {
  297. client.Reply(RplWhoReply(server, channel, member))
  298. }
  299. }
  300. func (msg *WhoCommand) HandleServer(server *Server) {
  301. client := msg.Client()
  302. // TODO implement wildcard matching
  303. mask := string(msg.mask)
  304. if mask == "" {
  305. for _, channel := range server.channels {
  306. whoChannel(client, server, channel)
  307. }
  308. } else if IsChannel(mask) {
  309. channel := server.channels[mask]
  310. if channel != nil {
  311. whoChannel(client, server, channel)
  312. }
  313. } else {
  314. mclient := server.clients[mask]
  315. if mclient != nil {
  316. client.Reply(RplWhoReply(server, mclient.channels.First(), mclient))
  317. }
  318. }
  319. client.Reply(RplEndOfWho(server, mask))
  320. }
  321. func (msg *OperCommand) HandleServer(server *Server) {
  322. client := msg.Client()
  323. if server.operators[msg.name] != msg.password {
  324. client.Reply(ErrPasswdMismatch(server))
  325. return
  326. }
  327. client.operator = true
  328. client.Reply(RplYoureOper(server))
  329. client.Reply(RplUModeIs(server, client))
  330. }