Testing ground for GUI
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.

1527 lines
37KB

  1. //
  2. // Copyright (c) 2014 - 2018, Přemysl Janouch <p@janouch.name>
  3. //
  4. // Permission to use, copy, modify, and/or distribute this software for any
  5. // purpose with or without fee is hereby granted.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  10. // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  12. // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  13. // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. //
  15. // hid is a straight-forward port of kike IRCd from C.
  16. package main
  17. /*
  18. // ANSI terminal formatting, would be better if we had isatty() available
  19. func tf(text string, ansi string) string {
  20. return "\x1b[0;" + ansi + "m" + text + "\x1b[0m"
  21. }
  22. func logErrorf(format string, args ...interface{}) {
  23. fmt.Fprintf(os.Stderr, tf("error: "+format+"\n", "1;31"), args...)
  24. }
  25. func logFatalf(format string, args ...interface{}) {
  26. fmt.Fprintf(os.Stderr, tf("fatal: "+format+"\n", "1;31"), args...)
  27. os.Exit(1)
  28. }
  29. func logFatal(object interface{}) {
  30. logFatalf("%s", object)
  31. }
  32. func getHome() (home string) {
  33. if u, _ := user.Current(); u != nil {
  34. home = u.HomeDir
  35. } else {
  36. home = os.Getenv("HOME")
  37. }
  38. return
  39. }
  40. // Only handling the simple case as that's what one mostly wants.
  41. // TODO(p): Handle the generic case as well.
  42. func expandTilde(path string) string {
  43. if strings.HasPrefix(path, "~/") {
  44. return getHome() + path[1:]
  45. }
  46. return path
  47. }
  48. func getXdgHomeDir(name, def string) string {
  49. env := os.Getenv(name)
  50. if env != "" && env[0] == '/' {
  51. return env
  52. }
  53. return filepath.Join(getHome(), def)
  54. }
  55. // Retrieve all XDG base directories for configuration files
  56. func getXdgConfigDirs() (result []string) {
  57. home := getXdgHomeDir("XDG_CONFIG_HOME", ".config")
  58. if home != "" {
  59. result = append(result, home)
  60. }
  61. dirs := os.Getenv("XDG_CONFIG_DIRS")
  62. if dirs == "" {
  63. dirs = "/etc/xdg"
  64. }
  65. for _, path := range strings.Split(dirs, ":") {
  66. if path != "" {
  67. result = append(result, path)
  68. }
  69. }
  70. return
  71. }
  72. // Read a configuration file with the given basename w/o extension
  73. func readConfigFile(name string, output interface{}) error {
  74. var suffix = filepath.Join(projectName, name+".json")
  75. for _, path := range getXdgConfigDirs() {
  76. full := filepath.Join(path, suffix)
  77. file, err := os.Open(full)
  78. if err != nil {
  79. if !os.IsNotExist(err) {
  80. return err
  81. }
  82. continue
  83. }
  84. defer file.Close()
  85. decoder := json.NewDecoder(file)
  86. err = decoder.Decode(output)
  87. if err != nil {
  88. return fmt.Errorf("%s: %s", full, err)
  89. }
  90. return nil
  91. }
  92. return errors.New("configuration file not found")
  93. }
  94. */
  95. import (
  96. "bufio"
  97. "crypto/sha256"
  98. "crypto/tls"
  99. "encoding/hex"
  100. "flag"
  101. "fmt"
  102. "io"
  103. "log"
  104. "net"
  105. "os"
  106. "os/signal"
  107. "path/filepath"
  108. "regexp"
  109. "strconv"
  110. "strings"
  111. "syscall"
  112. "time"
  113. )
  114. var debugMode = false
  115. // --- Utilities ---------------------------------------------------------------
  116. //
  117. // Trivial SSL/TLS autodetection. The first block of data returned by Recvfrom
  118. // must be at least three octets long for this to work reliably, but that should
  119. // not pose a problem in practice. We might try waiting for them.
  120. //
  121. // SSL2: 1xxx xxxx | xxxx xxxx | <1>
  122. // (message length) (client hello)
  123. // SSL3/TLS: <22> | <3> | xxxx xxxx
  124. // (handshake)| (protocol version)
  125. //
  126. func detectTLS(sysconn syscall.RawConn) (isTLS bool) {
  127. sysconn.Read(func(fd uintptr) (done bool) {
  128. var buf [3]byte
  129. n, _, err := syscall.Recvfrom(int(fd), buf[:], syscall.MSG_PEEK)
  130. switch {
  131. case n == 3:
  132. isTLS = buf[0]&0x80 != 0 && buf[2] == 1
  133. fallthrough
  134. case n == 2:
  135. isTLS = buf[0] == 22 && buf[1] == 3
  136. case n == 1:
  137. isTLS = buf[0] == 22
  138. case err == syscall.EAGAIN:
  139. return false
  140. }
  141. return true
  142. })
  143. return isTLS
  144. }
  145. // --- Configuration -----------------------------------------------------------
  146. // XXX: Do we really want to support default nil values?
  147. var config = []struct {
  148. key string // INI key
  149. def []rune // default value, may be nil
  150. description string // documentation
  151. }{
  152. // XXX: I'm not sure if Go will cooperate here.
  153. {"pid_file", nil, "Path or name of the PID file"},
  154. {"bind", []rune(":6667"), "Address of the IRC server"},
  155. }
  156. // --- Rate limiter ------------------------------------------------------------
  157. type floodDetector struct {
  158. interval uint // interval for the limit
  159. limit uint // maximum number of events allowed
  160. timestamps []int64 // timestamps of last events
  161. pos uint // index of the oldest event
  162. }
  163. func newFloodDetector(interval, limit uint) *floodDetector {
  164. return &floodDetector{
  165. interval: interval,
  166. limit: limit,
  167. timestamps: make([]int64, limit+1),
  168. pos: 0,
  169. }
  170. }
  171. func (fd *floodDetector) check() bool {
  172. now := time.Now().Unix()
  173. fd.timestamps[fd.pos] = now
  174. fd.pos++
  175. if fd.pos > fd.limit {
  176. fd.pos = 0
  177. }
  178. var count uint
  179. begin := now - int64(fd.interval)
  180. for _, ts := range fd.timestamps {
  181. if ts >= begin {
  182. count++
  183. }
  184. }
  185. return count <= fd.limit
  186. }
  187. // --- IRC protocol ------------------------------------------------------------
  188. //go:generate sh -c "./hid-gen-replies.sh > hid-replies.go < hid-replies"
  189. func ircToLower(c byte) byte {
  190. switch c {
  191. case '[':
  192. return '{'
  193. case ']':
  194. return '}'
  195. case '\\':
  196. return '|'
  197. case '~':
  198. return '^'
  199. }
  200. if c >= 'A' && c <= 'Z' {
  201. return c + ('a' - 'A')
  202. }
  203. return c
  204. }
  205. // TODO: To support ALL CAPS initialization of maps, perhaps we should use
  206. // ircToUpper instead.
  207. // FIXME: This doesn't follow the meaning of strxfrm and perhaps should be
  208. // renamed to ircNormalize.
  209. func ircStrxfrm(ident string) string {
  210. var canon []byte
  211. for _, c := range []byte(ident) {
  212. canon = append(canon, ircToLower(c))
  213. }
  214. return string(canon)
  215. }
  216. func ircFnmatch(pattern string, s string) bool {
  217. pattern, s = ircStrxfrm(pattern), ircStrxfrm(s)
  218. // FIXME: This should not support [] ranges and handle / specially.
  219. // We could translate the pattern to a regular expression.
  220. matched, _ := filepath.Match(pattern, s)
  221. return matched
  222. }
  223. // TODO: We will need to add support for IRCv3 tags.
  224. var reMsg = regexp.MustCompile(
  225. `^(?::([^! ]*)(?:!([^@]*)@([^ ]*))? +)?([^ ]+)(.*)?$`)
  226. var reArgs = regexp.MustCompile(`:.*| [^: ][^ ]*`)
  227. type message struct {
  228. nick string // optional nickname
  229. user string // optional username
  230. host string // optional hostname or IP address
  231. command string // command name
  232. params []string // arguments
  233. }
  234. // Everything as per RFC 2812
  235. const (
  236. ircMaxNickname = 9
  237. ircMaxHostname = 63
  238. ircMaxChannelName = 50
  239. ircMaxMessageLength = 510
  240. )
  241. // TODO: Port the IRC token validation part as needed.
  242. const reClassSpecial = "\\[\\]\\\\`_^{|}"
  243. var (
  244. // Extending ASCII to the whole range of Unicode letters.
  245. reNickname = regexp.MustCompile(
  246. `^[\pL` + reClassSpecial + `][\pL` + reClassSpecial + `0-9-]*$`)
  247. // Notably, this won't match invalid UTF-8 characters, although the
  248. // behaviour seems to be unstated in the documentation.
  249. reUsername = regexp.MustCompile(`^[^\0\r\n @]+$`)
  250. reChannelName = regexp.MustCompile(`^[^\0\7\r\n ,:]+$`)
  251. )
  252. func ircIsValidNickname(nickname string) bool {
  253. return len(nickname) <= ircMaxNickname && reNickname.MatchString(nickname)
  254. }
  255. func ircIsValidUsername(username string) bool {
  256. // XXX: We really should put a limit on this
  257. // despite the RFC not mentioning one.
  258. return reUsername.MatchString(username)
  259. }
  260. func ircIsValidChannelName(name string) bool {
  261. return len(name) <= ircMaxChannelName && reChannelName.MatchString(name)
  262. }
  263. // --- Clients (equals users) --------------------------------------------------
  264. type connCloseWrite interface {
  265. net.Conn
  266. CloseWrite() error
  267. }
  268. const ircSupportedUserModes = "aiwros"
  269. const (
  270. ircUserModeInvisible = 1 << iota
  271. ircUserModeRxWallops
  272. ircUserModeRestricted
  273. ircUserModeOperator
  274. ircUserModeRxServerNotices
  275. )
  276. const (
  277. ircCapMultiPrefix = 1 << iota
  278. ircCapInviteNotify
  279. ircCapEchoMessage
  280. ircCapUserhostInNames
  281. ircCapServerTime
  282. )
  283. type client struct {
  284. transport net.Conn // underlying connection
  285. tls *tls.Conn // TLS, if detected
  286. conn connCloseWrite // high-level connection
  287. inQ []byte // unprocessed input
  288. outQ []byte // unprocessed output
  289. reading bool // whether a reading goroutine is running
  290. writing bool // whether a writing goroutine is running
  291. closing bool // whether we're closing the connection
  292. killTimer *time.Timer // hard kill timeout
  293. opened int64 // when the connection was opened
  294. nSentMessages uint // number of sent messages total
  295. sentBytes int // number of sent bytes total
  296. nReceivedMessages uint // number of received messages total
  297. receivedBytes int // number of received bytes total
  298. hostname string // hostname or IP shown to the network
  299. port string // port of the peer as a string
  300. address string // full network address
  301. pingTimer *time.Timer // we should send a PING
  302. timeoutTimer *time.Timer // connection seems to be dead
  303. registered bool // the user has registered
  304. capNegotiating bool // negotiating capabilities
  305. capsEnabled uint // enabled capabilities
  306. capVersion uint // CAP protocol version
  307. tlsCertFingerprint string // client certificate fingerprint
  308. nickname string // IRC nickname (main identifier)
  309. username string // IRC username
  310. realname string // IRC realname (or e-mail)
  311. mode uint // user's mode
  312. awayMessage string // away message
  313. lastActive int64 // last PRIVMSG, to get idle time
  314. invites map[string]bool // channel invitations by operators
  315. antiflood floodDetector // flood detector
  316. }
  317. // --- Channels ----------------------------------------------------------------
  318. const ircSupportedChanModes = "ov" + "beI" + "imnqpst" + "kl"
  319. const (
  320. ircChanModeInviteOnly = 1 << iota
  321. ircChanModeModerated
  322. ircChanModeNoOutsideMsgs
  323. ircChanModeQuiet
  324. ircChanModePrivate
  325. ircChanModeSecret
  326. ircChanModeProtectedTopic
  327. ircChanModeOperator
  328. ircChanModeVoice
  329. )
  330. type channel struct {
  331. name string // channel name
  332. modes uint // channel modes
  333. key string // channel key
  334. userLimit int // user limit or -1
  335. created int64 // creation time
  336. topic string // channel topic
  337. topicWho string // who set the topic
  338. topicTime int64 // when the topic was set
  339. userModes map[*client]uint // modes for all channel users
  340. banList []string // ban list
  341. exceptionList []string // exceptions from bans
  342. inviteList []string // exceptions from +I
  343. }
  344. func newChannel() *channel {
  345. return &channel{userLimit: -1}
  346. }
  347. // TODO: Port struct channel methods.
  348. // --- IRC server context ------------------------------------------------------
  349. type whowasInfo struct {
  350. nickname, username, realname, hostname string
  351. }
  352. func newWhowasInfo(c *client) *whowasInfo {
  353. return &whowasInfo{
  354. nickname: c.nickname,
  355. username: c.username,
  356. realname: c.realname,
  357. hostname: c.hostname,
  358. }
  359. }
  360. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  361. type ircCommand struct {
  362. name string
  363. requiresRegistration bool
  364. handler func(*message, *client)
  365. nReceived uint // number of commands received
  366. bytesReceived uint // number of bytes received total
  367. }
  368. type preparedEvent struct {
  369. client *client
  370. host string // client's hostname or literal IP address
  371. isTLS bool // the client seems to use TLS
  372. }
  373. type readEvent struct {
  374. client *client
  375. data []byte // new data from the client
  376. err error // read error
  377. }
  378. type writeEvent struct {
  379. client *client
  380. written int // amount of bytes written
  381. err error // write error
  382. }
  383. // TODO: Port server_context. Maybe we want to keep it in a struct?
  384. // XXX: Beware that maps with identifier keys need to be indexed correctly.
  385. // We might want to enforce accessor functions for users and channels.
  386. var (
  387. started int64 // when has the server been started
  388. users map[string]*client // maps nicknames to clients
  389. channels map[string]*channel // maps channel names to data
  390. handlers map[string]bool // TODO message handlers
  391. capHandlers map[string]bool // TODO CAP message handlers
  392. whowas map[string]*whowasInfo // WHOWAS registry
  393. serverName string // our server name
  394. pingInterval uint // ping interval in seconds
  395. maxConnections int // max connections allowed or 0
  396. motd []string // MOTD (none if empty)
  397. operators map[string]bool // TLS certificate fingerprints for IRCops
  398. )
  399. var (
  400. sigs = make(chan os.Signal, 1)
  401. conns = make(chan net.Conn)
  402. prepared = make(chan preparedEvent)
  403. reads = make(chan readEvent)
  404. writes = make(chan writeEvent)
  405. timeouts = make(chan *client)
  406. tlsConf *tls.Config
  407. clients = make(map[*client]bool)
  408. listener net.Listener
  409. // TODO: quitting, quitTimer as they are named in kike?
  410. inShutdown bool
  411. shutdownTimer <-chan time.Time
  412. )
  413. // Forcefully tear down all connections.
  414. func forceShutdown(reason string) {
  415. if !inShutdown {
  416. log.Fatalln("forceShutdown called without initiateShutdown")
  417. }
  418. log.Printf("forced shutdown (%s)\n", reason)
  419. for c := range clients {
  420. c.destroy("TODO")
  421. }
  422. }
  423. // Initiate a clean shutdown of the whole daemon.
  424. func initiateShutdown() {
  425. log.Println("shutting down")
  426. if err := listener.Close(); err != nil {
  427. log.Println(err)
  428. }
  429. for c := range clients {
  430. c.closeLink("TODO")
  431. }
  432. shutdownTimer = time.After(5 * time.Second)
  433. inShutdown = true
  434. }
  435. // TODO: ircChannelCreate
  436. func ircChannelDestroyIfEmpty(ch *channel) {
  437. // TODO
  438. }
  439. // TODO: ircSendToRoommates
  440. // Broadcast to all /other/ clients (telnet-friendly, also in accordance to
  441. // the plan of extending this to an IRCd).
  442. func broadcast(line string, except *client) {
  443. for c := range clients {
  444. if c != except {
  445. c.send(line)
  446. }
  447. }
  448. }
  449. func ircSendToRoommates(c *client, message string) {
  450. // TODO
  451. }
  452. // --- Clients (continued) -----------------------------------------------------
  453. // TODO: Perhaps we should append to *[]byte for performance.
  454. func clientModeToString(m uint, mode *string) {
  455. if 0 != m&ircUserModeInvisible {
  456. *mode += "i"
  457. }
  458. if 0 != m&ircUserModeRxWallops {
  459. *mode += "w"
  460. }
  461. if 0 != m&ircUserModeRestricted {
  462. *mode += "r"
  463. }
  464. if 0 != m&ircUserModeOperator {
  465. *mode += "o"
  466. }
  467. if 0 != m&ircUserModeRxServerNotices {
  468. *mode += "s"
  469. }
  470. }
  471. func (c *client) getMode() string {
  472. mode := ""
  473. if c.awayMessage != "" {
  474. mode += "a"
  475. }
  476. clientModeToString(c.mode, &mode)
  477. return mode
  478. }
  479. func (c *client) send(line string) {
  480. if c.conn == nil || c.closing {
  481. return
  482. }
  483. // TODO: Rename inQ and outQ to recvQ and sendQ as they are usually named.
  484. oldOutQ := len(c.outQ)
  485. // So far there's only one message tag we use, so we can do it simple;
  486. // note that a 1024-character limit applies to messages with tags on.
  487. if 0 != c.capsEnabled&ircCapServerTime {
  488. c.outQ = time.Now().UTC().
  489. AppendFormat(c.outQ, "@time=2006-01-02T15:04:05.000Z ")
  490. }
  491. bytes := []byte(line)
  492. if len(bytes) > ircMaxMessageLength {
  493. bytes = bytes[:ircMaxMessageLength]
  494. }
  495. // TODO: Kill the connection above some "SendQ" threshold (careful!)
  496. c.outQ = append(c.outQ, bytes...)
  497. c.outQ = append(c.outQ, "\r\n"...)
  498. c.flushOutQ()
  499. // Technically we haven't sent it yet but that's a minor detail
  500. c.nSentMessages++
  501. c.sentBytes += len(c.outQ) - oldOutQ
  502. }
  503. func (c *client) sendf(format string, a ...interface{}) {
  504. c.send(fmt.Sprintf(format, a...))
  505. }
  506. func (c *client) addToWhowas() {
  507. // Only keeping one entry for each nickname.
  508. // TODO: Make sure this list doesn't get too long, for example by
  509. // putting them in a linked list ordered by time.
  510. whowas[ircStrxfrm(c.nickname)] = newWhowasInfo(c)
  511. }
  512. func (c *client) unregister(reason string) {
  513. if !c.registered {
  514. return
  515. }
  516. ircSendToRoommates(c, fmt.Sprintf(":%s!%s@%s QUIT :%s",
  517. c.nickname, c.username, c.hostname, reason))
  518. // The eventual QUIT message will take care of state at clients.
  519. for _, ch := range channels {
  520. delete(ch.userModes, c)
  521. ircChannelDestroyIfEmpty(ch)
  522. }
  523. c.addToWhowas()
  524. delete(users, ircStrxfrm(c.nickname))
  525. c.nickname = ""
  526. c.registered = false
  527. }
  528. // TODO: Rename to kill.
  529. // Close the connection and forget about the client.
  530. func (c *client) destroy(reason string) {
  531. if reason == "" {
  532. reason = "Client exited"
  533. }
  534. c.unregister(reason)
  535. // TODO: Log the address; seems like we always have c.address.
  536. log.Println("client destroyed")
  537. // Try to send a "close notify" alert if the TLS object is ready,
  538. // otherwise just tear down the transport.
  539. if c.conn != nil {
  540. _ = c.conn.Close()
  541. } else {
  542. _ = c.transport.Close()
  543. }
  544. // Clean up the goroutine, although a spurious event may still be sent.
  545. // TODO: Other timers if needed.
  546. if c.killTimer != nil {
  547. c.killTimer.Stop()
  548. }
  549. delete(clients, c)
  550. }
  551. // Tear down the client connection, trying to do so in a graceful manner.
  552. func (c *client) closeLink(reason string) {
  553. // Let's just cut the connection, the client can try again later.
  554. // We also want to avoid accidentally writing to the socket before
  555. // address resolution has finished.
  556. if c.conn == nil {
  557. c.destroy(reason)
  558. return
  559. }
  560. if c.closing {
  561. return
  562. }
  563. nickname := c.nickname
  564. if nickname == "" {
  565. nickname = "*"
  566. }
  567. // We push an "ERROR" message to the write buffer and let the writer send
  568. // it, with some arbitrary timeout. The "closing" state makes sure
  569. // that a/ we ignore any successive messages, and b/ that the connection
  570. // is killed after the write buffer is transferred and emptied.
  571. // (Since we send this message, we don't need to call CloseWrite here.)
  572. c.sendf("ERROR :Closing link: %s[%s] (%s)",
  573. nickname, c.hostname /* TODO host IP? */, reason)
  574. c.closing = true
  575. c.unregister(reason)
  576. c.killTimer = time.AfterFunc(3*time.Second, func() {
  577. timeouts <- c
  578. })
  579. }
  580. func (c *client) inMaskList(masks []string) bool {
  581. client := fmt.Sprintf("%s!%s@%s", c.nickname, c.username, c.hostname)
  582. for _, mask := range masks {
  583. if ircFnmatch(mask, client) {
  584. return true
  585. }
  586. }
  587. return false
  588. }
  589. func (c *client) getTLSCertFingerprint() string {
  590. if c.tls == nil {
  591. return ""
  592. }
  593. peerCerts := c.tls.ConnectionState().PeerCertificates
  594. if len(peerCerts) == 0 {
  595. return ""
  596. }
  597. hash := sha256.Sum256(peerCerts[0].Raw)
  598. return hex.EncodeToString(hash[:])
  599. }
  600. // --- Timers ------------------------------------------------------------------
  601. // TODO
  602. // --- IRC command handling ----------------------------------------------------
  603. // XXX: ap doesn't really need to be a slice.
  604. func (c *client) makeReply(id int, ap []interface{}) string {
  605. nickname := c.nickname
  606. if nickname == "" {
  607. nickname = "*"
  608. }
  609. s := fmt.Sprintf(":%s %03d %s ", serverName, id, nickname)
  610. a := fmt.Sprintf(defaultReplies[id], ap...)
  611. return s + a
  612. }
  613. // XXX: This way we cannot typecheck the arguments, so we must be careful.
  614. func (c *client) sendReply(id int, args ...interface{}) {
  615. c.send(c.makeReply(id, args))
  616. }
  617. /// Send a space-separated list of words across as many replies as needed.
  618. func (c *client) sendReplyVector(id int, items []string, args ...interface{}) {
  619. common := c.makeReply(id, args)
  620. // We always send at least one message (there might be a client that
  621. // expects us to send this message at least once).
  622. for len(items) > 0 {
  623. // If not even a single item fits in the limit (which may happen,
  624. // in theory) it just gets cropped. We could also skip it.
  625. reply := append([]byte(common), items[0]...)
  626. // Append as many items as fits in a single message.
  627. for len(items) > 0 &&
  628. len(reply)+1+len(items[0]) <= ircMaxMessageLength {
  629. reply = append(reply, ' ')
  630. reply = append(reply, items[0]...)
  631. items = items[1:]
  632. }
  633. c.send(string(reply))
  634. }
  635. }
  636. func (c *client) sendMOTD() {
  637. if len(motd) == 0 {
  638. c.sendReply(ERR_NOMOTD)
  639. return
  640. }
  641. c.sendReply(RPL_MOTDSTART, serverName)
  642. for _, line := range motd {
  643. c.sendReply(RPL_MOTD, line)
  644. }
  645. c.sendReply(RPL_ENDOFMOTD)
  646. }
  647. func (c *client) sendLUSERS() {
  648. nUsers, nServices, nOpers, nUnknown := 0, 0, 0, 0
  649. for c := range clients {
  650. if c.registered {
  651. nUsers++
  652. } else {
  653. nUnknown++
  654. }
  655. if 0 != c.mode&ircUserModeOperator {
  656. nOpers++
  657. }
  658. }
  659. nChannels := 0
  660. for _, ch := range channels {
  661. if 0 != ch.modes&ircChanModeSecret {
  662. nChannels++
  663. }
  664. }
  665. c.sendReply(RPL_LUSERCLIENT, nUsers, nServices, 1 /* servers total */)
  666. if nOpers != 0 {
  667. c.sendReply(RPL_LUSEROP, nOpers)
  668. }
  669. if nUnknown != 0 {
  670. c.sendReply(RPL_LUSERUNKNOWN, nUnknown)
  671. }
  672. if nChannels != 0 {
  673. c.sendReply(RPL_LUSERCHANNELS, nChannels)
  674. }
  675. c.sendReply(RPL_LUSERME, nUsers+nServices+nUnknown, 0 /* peer servers */)
  676. }
  677. func isThisMe(target string) bool {
  678. // Target servers can also be matched by their users
  679. if ircFnmatch(target, serverName) {
  680. return true
  681. }
  682. _, ok := users[ircStrxfrm(target)]
  683. return ok
  684. }
  685. func (c *client) sendISUPPORT() {
  686. // Only # channels, +e supported, +I supported, unlimited arguments to MODE
  687. c.sendReply(RPL_ISUPPORT, "CHANTYPES=# EXCEPTS INVEX MODES"+
  688. " TARGMAX=WHOIS:,LIST:,NAMES:,PRIVMSG:1,NOTICE:1,KICK:"+
  689. " NICKLEN=%d CHANNELLEN=%d", ircMaxNickname, ircMaxChannelName)
  690. }
  691. func (c *client) tryFinishRegistration() {
  692. // TODO: Check if the realname is really required.
  693. if c.nickname == "" || c.username == "" || c.realname == "" {
  694. return
  695. }
  696. if c.registered || c.capNegotiating {
  697. return
  698. }
  699. c.registered = true
  700. c.sendReply(RPL_WELCOME, c.nickname, c.username, c.hostname)
  701. c.sendReply(RPL_YOURHOST, serverName, "TODO version")
  702. // The purpose of this message eludes me.
  703. c.sendReply(RPL_CREATED, time.Unix(started, 0).Format("Mon, 02 Jan 2006"))
  704. c.sendReply(RPL_MYINFO, serverName, "TODO version",
  705. ircSupportedUserModes, ircSupportedChanModes)
  706. c.sendISUPPORT()
  707. c.sendLUSERS()
  708. c.sendMOTD()
  709. if mode := c.getMode(); mode != "" {
  710. c.sendf(":%s MODE %s :+%s", c.nickname, c.nickname, mode)
  711. }
  712. c.tlsCertFingerprint = c.getTLSCertFingerprint()
  713. if c.tlsCertFingerprint != "" {
  714. c.sendf(":%s NOTICE %s :Your TLS client certificate fingerprint is %s",
  715. serverName, c.nickname, c.tlsCertFingerprint)
  716. }
  717. delete(whowas, ircStrxfrm(c.nickname))
  718. }
  719. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  720. // IRCv3 capability negotiation. See http://ircv3.org for details.
  721. type ircCapArgs struct {
  722. subcommand string // the subcommand being processed
  723. fullParams string // whole parameter string
  724. params []string // split parameters
  725. target string // target parameter for replies
  726. }
  727. var ircCapTable = []struct {
  728. flag uint // flag
  729. name string // name of the capability
  730. }{
  731. {ircCapMultiPrefix, "multi-prefix"},
  732. {ircCapInviteNotify, "invite-notify"},
  733. {ircCapEchoMessage, "echo-message"},
  734. {ircCapUserhostInNames, "userhost-in-names"},
  735. {ircCapServerTime, "server-time"},
  736. }
  737. func (c *client) handleCAPLS(a *ircCapArgs) {
  738. if len(a.params) == 1 {
  739. if ver, err := strconv.ParseUint(a.params[0], 10, 32); err != nil {
  740. c.sendReply(ERR_INVALIDCAPCMD, a.subcommand,
  741. "Ignoring invalid protocol version number")
  742. } else {
  743. c.capVersion = uint(ver)
  744. }
  745. }
  746. c.capNegotiating = true
  747. c.sendf(":%s CAP %s LS :multi-prefix invite-notify echo-message"+
  748. " userhost-in-names server-time", serverName, a.target)
  749. }
  750. func (c *client) handleCAPLIST(a *ircCapArgs) {
  751. caps := []string{}
  752. for _, cap := range ircCapTable {
  753. if 0 != c.capsEnabled&cap.flag {
  754. caps = append(caps, cap.name)
  755. }
  756. }
  757. c.sendf(":%s CAP %s LIST :%s", serverName, a.target,
  758. strings.Join(caps, " "))
  759. }
  760. func ircDecodeCapability(name string) uint {
  761. for _, cap := range ircCapTable {
  762. if cap.name == name {
  763. return cap.flag
  764. }
  765. }
  766. return 0
  767. }
  768. func (c *client) handleCAPREQ(a *ircCapArgs) {
  769. c.capNegotiating = true
  770. newCaps := c.capsEnabled
  771. ok := true
  772. for _, param := range a.params {
  773. removing := false
  774. name := param
  775. if name[:1] == "-" {
  776. removing = true
  777. name = name[1:]
  778. }
  779. if cap := ircDecodeCapability(name); cap == 0 {
  780. ok = false
  781. } else if removing {
  782. newCaps &= ^cap
  783. } else {
  784. newCaps |= cap
  785. }
  786. }
  787. if ok {
  788. c.capsEnabled = newCaps
  789. c.sendf(":%s CAP %s ACK :%s", serverName, a.target, a.fullParams)
  790. } else {
  791. c.sendf(":%s CAP %s NAK :%s", serverName, a.target, a.fullParams)
  792. }
  793. }
  794. func (c *client) handleCAPACK(a *ircCapArgs) {
  795. if len(a.params) > 0 {
  796. c.sendReply(ERR_INVALIDCAPCMD, a.subcommand,
  797. "No acknowledgable capabilities supported")
  798. }
  799. }
  800. func (c *client) handleCAPEND(a *ircCapArgs) {
  801. c.capNegotiating = false
  802. c.tryFinishRegistration()
  803. }
  804. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  805. // TODO: Beware of case sensitivity, probably need to index it by ircStrxfrm,
  806. // which should arguably be named ircToLower and ircToUpper or something.
  807. var ircCapHandlers = map[string]func(*client, *ircCapArgs){
  808. "LS": (*client).handleCAPLS,
  809. "LIST": (*client).handleCAPLIST,
  810. "REQ": (*client).handleCAPREQ,
  811. "ACK": (*client).handleCAPACK,
  812. "END": (*client).handleCAPEND,
  813. }
  814. // XXX: Maybe these also deserve to be methods for client? They operato on
  815. // global state, though.
  816. func ircHandleCAP(msg *message, c *client) {
  817. if len(msg.params) < 1 {
  818. c.sendReply(ERR_NEEDMOREPARAMS, msg.command)
  819. return
  820. }
  821. // TODO: This really does seem to warrant a method.
  822. nickname := c.nickname
  823. if nickname == "" {
  824. nickname = "*"
  825. }
  826. args := &ircCapArgs{
  827. target: nickname,
  828. subcommand: msg.params[0],
  829. fullParams: "",
  830. params: []string{},
  831. }
  832. if len(msg.params) > 1 {
  833. args.fullParams = msg.params[1]
  834. // TODO: ignore_empty, likely create SplitSkipEmpty
  835. args.params = strings.Split(args.fullParams, " ")
  836. }
  837. // FIXME: We should ASCII ToUpper the subcommand.
  838. if fn, ok := ircCapHandlers[ircStrxfrm(args.subcommand)]; !ok {
  839. c.sendReply(ERR_INVALIDCAPCMD, args.subcommand,
  840. "Invalid CAP subcommand")
  841. } else {
  842. fn(c, args)
  843. }
  844. }
  845. func ircHandlePASS(msg *message, c *client) {
  846. if c.registered {
  847. c.sendReply(ERR_ALREADYREGISTERED)
  848. } else if len(msg.params) < 1 {
  849. c.sendReply(ERR_NEEDMOREPARAMS, msg.command)
  850. }
  851. // We have TLS client certificates for this purpose; ignoring.
  852. }
  853. func ircHandleNICK(msg *message, c *client) {
  854. if len(msg.params) < 1 {
  855. c.sendReply(ERR_NONICKNAMEGIVEN)
  856. return
  857. }
  858. nickname := msg.params[0]
  859. if !ircIsValidNickname(nickname) {
  860. c.sendReply(ERR_ERRONEOUSNICKNAME, nickname)
  861. return
  862. }
  863. nicknameNormalized := ircStrxfrm(nickname)
  864. if client, ok := users[nicknameNormalized]; ok && client != c {
  865. c.sendReply(ERR_NICKNAMEINUSE, nickname)
  866. return
  867. }
  868. if c.registered {
  869. c.addToWhowas()
  870. message := fmt.Sprintf(":%s!%s@%s NICK :%s",
  871. c.nickname, c.username, c.hostname, nickname)
  872. ircSendToRoommates(c, message)
  873. c.send(message)
  874. }
  875. // Release the old nickname and allocate a new one.
  876. if c.nickname != "" {
  877. delete(users, ircStrxfrm(c.nickname))
  878. }
  879. c.nickname = nickname
  880. users[nicknameNormalized] = c
  881. c.tryFinishRegistration()
  882. }
  883. func ircHandleUSER(msg *message, c *client) {
  884. if c.registered {
  885. c.sendReply(ERR_ALREADYREGISTERED)
  886. return
  887. }
  888. if len(msg.params) < 4 {
  889. c.sendReply(ERR_NEEDMOREPARAMS, msg.command)
  890. return
  891. }
  892. username, mode, realname := msg.params[0], msg.params[1], msg.params[3]
  893. // Unfortunately the protocol doesn't give us any means of rejecting it
  894. if !ircIsValidUsername(username) {
  895. username = "*"
  896. }
  897. c.username = username
  898. c.realname = realname
  899. c.mode = 0
  900. if m, err := strconv.ParseUint(mode, 10, 32); err != nil {
  901. if 0 != m&4 {
  902. c.mode |= ircUserModeRxWallops
  903. }
  904. if 0 != m&8 {
  905. c.mode |= ircUserModeInvisible
  906. }
  907. }
  908. c.tryFinishRegistration()
  909. }
  910. func ircHandleUSERHOST(msg *message, c *client) {
  911. if len(msg.params) < 1 {
  912. c.sendReply(ERR_NEEDMOREPARAMS, msg.command)
  913. return
  914. }
  915. // TODO
  916. }
  917. func ircHandleLUSERS(msg *message, c *client) {
  918. if len(msg.params) > 1 && !isThisMe(msg.params[1]) {
  919. c.sendReply(ERR_NOSUCHSERVER, msg.params[1])
  920. return
  921. }
  922. c.sendLUSERS()
  923. }
  924. func ircHandleMOTD(msg *message, c *client) {
  925. if len(msg.params) > 0 && !isThisMe(msg.params[0]) {
  926. c.sendReply(ERR_NOSUCHSERVER, msg.params[1])
  927. return
  928. }
  929. c.sendMOTD()
  930. }
  931. func ircHandlePING(msg *message, c *client) {
  932. // XXX: The RFC is pretty incomprehensible about the exact usage.
  933. if len(msg.params) > 1 && !isThisMe(msg.params[1]) {
  934. c.sendReply(ERR_NOSUCHSERVER, msg.params[1])
  935. } else if len(msg.params) < 1 {
  936. c.sendReply(ERR_NOORIGIN)
  937. } else {
  938. c.sendf(":%s PONG :%s", serverName, msg.params[0])
  939. }
  940. }
  941. func ircHandlePONG(msg *message, c *client) {
  942. // We are the only server, so we don't have to care too much.
  943. if len(msg.params) < 1 {
  944. c.sendReply(ERR_NOORIGIN)
  945. return
  946. }
  947. // Set a new timer to send another PING
  948. // TODO
  949. }
  950. func ircHandleQUIT(msg *message, c *client) {
  951. reason := c.nickname
  952. if len(msg.params) > 0 {
  953. reason = msg.params[0]
  954. }
  955. c.closeLink("Quit: " + reason)
  956. }
  957. func ircHandleTIME(msg *message, c *client) {
  958. if len(msg.params) > 0 && !isThisMe(msg.params[0]) {
  959. c.sendReply(ERR_NOSUCHSERVER, msg.params[0])
  960. return
  961. }
  962. c.sendReply(RPL_TIME, serverName,
  963. time.Now().Format("Mon Jan _2 2006 15:04:05"))
  964. }
  965. func ircHandleVERSION(msg *message, c *client) {
  966. if len(msg.params) > 0 && !isThisMe(msg.params[0]) {
  967. c.sendReply(ERR_NOSUCHSERVER, msg.params[0])
  968. return
  969. }
  970. postVersion := 0
  971. if debugMode {
  972. postVersion = 1
  973. }
  974. c.sendReply(RPL_VERSION, "TODO version", postVersion, serverName,
  975. "TODO program name"+" "+"TODO version")
  976. c.sendISUPPORT()
  977. }
  978. /*
  979. func ircChannelMulticast(ch *channel, msg string, except *client) {
  980. for c, m := range ch.userModes {
  981. if c != except {
  982. c.send(msg)
  983. }
  984. }
  985. }
  986. func ircModifyMode(mask *uint, mode uint, add bool) bool {
  987. orig := *mask
  988. if add {
  989. *mask |= mode
  990. } else {
  991. *mask &= ^mode
  992. }
  993. return *mask != orig
  994. }
  995. func ircUpdateUserMode(c *client, newMode uint) {
  996. // TODO: Port, as well as all the other kike functions.
  997. }
  998. */
  999. func ircHandleMODE(msg *message, c *client) {
  1000. if len(msg.params) < 1 {
  1001. c.sendReply(ERR_NEEDMOREPARAMS, msg.command)
  1002. return
  1003. }
  1004. // TODO
  1005. target := msg.params[0]
  1006. client := users[ircStrxfrm(target)]
  1007. ch := users[ircStrxfrm(target)]
  1008. if client != nil {
  1009. // TODO: Think about strcmp.
  1010. //if ircStrcmp(target, c.nickname) != 0 {
  1011. //}
  1012. } else if ch != nil {
  1013. // TODO
  1014. }
  1015. }
  1016. func ircHandleUserMessage(msg *message, c *client,
  1017. command string, allowAwayReply bool) {
  1018. if len(msg.params) < 1 {
  1019. c.sendReply(ERR_NORECIPIENT, msg.command)
  1020. return
  1021. }
  1022. if len(msg.params) < 2 || msg.params[1] == "" {
  1023. c.sendReply(ERR_NOTEXTTOSEND)
  1024. return
  1025. }
  1026. target, text := msg.params[0], msg.params[1]
  1027. if client, ok := users[ircStrxfrm(target)]; ok {
  1028. // TODO
  1029. _ = client
  1030. _ = text
  1031. } else if ch, ok := channels[ircStrxfrm(target)]; ok {
  1032. // TODO
  1033. _ = ch
  1034. } else {
  1035. c.sendReply(ERR_NOSUCHNICK, target)
  1036. }
  1037. }
  1038. // TODO: All the various real command handlers.
  1039. func ircHandleX(msg *message, c *client) {
  1040. }
  1041. // --- ? -----------------------------------------------------------------------
  1042. // Handle the results from initializing the client's connection.
  1043. func (c *client) onPrepared(host string, isTLS bool) {
  1044. if isTLS {
  1045. c.tls = tls.Server(c.transport, tlsConf)
  1046. c.conn = c.tls
  1047. } else {
  1048. c.conn = c.transport.(connCloseWrite)
  1049. }
  1050. c.hostname = host
  1051. c.address = net.JoinHostPort(host, c.port)
  1052. // TODO: If we've tried to send any data before now, we need to flushOutQ.
  1053. go read(c)
  1054. c.reading = true
  1055. }
  1056. // Handle the results from trying to read from the client connection.
  1057. func (c *client) onRead(data []byte, readErr error) {
  1058. if !c.reading {
  1059. // Abusing the flag to emulate CloseRead and skip over data, see below.
  1060. return
  1061. }
  1062. c.inQ = append(c.inQ, data...)
  1063. for {
  1064. // XXX: This accepts even simple LF newlines, even though they're not
  1065. // really allowed by the protocol.
  1066. advance, token, _ := bufio.ScanLines(c.inQ, false /* atEOF */)
  1067. if advance == 0 {
  1068. break
  1069. }
  1070. c.inQ = c.inQ[advance:]
  1071. line := string(token)
  1072. log.Printf("-> %s\n", line)
  1073. m := reMsg.FindStringSubmatch(line)
  1074. if m == nil {
  1075. log.Println("error: invalid line")
  1076. continue
  1077. }
  1078. msg := message{m[1], m[2], m[3], m[4], nil}
  1079. for _, x := range reArgs.FindAllString(m[5], -1) {
  1080. msg.params = append(msg.params, x[1:])
  1081. }
  1082. broadcast(line, c)
  1083. }
  1084. if readErr != nil {
  1085. c.reading = false
  1086. if readErr != io.EOF {
  1087. log.Println(readErr)
  1088. c.destroy("TODO")
  1089. } else if c.closing {
  1090. // Disregarding whether a clean shutdown has happened or not.
  1091. log.Println("client finished shutdown")
  1092. c.destroy("TODO")
  1093. } else {
  1094. log.Println("client EOF")
  1095. c.closeLink("")
  1096. }
  1097. } else if len(c.inQ) > 8192 {
  1098. log.Println("client inQ overrun")
  1099. c.closeLink("inQ overrun")
  1100. // tls.Conn doesn't have the CloseRead method (and it needs to be able
  1101. // to read from the TCP connection even for writes, so there isn't much
  1102. // sense in expecting the implementation to do anything useful),
  1103. // otherwise we'd use it to block incoming packet data.
  1104. c.reading = false
  1105. }
  1106. }
  1107. // Spawn a goroutine to flush the outQ if possible and necessary.
  1108. func (c *client) flushOutQ() {
  1109. if !c.writing && c.conn != nil {
  1110. go write(c, c.outQ)
  1111. c.writing = true
  1112. }
  1113. }
  1114. // Handle the results from trying to write to the client connection.
  1115. func (c *client) onWrite(written int, writeErr error) {
  1116. c.outQ = c.outQ[written:]
  1117. c.writing = false
  1118. if writeErr != nil {
  1119. log.Println(writeErr)
  1120. c.destroy("TODO")
  1121. } else if len(c.outQ) > 0 {
  1122. c.flushOutQ()
  1123. } else if c.closing {
  1124. if c.reading {
  1125. c.conn.CloseWrite()
  1126. } else {
  1127. c.destroy("TODO")
  1128. }
  1129. }
  1130. }
  1131. // --- Worker goroutines -------------------------------------------------------
  1132. func accept(ln net.Listener) {
  1133. for {
  1134. if conn, err := ln.Accept(); err != nil {
  1135. // TODO: Consider specific cases in error handling, some errors
  1136. // are transitional while others are fatal.
  1137. log.Println(err)
  1138. break
  1139. } else {
  1140. conns <- conn
  1141. }
  1142. }
  1143. }
  1144. func prepare(client *client) {
  1145. conn := client.transport
  1146. host, _, err := net.SplitHostPort(conn.RemoteAddr().String())
  1147. if err != nil {
  1148. // In effect, we require TCP/UDP, as they have port numbers.
  1149. log.Fatalln(err)
  1150. }
  1151. // The Cgo resolver doesn't pthread_cancel getnameinfo threads, so not
  1152. // bothering with pointless contexts.
  1153. ch := make(chan string, 1)
  1154. go func() {
  1155. defer close(ch)
  1156. if names, err := net.LookupAddr(host); err != nil {
  1157. log.Println(err)
  1158. } else {
  1159. ch <- names[0]
  1160. }
  1161. }()
  1162. // While we can't cancel it, we still want to set a timeout on it.
  1163. select {
  1164. case <-time.After(5 * time.Second):
  1165. case resolved, ok := <-ch:
  1166. if ok {
  1167. host = resolved
  1168. }
  1169. }
  1170. // Note that in this demo application the autodetection prevents non-TLS
  1171. // clients from receiving any messages until they send something.
  1172. isTLS := false
  1173. if sysconn, err := conn.(syscall.Conn).SyscallConn(); err != nil {
  1174. // This is just for the TLS detection and doesn't need to be fatal.
  1175. log.Println(err)
  1176. } else {
  1177. isTLS = detectTLS(sysconn)
  1178. }
  1179. // FIXME: When the client sends no data, we still initialize its conn.
  1180. prepared <- preparedEvent{client, host, isTLS}
  1181. }
  1182. func read(client *client) {
  1183. // A new buffer is allocated each time we receive some bytes, because of
  1184. // thread-safety. Therefore the buffer shouldn't be too large, or we'd
  1185. // need to copy it each time into a precisely sized new buffer.
  1186. var err error
  1187. for err == nil {
  1188. var (
  1189. buf [512]byte
  1190. n int
  1191. )
  1192. n, err = client.conn.Read(buf[:])
  1193. reads <- readEvent{client, buf[:n], err}
  1194. }
  1195. }
  1196. // Flush outQ, which is passed by parameter so that there are no data races.
  1197. func write(client *client, data []byte) {
  1198. // We just write as much as we can, the main goroutine does the looping.
  1199. n, err := client.conn.Write(data)
  1200. writes <- writeEvent{client, n, err}
  1201. }
  1202. // --- Main --------------------------------------------------------------------
  1203. func processOneEvent() {
  1204. select {
  1205. case <-sigs:
  1206. if inShutdown {
  1207. forceShutdown("requested by user")
  1208. } else {
  1209. initiateShutdown()
  1210. }
  1211. case <-shutdownTimer:
  1212. forceShutdown("timeout")
  1213. case conn := <-conns:
  1214. log.Println("accepted client connection")
  1215. // In effect, we require TCP/UDP, as they have port numbers.
  1216. address := conn.RemoteAddr().String()
  1217. host, port, err := net.SplitHostPort(address)
  1218. if err != nil {
  1219. log.Fatalln(err)
  1220. }
  1221. c := &client{
  1222. transport: conn,
  1223. address: address,
  1224. hostname: host,
  1225. port: port,
  1226. }
  1227. clients[c] = true
  1228. go prepare(c)
  1229. case ev := <-prepared:
  1230. log.Println("client is ready:", ev.host)
  1231. if _, ok := clients[ev.client]; ok {
  1232. ev.client.onPrepared(ev.host, ev.isTLS)
  1233. }
  1234. case ev := <-reads:
  1235. log.Println("received data from client")
  1236. if _, ok := clients[ev.client]; ok {
  1237. ev.client.onRead(ev.data, ev.err)
  1238. }
  1239. case ev := <-writes:
  1240. log.Println("sent data to client")
  1241. if _, ok := clients[ev.client]; ok {
  1242. ev.client.onWrite(ev.written, ev.err)
  1243. }
  1244. case c := <-timeouts:
  1245. if _, ok := clients[c]; ok {
  1246. log.Println("client timeouted")
  1247. c.destroy("TODO")
  1248. }
  1249. }
  1250. }
  1251. func main() {
  1252. flag.BoolVar(&debugMode, "debug", false, "debug mode")
  1253. version := flag.Bool("version", false, "show version and exit")
  1254. flag.Parse()
  1255. // TODO: Consider using the same version number for all subprojects.
  1256. if *version {
  1257. fmt.Printf("%s %s\n", "hid", "0")
  1258. return
  1259. }
  1260. // TODO: Configuration--create an INI parser, probably;
  1261. // lift XDG_CONFIG_HOME from gitlab-notifier.
  1262. if len(flag.Args()) != 3 {
  1263. log.Fatalf("usage: %s KEY CERT ADDRESS\n", os.Args[0])
  1264. }
  1265. cert, err := tls.LoadX509KeyPair(flag.Arg(1), flag.Arg(0))
  1266. if err != nil {
  1267. log.Fatalln(err)
  1268. }
  1269. tlsConf = &tls.Config{
  1270. Certificates: []tls.Certificate{cert},
  1271. ClientAuth: tls.RequestClientCert,
  1272. SessionTicketsDisabled: true,
  1273. }
  1274. listener, err = net.Listen("tcp", flag.Arg(2))
  1275. if err != nil {
  1276. log.Fatalln(err)
  1277. }
  1278. go accept(listener)
  1279. signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
  1280. for !inShutdown || len(clients) > 0 {
  1281. processOneEvent()
  1282. }
  1283. }