npc.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. package action
  2. import (
  3. "crypto/tls"
  4. "ehang.io/nps/lib/cert"
  5. "ehang.io/nps/lib/enet"
  6. "ehang.io/nps/lib/pb"
  7. "github.com/golang/protobuf/proto"
  8. "github.com/pkg/errors"
  9. "net"
  10. )
  11. type NpcAction struct {
  12. NpcId string `json:"npc_id" required:"true" placeholder:"npc id" zh_name:"客户端"`
  13. BridgeAddr string `json:"bridge_addr" placeholder:"127.0.0.1:8080" zh_name:"网桥地址"`
  14. UnixSocket bool `json:"unix_sock" placeholder:"" zh_name:"转发到unix socket"`
  15. networkTcp pb.ConnType
  16. tlsConfig *tls.Config
  17. connRequest *pb.ConnRequest
  18. DefaultAction
  19. }
  20. func (na *NpcAction) GetName() string {
  21. return "npc"
  22. }
  23. func (na *NpcAction) GetZhName() string {
  24. return "转发到客户端"
  25. }
  26. func (na *NpcAction) Init() error {
  27. if na.tlsConfig == nil {
  28. return errors.New("tls config is nil")
  29. }
  30. sn, err := cert.GetCertSnFromConfig(na.tlsConfig)
  31. if err != nil {
  32. return errors.Wrap(err, "get serial number")
  33. }
  34. na.connRequest = &pb.ConnRequest{Id: sn}
  35. na.networkTcp = pb.ConnType_tcp
  36. if na.UnixSocket {
  37. // just support unix
  38. na.networkTcp = pb.ConnType_unix
  39. }
  40. return nil
  41. }
  42. func (na *NpcAction) RunConnWithAddr(clientConn net.Conn, addr string) error {
  43. serverConn, err := na.GetServeConnWithAddr(addr)
  44. if err != nil {
  45. return err
  46. }
  47. na.startCopy(clientConn, serverConn)
  48. return nil
  49. }
  50. func (na *NpcAction) CanServe() bool {
  51. return true
  52. }
  53. func (na *NpcAction) GetServeConnWithAddr(addr string) (net.Conn, error) {
  54. return dialBridge(na, na.networkTcp, addr)
  55. }
  56. func (na *NpcAction) RunPacketConn(pc net.PacketConn) error {
  57. serverPacketConn, err := dialBridge(na, pb.ConnType_udp, "")
  58. if err != nil {
  59. return err
  60. }
  61. return na.startCopyPacketConn(pc, enet.NewTcpPacketConn(serverPacketConn))
  62. }
  63. func dialBridge(npc *NpcAction, connType pb.ConnType, addr string) (net.Conn, error) {
  64. tlsConn, err := tls.Dial("tcp", npc.BridgeAddr, npc.tlsConfig)
  65. if err != nil {
  66. return nil, errors.Wrap(err, "dial bridge tls")
  67. }
  68. cr := proto.Clone(npc.connRequest).(*pb.ConnRequest)
  69. cr.ConnType = &pb.ConnRequest_AppInfo{AppInfo: &pb.AppInfo{ConnType: connType, AppAddr: addr, NpcId: npc.NpcId}}
  70. if _, err = pb.WriteMessage(tlsConn, cr); err != nil {
  71. return nil, errors.Wrap(err, "write enet request")
  72. }
  73. return tlsConn, err
  74. }