| 
									
										
										
										
											2015-12-04 22:53:31 +01:00
										 |  |  | // Package point is a shell of V2Ray to run on various of systems. | 
					
						
							|  |  |  | // Point server is a full functionality proxying system. It consists of an inbound and an outbound | 
					
						
							|  |  |  | // connection, as well as any number of inbound and outbound detours. It provides a way internally | 
					
						
							|  |  |  | // to route network packets. | 
					
						
							| 
									
										
										
										
											2015-10-14 14:51:19 +02:00
										 |  |  | package point | 
					
						
							| 
									
										
										
										
											2015-09-05 17:48:38 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2015-12-05 22:55:45 +01:00
										 |  |  | 	"github.com/v2ray/v2ray-core/app" | 
					
						
							| 
									
										
										
										
											2016-01-31 17:01:28 +01:00
										 |  |  | 	"github.com/v2ray/v2ray-core/app/dispatcher" | 
					
						
							|  |  |  | 	"github.com/v2ray/v2ray-core/app/proxyman" | 
					
						
							| 
									
										
										
										
											2015-11-22 17:41:52 +01:00
										 |  |  | 	"github.com/v2ray/v2ray-core/app/router" | 
					
						
							| 
									
										
										
										
											2015-09-20 00:50:21 +02:00
										 |  |  | 	"github.com/v2ray/v2ray-core/common/log" | 
					
						
							| 
									
										
										
										
											2015-09-19 23:54:36 +02:00
										 |  |  | 	v2net "github.com/v2ray/v2ray-core/common/net" | 
					
						
							| 
									
										
										
										
											2015-10-13 12:27:50 +02:00
										 |  |  | 	"github.com/v2ray/v2ray-core/common/retry" | 
					
						
							| 
									
										
										
										
											2016-01-01 23:44:11 +01:00
										 |  |  | 	"github.com/v2ray/v2ray-core/proxy" | 
					
						
							| 
									
										
										
										
											2016-01-02 23:32:18 +01:00
										 |  |  | 	proxyrepo "github.com/v2ray/v2ray-core/proxy/repo" | 
					
						
							| 
									
										
										
										
											2015-10-14 14:51:19 +02:00
										 |  |  | 	"github.com/v2ray/v2ray-core/transport/ray" | 
					
						
							| 
									
										
										
										
											2015-09-05 17:48:38 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-04 22:53:31 +01:00
										 |  |  | // Point shell of V2Ray. | 
					
						
							| 
									
										
										
										
											2015-09-12 22:11:54 +02:00
										 |  |  | type Point struct { | 
					
						
							| 
									
										
										
										
											2016-01-21 01:40:52 +01:00
										 |  |  | 	port      v2net.Port | 
					
						
							| 
									
										
										
										
											2016-01-25 17:18:24 +01:00
										 |  |  | 	ich       proxy.InboundHandler | 
					
						
							|  |  |  | 	och       proxy.OutboundHandler | 
					
						
							| 
									
										
										
										
											2016-01-21 01:40:52 +01:00
										 |  |  | 	idh       []InboundDetourHandler | 
					
						
							|  |  |  | 	taggedIdh map[string]InboundDetourHandler | 
					
						
							| 
									
										
										
										
											2016-01-25 17:18:24 +01:00
										 |  |  | 	odh       map[string]proxy.OutboundHandler | 
					
						
							| 
									
										
										
										
											2016-01-21 01:40:52 +01:00
										 |  |  | 	router    router.Router | 
					
						
							| 
									
										
										
										
											2016-01-31 17:01:28 +01:00
										 |  |  | 	space     *app.SpaceController | 
					
						
							| 
									
										
										
										
											2015-09-05 17:48:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-12 22:11:54 +02:00
										 |  |  | // NewPoint returns a new Point server based on given configuration. | 
					
						
							| 
									
										
										
										
											2015-09-07 12:00:46 +02:00
										 |  |  | // The server is not started at this point. | 
					
						
							| 
									
										
										
										
											2016-01-17 21:43:10 +01:00
										 |  |  | func NewPoint(pConfig *Config) (*Point, error) { | 
					
						
							| 
									
										
										
										
											2015-09-12 22:11:54 +02:00
										 |  |  | 	var vpoint = new(Point) | 
					
						
							| 
									
										
										
										
											2016-01-17 21:43:10 +01:00
										 |  |  | 	vpoint.port = pConfig.Port | 
					
						
							| 
									
										
										
										
											2015-09-12 11:51:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-17 21:43:10 +01:00
										 |  |  | 	if pConfig.LogConfig != nil { | 
					
						
							|  |  |  | 		logConfig := pConfig.LogConfig | 
					
						
							|  |  |  | 		if len(logConfig.AccessLog) > 0 { | 
					
						
							|  |  |  | 			err := log.InitAccessLogger(logConfig.AccessLog) | 
					
						
							| 
									
										
										
										
											2015-12-05 21:10:14 +01:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-17 21:43:10 +01:00
										 |  |  | 		if len(logConfig.ErrorLog) > 0 { | 
					
						
							|  |  |  | 			err := log.InitErrorLogger(logConfig.ErrorLog) | 
					
						
							| 
									
										
										
										
											2015-12-05 21:10:14 +01:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-17 21:43:10 +01:00
										 |  |  | 		log.SetLogLevel(logConfig.LogLevel) | 
					
						
							| 
									
										
										
										
											2015-12-05 21:10:14 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-31 17:01:28 +01:00
										 |  |  | 	vpoint.space = app.NewController() | 
					
						
							|  |  |  | 	vpoint.space.Bind(dispatcher.APP_ID, vpoint) | 
					
						
							|  |  |  | 	vpoint.space.Bind(proxyman.APP_ID_INBOUND_MANAGER, vpoint) | 
					
						
							| 
									
										
										
										
											2015-12-05 22:55:45 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-17 21:43:10 +01:00
										 |  |  | 	ichConfig := pConfig.InboundConfig.Settings | 
					
						
							| 
									
										
										
										
											2016-01-25 17:23:10 +01:00
										 |  |  | 	ich, err := proxyrepo.CreateInboundHandler(pConfig.InboundConfig.Protocol, vpoint.space.ForContext("vpoint-default-inbound"), ichConfig) | 
					
						
							| 
									
										
										
										
											2015-10-07 00:30:44 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2016-01-18 12:24:33 +01:00
										 |  |  | 		log.Error("Failed to create inbound connection handler: ", err) | 
					
						
							| 
									
										
										
										
											2015-10-07 00:30:44 +02:00
										 |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	vpoint.ich = ich | 
					
						
							| 
									
										
										
										
											2015-09-12 11:51:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-17 21:43:10 +01:00
										 |  |  | 	ochConfig := pConfig.OutboundConfig.Settings | 
					
						
							| 
									
										
										
										
											2016-01-25 17:23:10 +01:00
										 |  |  | 	och, err := proxyrepo.CreateOutboundHandler(pConfig.OutboundConfig.Protocol, vpoint.space.ForContext("vpoint-default-outbound"), ochConfig) | 
					
						
							| 
									
										
										
										
											2015-10-07 00:30:44 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2016-01-18 12:24:33 +01:00
										 |  |  | 		log.Error("Failed to create outbound connection handler: ", err) | 
					
						
							| 
									
										
										
										
											2015-10-07 00:30:44 +02:00
										 |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	vpoint.och = och | 
					
						
							| 
									
										
										
										
											2015-09-11 00:24:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-21 01:40:52 +01:00
										 |  |  | 	vpoint.taggedIdh = make(map[string]InboundDetourHandler) | 
					
						
							| 
									
										
										
										
											2016-01-17 21:43:10 +01:00
										 |  |  | 	detours := pConfig.InboundDetours | 
					
						
							| 
									
										
										
										
											2015-11-01 00:11:41 +01:00
										 |  |  | 	if len(detours) > 0 { | 
					
						
							| 
									
										
										
										
											2016-01-21 01:40:52 +01:00
										 |  |  | 		vpoint.idh = make([]InboundDetourHandler, len(detours)) | 
					
						
							| 
									
										
										
										
											2015-11-01 00:11:41 +01:00
										 |  |  | 		for idx, detourConfig := range detours { | 
					
						
							| 
									
										
										
										
											2016-01-21 01:40:52 +01:00
										 |  |  | 			allocConfig := detourConfig.Allocation | 
					
						
							|  |  |  | 			var detourHandler InboundDetourHandler | 
					
						
							|  |  |  | 			switch allocConfig.Strategy { | 
					
						
							|  |  |  | 			case AllocationStrategyAlways: | 
					
						
							|  |  |  | 				dh, err := NewInboundDetourHandlerAlways(vpoint.space.ForContext(detourConfig.Tag), detourConfig) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					log.Error("Point: Failed to create detour handler: ", err) | 
					
						
							| 
									
										
										
										
											2016-01-30 12:12:57 +01:00
										 |  |  | 					return nil, ErrorBadConfiguration | 
					
						
							| 
									
										
										
										
											2016-01-21 01:40:52 +01:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				detourHandler = dh | 
					
						
							| 
									
										
										
										
											2016-01-22 16:25:01 +01:00
										 |  |  | 			case AllocationStrategyRandom: | 
					
						
							|  |  |  | 				dh, err := NewInboundDetourHandlerDynamic(vpoint.space.ForContext(detourConfig.Tag), detourConfig) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					log.Error("Point: Failed to create detour handler: ", err) | 
					
						
							| 
									
										
										
										
											2016-01-30 12:12:57 +01:00
										 |  |  | 					return nil, ErrorBadConfiguration | 
					
						
							| 
									
										
										
										
											2016-01-22 16:25:01 +01:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				detourHandler = dh | 
					
						
							| 
									
										
										
										
											2016-01-21 01:40:52 +01:00
										 |  |  | 			default: | 
					
						
							|  |  |  | 				log.Error("Point: Unknown allocation strategy: ", allocConfig.Strategy) | 
					
						
							| 
									
										
										
										
											2016-01-30 12:12:57 +01:00
										 |  |  | 				return nil, ErrorBadConfiguration | 
					
						
							| 
									
										
										
										
											2015-11-01 00:11:41 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			vpoint.idh[idx] = detourHandler | 
					
						
							| 
									
										
										
										
											2016-01-21 01:40:52 +01:00
										 |  |  | 			if len(detourConfig.Tag) > 0 { | 
					
						
							|  |  |  | 				vpoint.taggedIdh[detourConfig.Tag] = detourHandler | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-11-01 00:11:41 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-17 21:43:10 +01:00
										 |  |  | 	outboundDetours := pConfig.OutboundDetours | 
					
						
							| 
									
										
										
										
											2015-11-22 17:41:52 +01:00
										 |  |  | 	if len(outboundDetours) > 0 { | 
					
						
							| 
									
										
										
										
											2016-01-25 17:18:24 +01:00
										 |  |  | 		vpoint.odh = make(map[string]proxy.OutboundHandler) | 
					
						
							| 
									
										
										
										
											2015-11-22 17:41:52 +01:00
										 |  |  | 		for _, detourConfig := range outboundDetours { | 
					
						
							| 
									
										
										
										
											2016-01-25 17:23:43 +01:00
										 |  |  | 			detourHandler, err := proxyrepo.CreateOutboundHandler(detourConfig.Protocol, vpoint.space.ForContext(detourConfig.Tag), detourConfig.Settings) | 
					
						
							| 
									
										
										
										
											2015-11-22 17:41:52 +01:00
										 |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2016-01-18 12:24:33 +01:00
										 |  |  | 				log.Error("Failed to create detour outbound connection handler: ", err) | 
					
						
							| 
									
										
										
										
											2015-11-22 17:41:52 +01:00
										 |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-01-17 21:43:10 +01:00
										 |  |  | 			vpoint.odh[detourConfig.Tag] = detourHandler | 
					
						
							| 
									
										
										
										
											2015-11-22 17:41:52 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-17 21:43:10 +01:00
										 |  |  | 	routerConfig := pConfig.RouterConfig | 
					
						
							| 
									
										
										
										
											2015-11-22 17:41:52 +01:00
										 |  |  | 	if routerConfig != nil { | 
					
						
							| 
									
										
										
										
											2016-01-17 15:20:49 +00:00
										 |  |  | 		r, err := router.CreateRouter(routerConfig.Strategy, routerConfig.Settings) | 
					
						
							| 
									
										
										
										
											2015-11-22 17:41:52 +01:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2016-01-18 12:24:33 +01:00
										 |  |  | 			log.Error("Failed to create router: ", err) | 
					
						
							| 
									
										
										
										
											2016-01-30 12:12:57 +01:00
										 |  |  | 			return nil, ErrorBadConfiguration | 
					
						
							| 
									
										
										
										
											2015-11-22 17:41:52 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		vpoint.router = r | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-06 22:10:42 +02:00
										 |  |  | 	return vpoint, nil | 
					
						
							| 
									
										
										
										
											2015-09-05 17:48:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-04 00:33:25 +01:00
										 |  |  | func (this *Point) Close() { | 
					
						
							|  |  |  | 	this.ich.Close() | 
					
						
							|  |  |  | 	for _, idh := range this.idh { | 
					
						
							|  |  |  | 		idh.Close() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-12 22:11:54 +02:00
										 |  |  | // Start starts the Point server, and return any error during the process. | 
					
						
							| 
									
										
										
										
											2015-09-07 12:00:46 +02:00
										 |  |  | // In the case of any errors, the state of the server is unpredicatable. | 
					
						
							| 
									
										
										
										
											2015-11-27 12:29:20 +01:00
										 |  |  | func (this *Point) Start() error { | 
					
						
							|  |  |  | 	if this.port <= 0 { | 
					
						
							| 
									
										
										
										
											2016-01-18 12:24:33 +01:00
										 |  |  | 		log.Error("Invalid port ", this.port) | 
					
						
							| 
									
										
										
										
											2016-01-30 12:12:57 +01:00
										 |  |  | 		return ErrorBadConfiguration | 
					
						
							| 
									
										
										
										
											2015-09-06 22:10:42 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-09-22 18:11:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-01 00:11:41 +01:00
										 |  |  | 	err := retry.Timed(100 /* times */, 100 /* ms */).On(func() error { | 
					
						
							| 
									
										
										
										
											2015-11-27 12:29:20 +01:00
										 |  |  | 		err := this.ich.Listen(this.port) | 
					
						
							| 
									
										
										
										
											2015-11-01 00:11:41 +01:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							| 
									
										
										
										
											2015-10-14 01:15:29 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-01-18 12:24:33 +01:00
										 |  |  | 		log.Warning("Point server started on port ", this.port) | 
					
						
							| 
									
										
										
										
											2015-11-01 00:11:41 +01:00
										 |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2015-10-13 12:27:50 +02:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2015-11-01 00:11:41 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-27 12:29:20 +01:00
										 |  |  | 	for _, detourHandler := range this.idh { | 
					
						
							| 
									
										
										
										
											2015-11-01 00:11:41 +01:00
										 |  |  | 		err := detourHandler.Start() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2015-09-06 22:10:42 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-09-11 00:24:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-03 14:12:47 +00:00
										 |  |  | // Dispatches a Packet to an OutboundConnection. | 
					
						
							|  |  |  | // The packet will be passed through the router (if configured), and then sent to an outbound | 
					
						
							|  |  |  | // connection with matching tag. | 
					
						
							| 
									
										
										
										
											2015-12-10 23:55:39 +01:00
										 |  |  | func (this *Point) DispatchToOutbound(context app.Context, packet v2net.Packet) ray.InboundRay { | 
					
						
							| 
									
										
										
										
											2015-10-14 14:51:19 +02:00
										 |  |  | 	direct := ray.NewRay() | 
					
						
							| 
									
										
										
										
											2015-11-22 17:41:52 +01:00
										 |  |  | 	dest := packet.Destination() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-05 21:54:23 +01:00
										 |  |  | 	dispatcher := this.och | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-27 12:29:20 +01:00
										 |  |  | 	if this.router != nil { | 
					
						
							| 
									
										
										
										
											2016-01-11 12:35:36 +01:00
										 |  |  | 		if tag, err := this.router.TakeDetour(dest); err == nil { | 
					
						
							|  |  |  | 			if handler, found := this.odh[tag]; found { | 
					
						
							| 
									
										
										
										
											2016-01-18 12:24:33 +01:00
										 |  |  | 				log.Info("Point: Taking detour [", tag, "] for [", dest, "]", tag, dest) | 
					
						
							| 
									
										
										
										
											2016-01-05 21:54:23 +01:00
										 |  |  | 				dispatcher = handler | 
					
						
							| 
									
										
										
										
											2016-01-30 11:45:33 +01:00
										 |  |  | 			} else { | 
					
						
							|  |  |  | 				log.Warning("Point: Unable to find routing destination: ", tag) | 
					
						
							| 
									
										
										
										
											2015-11-22 17:41:52 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-05 21:54:23 +01:00
										 |  |  | 	go this.FilterPacketAndDispatch(packet, direct, dispatcher) | 
					
						
							| 
									
										
										
										
											2015-10-14 14:51:19 +02:00
										 |  |  | 	return direct | 
					
						
							| 
									
										
										
										
											2015-09-11 00:24:18 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-01-05 12:08:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-25 17:18:24 +01:00
										 |  |  | func (this *Point) FilterPacketAndDispatch(packet v2net.Packet, link ray.OutboundRay, dispatcher proxy.OutboundHandler) { | 
					
						
							| 
									
										
										
										
											2016-01-05 12:08:16 +01:00
										 |  |  | 	// Filter empty packets | 
					
						
							|  |  |  | 	chunk := packet.Chunk() | 
					
						
							|  |  |  | 	moreChunks := packet.MoreChunks() | 
					
						
							|  |  |  | 	changed := false | 
					
						
							|  |  |  | 	for chunk == nil && moreChunks { | 
					
						
							|  |  |  | 		changed = true | 
					
						
							|  |  |  | 		chunk, moreChunks = <-link.OutboundInput() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if chunk == nil && !moreChunks { | 
					
						
							| 
									
										
										
										
											2016-01-18 11:41:02 +01:00
										 |  |  | 		log.Info("Point: No payload to dispatch, stopping dispatching now.") | 
					
						
							| 
									
										
										
										
											2016-01-05 12:08:16 +01:00
										 |  |  | 		close(link.OutboundOutput()) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if changed { | 
					
						
							|  |  |  | 		packet = v2net.NewPacket(packet.Destination(), chunk, moreChunks) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dispatcher.Dispatch(packet, link) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-01-21 01:40:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-25 17:18:24 +01:00
										 |  |  | func (this *Point) GetHandler(context app.Context, tag string) (proxy.InboundHandler, int) { | 
					
						
							| 
									
										
										
										
											2016-01-21 16:22:56 +00:00
										 |  |  | 	handler, found := this.taggedIdh[tag] | 
					
						
							|  |  |  | 	if !found { | 
					
						
							| 
									
										
										
										
											2016-01-30 11:45:33 +01:00
										 |  |  | 		log.Warning("Point: Unable to find an inbound handler with tag: ", tag) | 
					
						
							| 
									
										
										
										
											2016-01-21 16:22:56 +00:00
										 |  |  | 		return nil, 0 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return handler.GetConnectionHandler() | 
					
						
							| 
									
										
										
										
											2016-01-21 01:40:52 +01:00
										 |  |  | } |