point.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // Package point is a shell of V2Ray to run on various of systems.
  2. // Point server is a full functionality proxying system. It consists of an inbound and an outbound
  3. // connection, as well as any number of inbound and outbound detours. It provides a way internally
  4. // to route network packets.
  5. package point
  6. import (
  7. "github.com/v2ray/v2ray-core/app"
  8. "github.com/v2ray/v2ray-core/app/controller"
  9. "github.com/v2ray/v2ray-core/app/router"
  10. "github.com/v2ray/v2ray-core/common/log"
  11. v2net "github.com/v2ray/v2ray-core/common/net"
  12. "github.com/v2ray/v2ray-core/common/retry"
  13. "github.com/v2ray/v2ray-core/proxy"
  14. proxyrepo "github.com/v2ray/v2ray-core/proxy/repo"
  15. "github.com/v2ray/v2ray-core/transport/ray"
  16. )
  17. // Point shell of V2Ray.
  18. type Point struct {
  19. port v2net.Port
  20. ich proxy.InboundConnectionHandler
  21. och proxy.OutboundConnectionHandler
  22. idh []InboundDetourHandler
  23. taggedIdh map[string]InboundDetourHandler
  24. odh map[string]proxy.OutboundConnectionHandler
  25. router router.Router
  26. space *controller.SpaceController
  27. }
  28. // NewPoint returns a new Point server based on given configuration.
  29. // The server is not started at this point.
  30. func NewPoint(pConfig *Config) (*Point, error) {
  31. var vpoint = new(Point)
  32. vpoint.port = pConfig.Port
  33. if pConfig.LogConfig != nil {
  34. logConfig := pConfig.LogConfig
  35. if len(logConfig.AccessLog) > 0 {
  36. err := log.InitAccessLogger(logConfig.AccessLog)
  37. if err != nil {
  38. return nil, err
  39. }
  40. }
  41. if len(logConfig.ErrorLog) > 0 {
  42. err := log.InitErrorLogger(logConfig.ErrorLog)
  43. if err != nil {
  44. return nil, err
  45. }
  46. }
  47. log.SetLogLevel(logConfig.LogLevel)
  48. }
  49. vpoint.space = controller.New()
  50. vpoint.space.Bind(vpoint)
  51. ichConfig := pConfig.InboundConfig.Settings
  52. ich, err := proxyrepo.CreateInboundConnectionHandler(pConfig.InboundConfig.Protocol, vpoint.space.ForContext("vpoint-default-inbound"), ichConfig)
  53. if err != nil {
  54. log.Error("Failed to create inbound connection handler: ", err)
  55. return nil, err
  56. }
  57. vpoint.ich = ich
  58. ochConfig := pConfig.OutboundConfig.Settings
  59. och, err := proxyrepo.CreateOutboundConnectionHandler(pConfig.OutboundConfig.Protocol, vpoint.space.ForContext("vpoint-default-outbound"), ochConfig)
  60. if err != nil {
  61. log.Error("Failed to create outbound connection handler: ", err)
  62. return nil, err
  63. }
  64. vpoint.och = och
  65. vpoint.taggedIdh = make(map[string]InboundDetourHandler)
  66. detours := pConfig.InboundDetours
  67. if len(detours) > 0 {
  68. vpoint.idh = make([]InboundDetourHandler, len(detours))
  69. for idx, detourConfig := range detours {
  70. allocConfig := detourConfig.Allocation
  71. var detourHandler InboundDetourHandler
  72. switch allocConfig.Strategy {
  73. case AllocationStrategyAlways:
  74. dh, err := NewInboundDetourHandlerAlways(vpoint.space.ForContext(detourConfig.Tag), detourConfig)
  75. if err != nil {
  76. log.Error("Point: Failed to create detour handler: ", err)
  77. return nil, BadConfiguration
  78. }
  79. detourHandler = dh
  80. case AllocationStrategyRandom:
  81. dh, err := NewInboundDetourHandlerDynamic(vpoint.space.ForContext(detourConfig.Tag), detourConfig)
  82. if err != nil {
  83. log.Error("Point: Failed to create detour handler: ", err)
  84. return nil, BadConfiguration
  85. }
  86. detourHandler = dh
  87. default:
  88. log.Error("Point: Unknown allocation strategy: ", allocConfig.Strategy)
  89. return nil, BadConfiguration
  90. }
  91. vpoint.idh[idx] = detourHandler
  92. if len(detourConfig.Tag) > 0 {
  93. vpoint.taggedIdh[detourConfig.Tag] = detourHandler
  94. }
  95. }
  96. }
  97. outboundDetours := pConfig.OutboundDetours
  98. if len(outboundDetours) > 0 {
  99. vpoint.odh = make(map[string]proxy.OutboundConnectionHandler)
  100. for _, detourConfig := range outboundDetours {
  101. detourHandler, err := proxyrepo.CreateOutboundConnectionHandler(detourConfig.Protocol, vpoint.space.ForContext(detourConfig.Tag), detourConfig.Settings)
  102. if err != nil {
  103. log.Error("Failed to create detour outbound connection handler: ", err)
  104. return nil, err
  105. }
  106. vpoint.odh[detourConfig.Tag] = detourHandler
  107. }
  108. }
  109. routerConfig := pConfig.RouterConfig
  110. if routerConfig != nil {
  111. r, err := router.CreateRouter(routerConfig.Strategy, routerConfig.Settings)
  112. if err != nil {
  113. log.Error("Failed to create router: ", err)
  114. return nil, BadConfiguration
  115. }
  116. vpoint.router = r
  117. }
  118. return vpoint, nil
  119. }
  120. func (this *Point) Close() {
  121. this.ich.Close()
  122. for _, idh := range this.idh {
  123. idh.Close()
  124. }
  125. }
  126. // Start starts the Point server, and return any error during the process.
  127. // In the case of any errors, the state of the server is unpredicatable.
  128. func (this *Point) Start() error {
  129. if this.port <= 0 {
  130. log.Error("Invalid port ", this.port)
  131. return BadConfiguration
  132. }
  133. err := retry.Timed(100 /* times */, 100 /* ms */).On(func() error {
  134. err := this.ich.Listen(this.port)
  135. if err != nil {
  136. return err
  137. }
  138. log.Warning("Point server started on port ", this.port)
  139. return nil
  140. })
  141. if err != nil {
  142. return err
  143. }
  144. for _, detourHandler := range this.idh {
  145. err := detourHandler.Start()
  146. if err != nil {
  147. return err
  148. }
  149. }
  150. return nil
  151. }
  152. // Dispatches a Packet to an OutboundConnection.
  153. // The packet will be passed through the router (if configured), and then sent to an outbound
  154. // connection with matching tag.
  155. func (this *Point) DispatchToOutbound(context app.Context, packet v2net.Packet) ray.InboundRay {
  156. direct := ray.NewRay()
  157. dest := packet.Destination()
  158. dispatcher := this.och
  159. if this.router != nil {
  160. if tag, err := this.router.TakeDetour(dest); err == nil {
  161. if handler, found := this.odh[tag]; found {
  162. log.Info("Point: Taking detour [", tag, "] for [", dest, "]", tag, dest)
  163. dispatcher = handler
  164. }
  165. }
  166. }
  167. go this.FilterPacketAndDispatch(packet, direct, dispatcher)
  168. return direct
  169. }
  170. func (this *Point) FilterPacketAndDispatch(packet v2net.Packet, link ray.OutboundRay, dispatcher proxy.OutboundConnectionHandler) {
  171. // Filter empty packets
  172. chunk := packet.Chunk()
  173. moreChunks := packet.MoreChunks()
  174. changed := false
  175. for chunk == nil && moreChunks {
  176. changed = true
  177. chunk, moreChunks = <-link.OutboundInput()
  178. }
  179. if chunk == nil && !moreChunks {
  180. log.Info("Point: No payload to dispatch, stopping dispatching now.")
  181. close(link.OutboundOutput())
  182. return
  183. }
  184. if changed {
  185. packet = v2net.NewPacket(packet.Destination(), chunk, moreChunks)
  186. }
  187. dispatcher.Dispatch(packet, link)
  188. }
  189. func (this *Point) GetHandler(context app.Context, tag string) (proxy.InboundConnectionHandler, int) {
  190. handler, found := this.taggedIdh[tag]
  191. if !found {
  192. return nil, 0
  193. }
  194. return handler.GetConnectionHandler()
  195. }