tcp.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package hub
  2. import (
  3. "crypto/tls"
  4. "errors"
  5. "net"
  6. "sync"
  7. "github.com/v2ray/v2ray-core/common/log"
  8. v2net "github.com/v2ray/v2ray-core/common/net"
  9. )
  10. var (
  11. ErrorClosedConnection = errors.New("Connection already closed.")
  12. )
  13. type TCPHub struct {
  14. sync.Mutex
  15. listener net.Listener
  16. connCallback ConnectionHandler
  17. accepting bool
  18. }
  19. func ListenTCP(address v2net.Address, port v2net.Port, callback ConnectionHandler, tlsConfig *tls.Config) (*TCPHub, error) {
  20. listener, err := net.ListenTCP("tcp", &net.TCPAddr{
  21. IP: address.IP(),
  22. Port: int(port),
  23. Zone: "",
  24. })
  25. if err != nil {
  26. return nil, err
  27. }
  28. var hub *TCPHub
  29. if tlsConfig != nil {
  30. tlsListener := tls.NewListener(listener, tlsConfig)
  31. hub = &TCPHub{
  32. listener: tlsListener,
  33. connCallback: callback,
  34. }
  35. } else {
  36. hub = &TCPHub{
  37. listener: listener,
  38. connCallback: callback,
  39. }
  40. }
  41. go hub.start()
  42. return hub, nil
  43. }
  44. func (this *TCPHub) Close() {
  45. this.Lock()
  46. defer this.Unlock()
  47. this.accepting = false
  48. this.listener.Close()
  49. this.listener = nil
  50. }
  51. func (this *TCPHub) start() {
  52. this.accepting = true
  53. for this.accepting {
  54. this.Lock()
  55. if !this.accepting {
  56. this.Unlock()
  57. break
  58. }
  59. conn, err := this.listener.Accept()
  60. this.Unlock()
  61. if err != nil {
  62. if this.accepting {
  63. log.Warning("Listener: Failed to accept new TCP connection: ", err)
  64. }
  65. continue
  66. }
  67. go this.connCallback(&Connection{
  68. conn: conn,
  69. listener: this,
  70. })
  71. }
  72. }
  73. // @Private
  74. func (this *TCPHub) Recycle(conn net.Conn) {
  75. if this.accepting {
  76. go this.connCallback(&Connection{
  77. conn: conn,
  78. listener: this,
  79. })
  80. }
  81. }