p2p.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package proxy
  2. import (
  3. "net"
  4. "strings"
  5. "time"
  6. "ehang.io/nps/lib/common"
  7. "github.com/astaxie/beego/logs"
  8. )
  9. type P2PServer struct {
  10. BaseServer
  11. p2pPort int
  12. p2p map[string]*p2p
  13. listener *net.UDPConn
  14. }
  15. type p2p struct {
  16. visitorAddr *net.UDPAddr
  17. providerAddr *net.UDPAddr
  18. }
  19. func NewP2PServer(p2pPort int) *P2PServer {
  20. return &P2PServer{
  21. p2pPort: p2pPort,
  22. p2p: make(map[string]*p2p),
  23. }
  24. }
  25. func (s *P2PServer) Start() error {
  26. logs.Info("start p2p server port", s.p2pPort)
  27. var err error
  28. s.listener, err = net.ListenUDP("udp", &net.UDPAddr{net.ParseIP("0.0.0.0"), s.p2pPort, ""})
  29. if err != nil {
  30. return err
  31. }
  32. for {
  33. buf := common.BufPoolUdp.Get().([]byte)
  34. n, addr, err := s.listener.ReadFromUDP(buf)
  35. if err != nil {
  36. if strings.Contains(err.Error(), "use of closed network connection") {
  37. break
  38. }
  39. continue
  40. }
  41. go s.handleP2P(addr, string(buf[:n]))
  42. }
  43. return nil
  44. }
  45. func (s *P2PServer) handleP2P(addr *net.UDPAddr, str string) {
  46. var (
  47. v *p2p
  48. ok bool
  49. )
  50. arr := strings.Split(str, common.CONN_DATA_SEQ)
  51. if len(arr) < 2 {
  52. return
  53. }
  54. if v, ok = s.p2p[arr[0]]; !ok {
  55. v = new(p2p)
  56. s.p2p[arr[0]] = v
  57. }
  58. logs.Trace("new p2p connection ,role %s , password %s ,local address %s", arr[1], arr[0], addr.String())
  59. if arr[1] == common.WORK_P2P_VISITOR {
  60. v.visitorAddr = addr
  61. for i := 20; i > 0; i-- {
  62. if v.providerAddr != nil {
  63. s.listener.WriteTo([]byte(v.providerAddr.String()), v.visitorAddr)
  64. s.listener.WriteTo([]byte(v.visitorAddr.String()), v.providerAddr)
  65. break
  66. }
  67. time.Sleep(time.Second)
  68. }
  69. delete(s.p2p, arr[0])
  70. } else {
  71. v.providerAddr = addr
  72. }
  73. }