server.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. package guerrilla
  2. import (
  3. "bytes"
  4. "crypto/rand"
  5. "crypto/tls"
  6. "crypto/x509"
  7. "fmt"
  8. "io"
  9. "io/ioutil"
  10. "net"
  11. "path/filepath"
  12. "strings"
  13. "sync"
  14. "sync/atomic"
  15. "time"
  16. "github.com/flashmob/go-guerrilla/backends"
  17. "github.com/flashmob/go-guerrilla/log"
  18. "github.com/flashmob/go-guerrilla/mail"
  19. "github.com/flashmob/go-guerrilla/mail/rfc5321"
  20. "github.com/flashmob/go-guerrilla/response"
  21. )
  22. const (
  23. CommandVerbMaxLength = 16
  24. CommandLineMaxLength = 1024
  25. // Number of allowed unrecognized commands before we terminate the connection
  26. MaxUnrecognizedCommands = 5
  27. )
  28. const (
  29. // server has just been created
  30. ServerStateNew = iota
  31. // Server has just been stopped
  32. ServerStateStopped
  33. // Server has been started and is running
  34. ServerStateRunning
  35. // Server could not start due to an error
  36. ServerStateStartError
  37. )
  38. // Server listens for SMTP clients on the port specified in its config
  39. type server struct {
  40. configStore atomic.Value // stores guerrilla.ServerConfig
  41. tlsConfigStore atomic.Value
  42. timeout atomic.Value // stores time.Duration
  43. listenInterface string
  44. clientPool *Pool
  45. wg sync.WaitGroup // for waiting to shutdown
  46. listener net.Listener
  47. closedListener chan bool
  48. hosts allowedHosts // stores map[string]bool for faster lookup
  49. state int
  50. // If log changed after a config reload, newLogStore stores the value here until it's safe to change it
  51. logStore atomic.Value
  52. mainlogStore atomic.Value
  53. backendStore atomic.Value
  54. envelopePool *mail.Pool
  55. }
  56. type allowedHosts struct {
  57. table map[string]bool // host lookup table
  58. wildcards []string // host wildcard list (* is used as a wildcard)
  59. sync.Mutex // guard access to the map
  60. }
  61. type command []byte
  62. var (
  63. cmdHELO command = []byte("HELO")
  64. cmdEHLO command = []byte("EHLO")
  65. cmdHELP command = []byte("HELP")
  66. cmdXCLIENT command = []byte("XCLIENT")
  67. cmdMAIL command = []byte("MAIL FROM:")
  68. cmdRCPT command = []byte("RCPT TO:")
  69. cmdRSET command = []byte("RSET")
  70. cmdVRFY command = []byte("VRFY")
  71. cmdNOOP command = []byte("NOOP")
  72. cmdQUIT command = []byte("QUIT")
  73. cmdDATA command = []byte("DATA")
  74. cmdSTARTTLS command = []byte("STARTTLS")
  75. )
  76. func (c command) match(in []byte) bool {
  77. return bytes.Index(in, []byte(c)) == 0
  78. }
  79. // Creates and returns a new ready-to-run Server from a configuration
  80. func newServer(sc *ServerConfig, b backends.Backend, l log.Logger) (*server, error) {
  81. server := &server{
  82. clientPool: NewPool(sc.MaxClients),
  83. closedListener: make(chan bool, 1),
  84. listenInterface: sc.ListenInterface,
  85. state: ServerStateNew,
  86. envelopePool: mail.NewPool(sc.MaxClients),
  87. }
  88. server.logStore.Store(l)
  89. server.backendStore.Store(b)
  90. logFile := sc.LogFile
  91. if logFile == "" {
  92. // none set, use the same log file as mainlog
  93. logFile = server.mainlog().GetLogDest()
  94. }
  95. // set level to same level as mainlog level
  96. mainlog, logOpenError := log.GetLogger(logFile, server.mainlog().GetLevel())
  97. server.mainlogStore.Store(mainlog)
  98. if logOpenError != nil {
  99. server.log().WithError(logOpenError).Errorf("Failed creating a logger for server [%s]", sc.ListenInterface)
  100. }
  101. server.setConfig(sc)
  102. server.setTimeout(sc.Timeout)
  103. if err := server.configureSSL(); err != nil {
  104. return server, err
  105. }
  106. return server, nil
  107. }
  108. func (s *server) configureSSL() error {
  109. sConfig := s.configStore.Load().(ServerConfig)
  110. if sConfig.TLS.AlwaysOn || sConfig.TLS.StartTLSOn {
  111. cert, err := tls.LoadX509KeyPair(sConfig.TLS.PublicKeyFile, sConfig.TLS.PrivateKeyFile)
  112. if err != nil {
  113. return fmt.Errorf("error while loading the certificate: %s", err)
  114. }
  115. tlsConfig := &tls.Config{
  116. Certificates: []tls.Certificate{cert},
  117. ClientAuth: tls.VerifyClientCertIfGiven,
  118. ServerName: sConfig.Hostname,
  119. }
  120. if len(sConfig.TLS.Protocols) > 0 {
  121. if min, ok := TLSProtocols[sConfig.TLS.Protocols[0]]; ok {
  122. tlsConfig.MinVersion = min
  123. }
  124. }
  125. if len(sConfig.TLS.Protocols) > 1 {
  126. if max, ok := TLSProtocols[sConfig.TLS.Protocols[1]]; ok {
  127. tlsConfig.MaxVersion = max
  128. }
  129. }
  130. if len(sConfig.TLS.Ciphers) > 0 {
  131. for _, val := range sConfig.TLS.Ciphers {
  132. if c, ok := TLSCiphers[val]; ok {
  133. tlsConfig.CipherSuites = append(tlsConfig.CipherSuites, c)
  134. }
  135. }
  136. }
  137. if len(sConfig.TLS.Curves) > 0 {
  138. for _, val := range sConfig.TLS.Curves {
  139. if c, ok := TLSCurves[val]; ok {
  140. tlsConfig.CurvePreferences = append(tlsConfig.CurvePreferences, c)
  141. }
  142. }
  143. }
  144. if len(sConfig.TLS.RootCAs) > 0 {
  145. caCert, err := ioutil.ReadFile(sConfig.TLS.RootCAs)
  146. if err != nil {
  147. s.log().WithError(err).Errorf("failed opening TLSRootCAs file [%s]", sConfig.TLS.RootCAs)
  148. } else {
  149. caCertPool := x509.NewCertPool()
  150. caCertPool.AppendCertsFromPEM(caCert)
  151. tlsConfig.RootCAs = caCertPool
  152. }
  153. }
  154. if len(sConfig.TLS.ClientAuthType) > 0 {
  155. if ca, ok := TLSClientAuthTypes[sConfig.TLS.ClientAuthType]; ok {
  156. tlsConfig.ClientAuth = ca
  157. }
  158. }
  159. tlsConfig.PreferServerCipherSuites = sConfig.TLS.PreferServerCipherSuites
  160. tlsConfig.Rand = rand.Reader
  161. s.tlsConfigStore.Store(tlsConfig)
  162. }
  163. return nil
  164. }
  165. // setBackend sets the backend to use for processing email envelopes
  166. func (s *server) setBackend(b backends.Backend) {
  167. s.backendStore.Store(b)
  168. }
  169. // backend gets the backend used to process email envelopes
  170. func (s *server) backend() backends.Backend {
  171. if b, ok := s.backendStore.Load().(backends.Backend); ok {
  172. return b
  173. }
  174. return nil
  175. }
  176. // Set the timeout for the server and all clients
  177. func (s *server) setTimeout(seconds int) {
  178. duration := time.Duration(int64(seconds))
  179. s.clientPool.SetTimeout(duration)
  180. s.timeout.Store(duration)
  181. }
  182. // goroutine safe config store
  183. func (s *server) setConfig(sc *ServerConfig) {
  184. s.configStore.Store(*sc)
  185. }
  186. // goroutine safe
  187. func (s *server) isEnabled() bool {
  188. sc := s.configStore.Load().(ServerConfig)
  189. return sc.IsEnabled
  190. }
  191. // Set the allowed hosts for the server
  192. func (s *server) setAllowedHosts(allowedHosts []string) {
  193. s.hosts.Lock()
  194. defer s.hosts.Unlock()
  195. s.hosts.table = make(map[string]bool, len(allowedHosts))
  196. s.hosts.wildcards = nil
  197. for _, h := range allowedHosts {
  198. if strings.Index(h, "*") != -1 {
  199. s.hosts.wildcards = append(s.hosts.wildcards, strings.ToLower(h))
  200. } else {
  201. s.hosts.table[strings.ToLower(h)] = true
  202. }
  203. }
  204. }
  205. // Begin accepting SMTP clients. Will block unless there is an error or server.Shutdown() is called
  206. func (s *server) Start(startWG *sync.WaitGroup) error {
  207. var clientID uint64
  208. clientID = 0
  209. listener, err := net.Listen("tcp", s.listenInterface)
  210. s.listener = listener
  211. if err != nil {
  212. startWG.Done() // don't wait for me
  213. s.state = ServerStateStartError
  214. return fmt.Errorf("[%s] Cannot listen on port: %s ", s.listenInterface, err.Error())
  215. }
  216. s.log().Infof("Listening on TCP %s", s.listenInterface)
  217. s.state = ServerStateRunning
  218. startWG.Done() // start successful, don't wait for me
  219. for {
  220. s.log().Debugf("[%s] Waiting for a new client. Next Client ID: %d", s.listenInterface, clientID+1)
  221. conn, err := listener.Accept()
  222. clientID++
  223. if err != nil {
  224. if e, ok := err.(net.Error); ok && !e.Temporary() {
  225. s.log().Infof("Server [%s] has stopped accepting new clients", s.listenInterface)
  226. // the listener has been closed, wait for clients to exit
  227. s.log().Infof("shutting down pool [%s]", s.listenInterface)
  228. s.clientPool.ShutdownState()
  229. s.clientPool.ShutdownWait()
  230. s.state = ServerStateStopped
  231. s.closedListener <- true
  232. return nil
  233. }
  234. s.mainlog().WithError(err).Info("Temporary error accepting client")
  235. continue
  236. }
  237. go func(p Poolable, borrowErr error) {
  238. c := p.(*client)
  239. if borrowErr == nil {
  240. s.handleClient(c)
  241. s.envelopePool.Return(c.Envelope)
  242. s.clientPool.Return(c)
  243. } else {
  244. s.log().WithError(borrowErr).Info("couldn't borrow a new client")
  245. // we could not get a client, so close the connection.
  246. _ = conn.Close()
  247. }
  248. // intentionally placed Borrow in args so that it's called in the
  249. // same main goroutine.
  250. }(s.clientPool.Borrow(conn, clientID, s.log(), s.envelopePool))
  251. }
  252. }
  253. func (s *server) Shutdown() {
  254. if s.listener != nil {
  255. // This will cause Start function to return, by causing an error on listener.Accept
  256. _ = s.listener.Close()
  257. // wait for the listener to listener.Accept
  258. <-s.closedListener
  259. // At this point Start will exit and close down the pool
  260. } else {
  261. s.clientPool.ShutdownState()
  262. // listener already closed, wait for clients to exit
  263. s.clientPool.ShutdownWait()
  264. s.state = ServerStateStopped
  265. }
  266. }
  267. func (s *server) GetActiveClientsCount() int {
  268. return s.clientPool.GetActiveClientsCount()
  269. }
  270. // Verifies that the host is a valid recipient.
  271. // host checking turned off if there is a single entry and it's a dot.
  272. func (s *server) allowsHost(host string) bool {
  273. s.hosts.Lock()
  274. defer s.hosts.Unlock()
  275. // if hosts contains a single dot, further processing is skipped
  276. if len(s.hosts.table) == 1 {
  277. if _, ok := s.hosts.table["."]; ok {
  278. return true
  279. }
  280. }
  281. if _, ok := s.hosts.table[strings.ToLower(host)]; ok {
  282. return true
  283. }
  284. // check the wildcards
  285. for _, w := range s.hosts.wildcards {
  286. if matched, err := filepath.Match(w, strings.ToLower(host)); matched && err == nil {
  287. return true
  288. }
  289. }
  290. return false
  291. }
  292. const commandSuffix = "\r\n"
  293. // Reads from the client until a \n terminator is encountered,
  294. // or until a timeout occurs.
  295. func (s *server) readCommand(client *client) ([]byte, error) {
  296. //var input string
  297. var err error
  298. var bs []byte
  299. // In command state, stop reading at line breaks
  300. bs, err = client.bufin.ReadSlice('\n')
  301. if err != nil {
  302. return bs, err
  303. } else if bytes.HasSuffix(bs, []byte(commandSuffix)) {
  304. return bs[:len(bs)-2], err
  305. }
  306. return bs[:len(bs)-1], err
  307. }
  308. // flushResponse a response to the client. Flushes the client.bufout buffer to the connection
  309. func (s *server) flushResponse(client *client) error {
  310. if err := client.setTimeout(s.timeout.Load().(time.Duration)); err != nil {
  311. return err
  312. }
  313. return client.bufout.Flush()
  314. }
  315. func (s *server) isShuttingDown() bool {
  316. return s.clientPool.IsShuttingDown()
  317. }
  318. // Handles an entire client SMTP exchange
  319. func (s *server) handleClient(client *client) {
  320. defer func() {
  321. s.log().WithFields(map[string]interface{}{
  322. "event": "disconnect",
  323. "id": client.ID,
  324. }).Info("Disconnect client")
  325. client.closeConn()
  326. }()
  327. sc := s.configStore.Load().(ServerConfig)
  328. s.log().WithFields(map[string]interface{}{
  329. "event": "connect",
  330. "id": client.ID,
  331. }).Infof("Handle client [%s]", client.RemoteIP)
  332. // Initial greeting
  333. greeting := fmt.Sprintf("220 %s SMTP Guerrilla(%s) #%d (%d) %s",
  334. sc.Hostname, Version, client.ID,
  335. s.clientPool.GetActiveClientsCount(), time.Now().Format(time.RFC3339))
  336. helo := fmt.Sprintf("250 %s Hello", sc.Hostname)
  337. // ehlo is a multi-line reply and need additional \r\n at the end
  338. ehlo := fmt.Sprintf("250-%s Hello\r\n", sc.Hostname)
  339. // Extended feature advertisements
  340. messageSize := fmt.Sprintf("250-SIZE %d\r\n", sc.MaxSize)
  341. pipelining := "250-PIPELINING\r\n"
  342. advertiseTLS := "250-STARTTLS\r\n"
  343. advertiseEnhancedStatusCodes := "250-ENHANCEDSTATUSCODES\r\n"
  344. // The last line doesn't need \r\n since string will be printed as a new line.
  345. // Also, Last line has no dash -
  346. help := "250 HELP"
  347. if sc.TLS.AlwaysOn {
  348. tlsConfig, ok := s.tlsConfigStore.Load().(*tls.Config)
  349. if !ok {
  350. s.mainlog().Error("Failed to load *tls.Config")
  351. } else if err := client.upgradeToTLS(tlsConfig); err == nil {
  352. advertiseTLS = ""
  353. } else {
  354. s.log().WithError(err).Warnf("[%s] Failed TLS handshake", client.RemoteIP)
  355. // server requires TLS, but can't handshake
  356. client.kill()
  357. }
  358. }
  359. if !sc.TLS.StartTLSOn {
  360. // STARTTLS turned off, don't advertise it
  361. advertiseTLS = ""
  362. }
  363. r := response.Canned
  364. for client.isAlive() {
  365. switch client.state {
  366. case ClientGreeting:
  367. client.sendResponse(greeting)
  368. client.state = ClientCmd
  369. case ClientCmd:
  370. client.bufin.setLimit(CommandLineMaxLength)
  371. input, err := s.readCommand(client)
  372. s.log().Debugf("Client sent: %s", input)
  373. if err == io.EOF {
  374. s.log().WithError(err).Warnf("Client closed the connection: %s", client.RemoteIP)
  375. return
  376. } else if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
  377. s.log().WithError(err).Warnf("Timeout: %s", client.RemoteIP)
  378. return
  379. } else if err == LineLimitExceeded {
  380. client.sendResponse(r.FailLineTooLong)
  381. client.kill()
  382. break
  383. } else if err != nil {
  384. s.log().WithError(err).Warnf("Read error: %s", client.RemoteIP)
  385. client.kill()
  386. break
  387. }
  388. if s.isShuttingDown() {
  389. client.state = ClientShutdown
  390. continue
  391. }
  392. cmdLen := len(input)
  393. if cmdLen > CommandVerbMaxLength {
  394. cmdLen = CommandVerbMaxLength
  395. }
  396. cmd := bytes.ToUpper(input[:cmdLen])
  397. switch {
  398. case cmdHELO.match(cmd):
  399. client.Helo = string(bytes.Trim(input[4:], " "))
  400. client.resetTransaction()
  401. client.sendResponse(helo)
  402. case cmdEHLO.match(cmd):
  403. client.Helo = string(bytes.Trim(input[4:], " "))
  404. client.resetTransaction()
  405. client.sendResponse(ehlo,
  406. messageSize,
  407. pipelining,
  408. advertiseTLS,
  409. advertiseEnhancedStatusCodes,
  410. help)
  411. case cmdHELP.match(cmd):
  412. quote := response.GetQuote()
  413. client.sendResponse("214-OK\r\n", quote)
  414. case sc.XClientOn && cmdXCLIENT.match(cmd):
  415. if toks := bytes.Split(input[8:], []byte{' '}); len(toks) > 0 {
  416. for i := range toks {
  417. if vals := bytes.Split(toks[i], []byte{'='}); len(vals) == 2 {
  418. if bytes.Compare(vals[1], []byte("[UNAVAILABLE]")) == 0 {
  419. // skip
  420. continue
  421. }
  422. if bytes.Compare(vals[0], []byte("ADDR")) == 0 {
  423. client.RemoteIP = string(vals[1])
  424. }
  425. if bytes.Compare(vals[0], []byte("HELO")) == 0 {
  426. client.Helo = string(vals[1])
  427. }
  428. }
  429. }
  430. }
  431. client.sendResponse(r.SuccessMailCmd)
  432. case cmdMAIL.match(cmd):
  433. if client.isInTransaction() {
  434. client.sendResponse(r.FailNestedMailCmd)
  435. break
  436. }
  437. client.MailFrom, err = client.parsePath([]byte(input[10:]), client.parser.MailFrom)
  438. if err != nil {
  439. s.log().WithError(err).Error("MAIL parse error", "["+string(input[10:])+"]")
  440. client.sendResponse(err)
  441. break
  442. } else if client.parser.NullPath {
  443. // bounce has empty from address
  444. client.MailFrom = mail.Address{}
  445. } else {
  446. s.log().WithFields(map[string]interface{}{
  447. "event": "mailfrom",
  448. "helo": client.Helo,
  449. "domain": client.MailFrom.Host,
  450. "address": getRemoteAddr(client.conn),
  451. "id": client.ID,
  452. }).Info("Mail from")
  453. }
  454. client.sendResponse(r.SuccessMailCmd)
  455. case cmdRCPT.match(cmd):
  456. if len(client.RcptTo) > rfc5321.LimitRecipients {
  457. client.sendResponse(r.ErrorTooManyRecipients)
  458. break
  459. }
  460. to, err := client.parsePath([]byte(input[8:]), client.parser.RcptTo)
  461. if err != nil {
  462. s.log().WithError(err).Error("RCPT parse error", "["+string(input[8:])+"]")
  463. client.sendResponse(err.Error())
  464. break
  465. }
  466. if !s.allowsHost(to.Host) {
  467. client.sendResponse(r.ErrorRelayDenied, " ", to.Host)
  468. } else {
  469. client.PushRcpt(to)
  470. rcptError := s.backend().ValidateRcpt(client.Envelope)
  471. if rcptError != nil {
  472. client.PopRcpt()
  473. client.sendResponse(r.FailRcptCmd, " ", rcptError.Error())
  474. } else {
  475. client.sendResponse(r.SuccessRcptCmd)
  476. }
  477. }
  478. case cmdRSET.match(cmd):
  479. client.resetTransaction()
  480. client.sendResponse(r.SuccessResetCmd)
  481. case cmdVRFY.match(cmd):
  482. client.sendResponse(r.SuccessVerifyCmd)
  483. case cmdNOOP.match(cmd):
  484. client.sendResponse(r.SuccessNoopCmd)
  485. case cmdQUIT.match(cmd):
  486. client.sendResponse(r.SuccessQuitCmd)
  487. client.kill()
  488. case cmdDATA.match(cmd):
  489. if len(client.RcptTo) == 0 {
  490. client.sendResponse(r.FailNoRecipientsDataCmd)
  491. break
  492. }
  493. client.sendResponse(r.SuccessDataCmd)
  494. client.state = ClientData
  495. case sc.TLS.StartTLSOn && cmdSTARTTLS.match(cmd):
  496. client.sendResponse(r.SuccessStartTLSCmd)
  497. client.state = ClientStartTLS
  498. default:
  499. client.errors++
  500. if client.errors >= MaxUnrecognizedCommands {
  501. client.sendResponse(r.FailMaxUnrecognizedCmd)
  502. client.kill()
  503. } else {
  504. client.sendResponse(r.FailUnrecognizedCmd)
  505. }
  506. }
  507. case ClientData:
  508. // intentionally placed the limit 1MB above so that reading does not return with an error
  509. // if the client goes a little over. Anything above will err
  510. client.bufin.setLimit(int64(sc.MaxSize) + 1024000) // This a hard limit.
  511. n, err := client.Data.ReadFrom(client.smtpReader.DotReader())
  512. if n > sc.MaxSize {
  513. err = fmt.Errorf("maximum DATA size exceeded (%d)", sc.MaxSize)
  514. }
  515. if err != nil {
  516. if err == LineLimitExceeded {
  517. client.sendResponse(r.FailReadLimitExceededDataCmd, " ", LineLimitExceeded.Error())
  518. client.kill()
  519. } else if err == MessageSizeExceeded {
  520. client.sendResponse(r.FailMessageSizeExceeded, " ", MessageSizeExceeded.Error())
  521. client.kill()
  522. } else {
  523. client.sendResponse(r.FailReadErrorDataCmd, " ", err.Error())
  524. client.kill()
  525. }
  526. s.log().WithError(err).Warn("Error reading data")
  527. client.resetTransaction()
  528. break
  529. }
  530. res := s.backend().Process(client.Envelope)
  531. if res.Code() < 300 {
  532. client.messagesSent++
  533. s.log().WithFields(map[string]interface{}{
  534. "helo": client.Helo,
  535. "remoteAddress": getRemoteAddr(client.conn),
  536. "success": true,
  537. }).Info("Received message")
  538. }
  539. client.sendResponse(res)
  540. client.state = ClientCmd
  541. if s.isShuttingDown() {
  542. client.state = ClientShutdown
  543. }
  544. client.resetTransaction()
  545. case ClientStartTLS:
  546. if !client.TLS && sc.TLS.StartTLSOn {
  547. tlsConfig, ok := s.tlsConfigStore.Load().(*tls.Config)
  548. if !ok {
  549. s.mainlog().Error("Failed to load *tls.Config")
  550. } else if err := client.upgradeToTLS(tlsConfig); err == nil {
  551. advertiseTLS = ""
  552. client.resetTransaction()
  553. } else {
  554. s.log().WithError(err).Warnf("[%s] Failed TLS handshake", client.RemoteIP)
  555. // Don't disconnect, let the client decide if it wants to continue
  556. }
  557. }
  558. // change to command state
  559. client.state = ClientCmd
  560. case ClientShutdown:
  561. // shutdown state
  562. client.sendResponse(r.ErrorShutdown)
  563. client.kill()
  564. }
  565. if client.bufErr != nil {
  566. s.log().WithError(client.bufErr).Debug("client could not buffer a response")
  567. return
  568. }
  569. // flush the response buffer
  570. if client.bufout.Buffered() > 0 {
  571. if s.log().IsDebug() {
  572. s.log().Debugf("Writing response to client: \n%s", client.response.String())
  573. }
  574. err := s.flushResponse(client)
  575. if err != nil {
  576. s.log().WithError(err).Debug("error writing response")
  577. return
  578. }
  579. }
  580. }
  581. }
  582. func (s *server) log() log.Logger {
  583. if l, ok := s.logStore.Load().(log.Logger); ok {
  584. return l
  585. }
  586. l, err := log.GetLogger(log.OutputStderr.String(), log.InfoLevel.String())
  587. if err == nil {
  588. s.logStore.Store(l)
  589. }
  590. return l
  591. }
  592. func (s *server) mainlog() log.Logger {
  593. if l, ok := s.mainlogStore.Load().(log.Logger); ok {
  594. return l
  595. }
  596. l, err := log.GetLogger(log.OutputStderr.String(), log.InfoLevel.String())
  597. if err == nil {
  598. s.mainlogStore.Store(l)
  599. }
  600. return l
  601. }