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.

socket.go 2.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // Copyright (c) 2012-2014 Jeremy Latt
  2. // Copyright (c) 2016- Daniel Oaks <daniel@danieloaks.net>
  3. // released under the MIT license
  4. package irc
  5. import (
  6. "bufio"
  7. "crypto/sha256"
  8. "crypto/tls"
  9. "encoding/hex"
  10. "errors"
  11. "io"
  12. "net"
  13. "strings"
  14. )
  15. var (
  16. errNotTLS = errors.New("Not a TLS connection")
  17. errNoPeerCerts = errors.New("Client did not provide a certificate")
  18. )
  19. // Socket represents an IRC socket.
  20. type Socket struct {
  21. Closed bool
  22. conn net.Conn
  23. reader *bufio.Reader
  24. }
  25. // NewSocket returns a new Socket.
  26. func NewSocket(conn net.Conn) Socket {
  27. return Socket{
  28. conn: conn,
  29. reader: bufio.NewReader(conn),
  30. }
  31. }
  32. // Close stops a Socket from being able to send/receive any more data.
  33. func (socket *Socket) Close() {
  34. if socket.Closed {
  35. return
  36. }
  37. socket.Closed = true
  38. socket.conn.Close()
  39. }
  40. // CertFP returns the fingerprint of the certificate provided by the client.
  41. func (socket *Socket) CertFP() (string, error) {
  42. var tlsConn, isTLS = socket.conn.(*tls.Conn)
  43. if !isTLS {
  44. return "", errNotTLS
  45. }
  46. // ensure handehake is performed
  47. tlsConn.Handshake()
  48. peerCerts := tlsConn.ConnectionState().PeerCertificates
  49. if len(peerCerts) < 1 {
  50. return "", errNoPeerCerts
  51. }
  52. rawCert := sha256.Sum256(peerCerts[0].Raw)
  53. fingerprint := hex.EncodeToString(rawCert[:])
  54. return fingerprint, nil
  55. }
  56. // Read returns a single IRC line from a Socket.
  57. func (socket *Socket) Read() (string, error) {
  58. if socket.Closed {
  59. return "", io.EOF
  60. }
  61. lineBytes, err := socket.reader.ReadBytes('\n')
  62. // convert bytes to string
  63. line := string(lineBytes[:])
  64. // read last message properly (such as ERROR/QUIT/etc), just fail next reads/writes
  65. if err == io.EOF {
  66. socket.Close()
  67. }
  68. if err == io.EOF && strings.TrimSpace(line) != "" {
  69. // don't do anything
  70. } else if err != nil {
  71. return "", err
  72. }
  73. return strings.TrimRight(line, "\r\n"), nil
  74. }
  75. // Write sends the given string out of Socket.
  76. func (socket *Socket) Write(data string) error {
  77. if socket.Closed {
  78. return io.EOF
  79. }
  80. // write data
  81. _, err := socket.conn.Write([]byte(data))
  82. if err != nil {
  83. socket.Close()
  84. return err
  85. }
  86. return nil
  87. }
  88. // WriteLine writes the given line out of Socket.
  89. func (socket *Socket) WriteLine(line string) error {
  90. return socket.Write(line + "\r\n")
  91. }