Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. package irc
  2. import (
  3. "bufio"
  4. "database/sql"
  5. "fmt"
  6. "log"
  7. "net"
  8. "net/http"
  9. "os"
  10. "os/signal"
  11. "strings"
  12. "syscall"
  13. "time"
  14. )
  15. type ServerCommand interface {
  16. Command
  17. HandleServer(*Server)
  18. }
  19. type RegServerCommand interface {
  20. Command
  21. HandleRegServer(*Server)
  22. }
  23. type Server struct {
  24. channels ChannelNameMap
  25. clients *ClientLookupSet
  26. commands chan Command
  27. ctime time.Time
  28. db *sql.DB
  29. idle chan *Client
  30. motdFile string
  31. name Name
  32. newConns chan net.Conn
  33. operators map[Name][]byte
  34. password []byte
  35. signals chan os.Signal
  36. whoWas *WhoWasList
  37. theaters map[Name][]byte
  38. isupport *ISupportList
  39. }
  40. var (
  41. SERVER_SIGNALS = []os.Signal{syscall.SIGINT, syscall.SIGHUP,
  42. syscall.SIGTERM, syscall.SIGQUIT}
  43. )
  44. func NewServer(config *Config) *Server {
  45. server := &Server{
  46. channels: make(ChannelNameMap),
  47. clients: NewClientLookupSet(),
  48. commands: make(chan Command),
  49. ctime: time.Now(),
  50. db: OpenDB(config.Server.Database),
  51. idle: make(chan *Client),
  52. motdFile: config.Server.MOTD,
  53. name: NewName(config.Server.Name),
  54. newConns: make(chan net.Conn),
  55. operators: config.Operators(),
  56. signals: make(chan os.Signal, len(SERVER_SIGNALS)),
  57. whoWas: NewWhoWasList(100),
  58. theaters: config.Theaters(),
  59. }
  60. if config.Server.Password != "" {
  61. server.password = config.Server.PasswordBytes()
  62. }
  63. server.loadChannels()
  64. for _, addr := range config.Server.Listen {
  65. server.listen(addr)
  66. }
  67. if config.Server.Wslisten != "" {
  68. server.wslisten(config.Server.Wslisten)
  69. }
  70. signal.Notify(server.signals, SERVER_SIGNALS...)
  71. // add RPL_ISUPPORT tokens
  72. server.isupport = NewISupportList()
  73. server.isupport.Add("CASEMAPPING", "ascii")
  74. // server.isupport.Add("CHANMODES", "") //TODO(dan): Channel mode list here
  75. // server.isupport.Add("CHANNELLEN", "") //TODO(dan): Support channel length
  76. server.isupport.Add("CHANTYPES", "#")
  77. server.isupport.Add("EXCEPTS", "")
  78. server.isupport.Add("INVEX", "")
  79. // server.isupport.Add("KICKLEN", "") //TODO(dan): Support kick length?
  80. // server.isupport.Add("MAXLIST", "") //TODO(dan): Support max list length?
  81. // server.isupport.Add("MODES", "") //TODO(dan): Support max modes?
  82. server.isupport.Add("NETWORK", config.Network.Name)
  83. // server.isupport.Add("NICKLEN", "") //TODO(dan): Support nick length
  84. server.isupport.Add("PREFIX", "(ov)@+")
  85. // server.isupport.Add("STATUSMSG", "@+") //TODO(dan): Autogenerate based on PREFIXes, support STATUSMSG
  86. // server.isupport.Add("TARGMAX", "") //TODO(dan): Support this
  87. // server.isupport.Add("TOPICLEN", "") //TODO(dan): Support topic length
  88. server.isupport.RegenerateCachedReply()
  89. return server
  90. }
  91. func loadChannelList(channel *Channel, list string, maskMode ChannelMode) {
  92. if list == "" {
  93. return
  94. }
  95. channel.lists[maskMode].AddAll(NewNames(strings.Split(list, " ")))
  96. }
  97. func (server *Server) loadChannels() {
  98. rows, err := server.db.Query(`
  99. SELECT name, flags, key, topic, user_limit, ban_list, except_list,
  100. invite_list
  101. FROM channel`)
  102. if err != nil {
  103. log.Fatal("error loading channels: ", err)
  104. }
  105. for rows.Next() {
  106. var name, flags, key, topic string
  107. var userLimit uint64
  108. var banList, exceptList, inviteList string
  109. err = rows.Scan(&name, &flags, &key, &topic, &userLimit, &banList,
  110. &exceptList, &inviteList)
  111. if err != nil {
  112. log.Println("Server.loadChannels:", err)
  113. continue
  114. }
  115. channel := NewChannel(server, NewName(name))
  116. for _, flag := range flags {
  117. channel.flags[ChannelMode(flag)] = true
  118. }
  119. channel.key = NewText(key)
  120. channel.topic = NewText(topic)
  121. channel.userLimit = userLimit
  122. loadChannelList(channel, banList, BanMask)
  123. loadChannelList(channel, exceptList, ExceptMask)
  124. loadChannelList(channel, inviteList, InviteMask)
  125. }
  126. }
  127. func (server *Server) processCommand(cmd Command) {
  128. client := cmd.Client()
  129. if !client.registered {
  130. regCmd, ok := cmd.(RegServerCommand)
  131. if !ok {
  132. client.Quit("unexpected command")
  133. return
  134. }
  135. regCmd.HandleRegServer(server)
  136. return
  137. }
  138. srvCmd, ok := cmd.(ServerCommand)
  139. if !ok {
  140. client.ErrUnknownCommand(cmd.Code())
  141. return
  142. }
  143. switch srvCmd.(type) {
  144. case *PingCommand, *PongCommand:
  145. client.Touch()
  146. case *QuitCommand:
  147. // no-op
  148. default:
  149. client.Active()
  150. client.Touch()
  151. }
  152. srvCmd.HandleServer(server)
  153. }
  154. func (server *Server) Shutdown() {
  155. server.db.Close()
  156. for _, client := range server.clients.byNick {
  157. client.Reply(RplNotice(server, client, "shutting down"))
  158. }
  159. }
  160. func (server *Server) Run() {
  161. done := false
  162. for !done {
  163. select {
  164. case <-server.signals:
  165. server.Shutdown()
  166. done = true
  167. case conn := <-server.newConns:
  168. NewClient(server, conn)
  169. case cmd := <-server.commands:
  170. server.processCommand(cmd)
  171. case client := <-server.idle:
  172. client.Idle()
  173. }
  174. }
  175. }
  176. //
  177. // listen goroutine
  178. //
  179. func (s *Server) listen(addr string) {
  180. listener, err := net.Listen("tcp", addr)
  181. if err != nil {
  182. log.Fatal(s, "listen error: ", err)
  183. }
  184. Log.info.Printf("%s listening on %s", s, addr)
  185. go func() {
  186. for {
  187. conn, err := listener.Accept()
  188. if err != nil {
  189. Log.error.Printf("%s accept error: %s", s, err)
  190. continue
  191. }
  192. Log.debug.Printf("%s accept: %s", s, conn.RemoteAddr())
  193. s.newConns <- conn
  194. }
  195. }()
  196. }
  197. //
  198. // websocket listen goroutine
  199. //
  200. func (s *Server) wslisten(addr string) {
  201. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  202. if r.Method != "GET" {
  203. Log.error.Printf("%s method not allowed", s)
  204. return
  205. }
  206. // We don't have any subprotocols, so if someone attempts to `new
  207. // WebSocket(server, "subprotocol")` they'll break here, instead of
  208. // getting the default, ambiguous, response from gorilla.
  209. if v, ok := r.Header["Sec-Websocket-Protocol"]; ok {
  210. http.Error(w, fmt.Sprintf("WebSocket subprocotols (e.g. %s) not supported", v), 400)
  211. }
  212. ws, err := upgrader.Upgrade(w, r, nil)
  213. if err != nil {
  214. Log.error.Printf("%s websocket upgrade error: %s", s, err)
  215. return
  216. }
  217. s.newConns <- WSContainer{ws}
  218. })
  219. go func() {
  220. Log.info.Printf("%s listening on %s", s, addr)
  221. err := http.ListenAndServe(addr, nil)
  222. if err != nil {
  223. Log.error.Printf("%s listenAndServe error: %s", s, err)
  224. }
  225. }()
  226. }
  227. //
  228. // server functionality
  229. //
  230. func (s *Server) tryRegister(c *Client) {
  231. if c.registered || !c.HasNick() || !c.HasUsername() ||
  232. (c.capState == CapNegotiating) {
  233. return
  234. }
  235. c.Register()
  236. c.RplWelcome()
  237. c.RplYourHost()
  238. c.RplCreated()
  239. c.RplMyInfo()
  240. c.RplISupport()
  241. s.MOTD(c)
  242. }
  243. func (server *Server) MOTD(client *Client) {
  244. if server.motdFile == "" {
  245. client.ErrNoMOTD()
  246. return
  247. }
  248. file, err := os.Open(server.motdFile)
  249. if err != nil {
  250. client.ErrNoMOTD()
  251. return
  252. }
  253. defer file.Close()
  254. client.RplMOTDStart()
  255. reader := bufio.NewReader(file)
  256. for {
  257. line, err := reader.ReadString('\n')
  258. if err != nil {
  259. break
  260. }
  261. line = strings.TrimRight(line, "\r\n")
  262. client.RplMOTD(line)
  263. }
  264. client.RplMOTDEnd()
  265. }
  266. func (s *Server) Id() Name {
  267. return s.name
  268. }
  269. func (s *Server) String() string {
  270. return s.name.String()
  271. }
  272. func (s *Server) Nick() Name {
  273. return s.Id()
  274. }
  275. func (server *Server) Reply(target *Client, message string) {
  276. target.Reply(RplPrivMsg(server, target, NewText(message)))
  277. }
  278. func (server *Server) Replyf(target *Client, format string, args ...interface{}) {
  279. server.Reply(target, fmt.Sprintf(format, args...))
  280. }
  281. //
  282. // registration commands
  283. //
  284. func (msg *PassCommand) HandleRegServer(server *Server) {
  285. client := msg.Client()
  286. if msg.err != nil {
  287. client.ErrPasswdMismatch()
  288. client.Quit("bad password")
  289. return
  290. }
  291. client.authorized = true
  292. }
  293. func (msg *ProxyCommand) HandleRegServer(server *Server) {
  294. msg.Client().hostname = msg.hostname
  295. }
  296. func (msg *RFC1459UserCommand) HandleRegServer(server *Server) {
  297. client := msg.Client()
  298. if !client.authorized {
  299. client.ErrPasswdMismatch()
  300. client.Quit("bad password")
  301. return
  302. }
  303. msg.setUserInfo(server)
  304. }
  305. func (msg *RFC2812UserCommand) HandleRegServer(server *Server) {
  306. client := msg.Client()
  307. if !client.authorized {
  308. client.ErrPasswdMismatch()
  309. client.Quit("bad password")
  310. return
  311. }
  312. flags := msg.Flags()
  313. if len(flags) > 0 {
  314. for _, mode := range flags {
  315. client.flags[mode] = true
  316. }
  317. client.RplUModeIs(client)
  318. }
  319. msg.setUserInfo(server)
  320. }
  321. func (msg *UserCommand) setUserInfo(server *Server) {
  322. client := msg.Client()
  323. if client.capState == CapNegotiating {
  324. client.capState = CapNegotiated
  325. }
  326. server.clients.Remove(client)
  327. client.username, client.realname = msg.username, msg.realname
  328. server.clients.Add(client)
  329. server.tryRegister(client)
  330. }
  331. func (msg *QuitCommand) HandleRegServer(server *Server) {
  332. msg.Client().Quit(msg.message)
  333. }
  334. //
  335. // normal commands
  336. //
  337. func (m *PassCommand) HandleServer(s *Server) {
  338. m.Client().ErrAlreadyRegistered()
  339. }
  340. func (m *PingCommand) HandleServer(s *Server) {
  341. client := m.Client()
  342. client.Reply(RplPong(client, m.server.Text()))
  343. }
  344. func (m *PongCommand) HandleServer(s *Server) {
  345. // no-op
  346. }
  347. func (m *UserCommand) HandleServer(s *Server) {
  348. m.Client().ErrAlreadyRegistered()
  349. }
  350. func (msg *QuitCommand) HandleServer(server *Server) {
  351. msg.Client().Quit(msg.message)
  352. }
  353. func (m *JoinCommand) HandleServer(s *Server) {
  354. client := m.Client()
  355. if m.zero {
  356. for channel := range client.channels {
  357. channel.Part(client, client.Nick().Text())
  358. }
  359. return
  360. }
  361. for name, key := range m.channels {
  362. if !name.IsChannel() {
  363. client.ErrNoSuchChannel(name)
  364. continue
  365. }
  366. channel := s.channels.Get(name)
  367. if channel == nil {
  368. channel = NewChannel(s, name)
  369. }
  370. channel.Join(client, key)
  371. }
  372. }
  373. func (m *PartCommand) HandleServer(server *Server) {
  374. client := m.Client()
  375. for _, chname := range m.channels {
  376. channel := server.channels.Get(chname)
  377. if channel == nil {
  378. m.Client().ErrNoSuchChannel(chname)
  379. continue
  380. }
  381. channel.Part(client, m.Message())
  382. }
  383. }
  384. func (msg *TopicCommand) HandleServer(server *Server) {
  385. client := msg.Client()
  386. channel := server.channels.Get(msg.channel)
  387. if channel == nil {
  388. client.ErrNoSuchChannel(msg.channel)
  389. return
  390. }
  391. if msg.setTopic {
  392. channel.SetTopic(client, msg.topic)
  393. } else {
  394. channel.GetTopic(client)
  395. }
  396. }
  397. func (msg *PrivMsgCommand) HandleServer(server *Server) {
  398. client := msg.Client()
  399. if msg.target.IsChannel() {
  400. channel := server.channels.Get(msg.target)
  401. if channel == nil {
  402. client.ErrNoSuchChannel(msg.target)
  403. return
  404. }
  405. channel.PrivMsg(client, msg.message)
  406. return
  407. }
  408. target := server.clients.Get(msg.target)
  409. if target == nil {
  410. client.ErrNoSuchNick(msg.target)
  411. return
  412. }
  413. target.Reply(RplPrivMsg(client, target, msg.message))
  414. if target.flags[Away] {
  415. client.RplAway(target)
  416. }
  417. }
  418. func (client *Client) WhoisChannelsNames() []string {
  419. chstrs := make([]string, len(client.channels))
  420. index := 0
  421. for channel := range client.channels {
  422. switch {
  423. case channel.members[client][ChannelOperator]:
  424. chstrs[index] = "@" + channel.name.String()
  425. case channel.members[client][Voice]:
  426. chstrs[index] = "+" + channel.name.String()
  427. default:
  428. chstrs[index] = channel.name.String()
  429. }
  430. index += 1
  431. }
  432. return chstrs
  433. }
  434. func (m *WhoisCommand) HandleServer(server *Server) {
  435. client := m.Client()
  436. // TODO implement target query
  437. for _, mask := range m.masks {
  438. matches := server.clients.FindAll(mask)
  439. if len(matches) == 0 {
  440. client.ErrNoSuchNick(mask)
  441. continue
  442. }
  443. for mclient := range matches {
  444. client.RplWhois(mclient)
  445. }
  446. }
  447. }
  448. func whoChannel(client *Client, channel *Channel, friends ClientSet) {
  449. for member := range channel.members {
  450. if !client.flags[Invisible] || friends[client] {
  451. client.RplWhoReply(channel, member)
  452. }
  453. }
  454. }
  455. func (msg *WhoCommand) HandleServer(server *Server) {
  456. client := msg.Client()
  457. friends := client.Friends()
  458. mask := msg.mask
  459. if mask == "" {
  460. for _, channel := range server.channels {
  461. whoChannel(client, channel, friends)
  462. }
  463. } else if mask.IsChannel() {
  464. // TODO implement wildcard matching
  465. channel := server.channels.Get(mask)
  466. if channel != nil {
  467. whoChannel(client, channel, friends)
  468. }
  469. } else {
  470. for mclient := range server.clients.FindAll(mask) {
  471. client.RplWhoReply(nil, mclient)
  472. }
  473. }
  474. client.RplEndOfWho(mask)
  475. }
  476. func (msg *OperCommand) HandleServer(server *Server) {
  477. client := msg.Client()
  478. if (msg.hash == nil) || (msg.err != nil) {
  479. client.ErrPasswdMismatch()
  480. return
  481. }
  482. client.flags[Operator] = true
  483. client.RplYoureOper()
  484. client.Reply(RplModeChanges(client, client, ModeChanges{&ModeChange{
  485. mode: Operator,
  486. op: Add,
  487. }}))
  488. }
  489. func (msg *AwayCommand) HandleServer(server *Server) {
  490. client := msg.Client()
  491. if len(msg.text) > 0 {
  492. client.flags[Away] = true
  493. } else {
  494. delete(client.flags, Away)
  495. }
  496. client.awayMessage = msg.text
  497. var op ModeOp
  498. if client.flags[Away] {
  499. op = Add
  500. client.RplNowAway()
  501. } else {
  502. op = Remove
  503. client.RplUnAway()
  504. }
  505. client.Reply(RplModeChanges(client, client, ModeChanges{&ModeChange{
  506. mode: Away,
  507. op: op,
  508. }}))
  509. }
  510. func (msg *IsOnCommand) HandleServer(server *Server) {
  511. client := msg.Client()
  512. ison := make([]string, 0)
  513. for _, nick := range msg.nicks {
  514. if iclient := server.clients.Get(nick); iclient != nil {
  515. ison = append(ison, iclient.Nick().String())
  516. }
  517. }
  518. client.RplIsOn(ison)
  519. }
  520. func (msg *MOTDCommand) HandleServer(server *Server) {
  521. server.MOTD(msg.Client())
  522. }
  523. func (msg *NoticeCommand) HandleServer(server *Server) {
  524. client := msg.Client()
  525. if msg.target.IsChannel() {
  526. channel := server.channels.Get(msg.target)
  527. if channel == nil {
  528. client.ErrNoSuchChannel(msg.target)
  529. return
  530. }
  531. channel.Notice(client, msg.message)
  532. return
  533. }
  534. target := server.clients.Get(msg.target)
  535. if target == nil {
  536. client.ErrNoSuchNick(msg.target)
  537. return
  538. }
  539. target.Reply(RplNotice(client, target, msg.message))
  540. }
  541. func (msg *KickCommand) HandleServer(server *Server) {
  542. client := msg.Client()
  543. for chname, nickname := range msg.kicks {
  544. channel := server.channels.Get(chname)
  545. if channel == nil {
  546. client.ErrNoSuchChannel(chname)
  547. continue
  548. }
  549. target := server.clients.Get(nickname)
  550. if target == nil {
  551. client.ErrNoSuchNick(nickname)
  552. continue
  553. }
  554. channel.Kick(client, target, msg.Comment())
  555. }
  556. }
  557. func (msg *ListCommand) HandleServer(server *Server) {
  558. client := msg.Client()
  559. // TODO target server
  560. if msg.target != "" {
  561. client.ErrNoSuchServer(msg.target)
  562. return
  563. }
  564. if len(msg.channels) == 0 {
  565. for _, channel := range server.channels {
  566. if !client.flags[Operator] && channel.flags[Private] {
  567. continue
  568. }
  569. client.RplList(channel)
  570. }
  571. } else {
  572. for _, chname := range msg.channels {
  573. channel := server.channels.Get(chname)
  574. if channel == nil || (!client.flags[Operator] && channel.flags[Private]) {
  575. client.ErrNoSuchChannel(chname)
  576. continue
  577. }
  578. client.RplList(channel)
  579. }
  580. }
  581. client.RplListEnd(server)
  582. }
  583. func (msg *NamesCommand) HandleServer(server *Server) {
  584. client := msg.Client()
  585. if len(server.channels) == 0 {
  586. for _, channel := range server.channels {
  587. channel.Names(client)
  588. }
  589. return
  590. }
  591. for _, chname := range msg.channels {
  592. channel := server.channels.Get(chname)
  593. if channel == nil {
  594. client.ErrNoSuchChannel(chname)
  595. continue
  596. }
  597. channel.Names(client)
  598. }
  599. }
  600. func (msg *VersionCommand) HandleServer(server *Server) {
  601. client := msg.Client()
  602. if (msg.target != "") && (msg.target != server.name) {
  603. client.ErrNoSuchServer(msg.target)
  604. return
  605. }
  606. client.RplVersion()
  607. }
  608. func (msg *InviteCommand) HandleServer(server *Server) {
  609. client := msg.Client()
  610. target := server.clients.Get(msg.nickname)
  611. if target == nil {
  612. client.ErrNoSuchNick(msg.nickname)
  613. return
  614. }
  615. channel := server.channels.Get(msg.channel)
  616. if channel == nil {
  617. client.RplInviting(target, msg.channel)
  618. target.Reply(RplInviteMsg(client, target, msg.channel))
  619. return
  620. }
  621. channel.Invite(target, client)
  622. }
  623. func (msg *TimeCommand) HandleServer(server *Server) {
  624. client := msg.Client()
  625. if (msg.target != "") && (msg.target != server.name) {
  626. client.ErrNoSuchServer(msg.target)
  627. return
  628. }
  629. client.RplTime()
  630. }
  631. func (msg *KillCommand) HandleServer(server *Server) {
  632. client := msg.Client()
  633. if !client.flags[Operator] {
  634. client.ErrNoPrivileges()
  635. return
  636. }
  637. target := server.clients.Get(msg.nickname)
  638. if target == nil {
  639. client.ErrNoSuchNick(msg.nickname)
  640. return
  641. }
  642. quitMsg := fmt.Sprintf("KILLed by %s: %s", client.Nick(), msg.comment)
  643. target.Quit(NewText(quitMsg))
  644. }
  645. func (msg *WhoWasCommand) HandleServer(server *Server) {
  646. client := msg.Client()
  647. for _, nickname := range msg.nicknames {
  648. results := server.whoWas.Find(nickname, msg.count)
  649. if len(results) == 0 {
  650. client.ErrWasNoSuchNick(nickname)
  651. } else {
  652. for _, whoWas := range results {
  653. client.RplWhoWasUser(whoWas)
  654. }
  655. }
  656. client.RplEndOfWhoWas(nickname)
  657. }
  658. }