func (this *VMessOutboundHandler) Dispatch(target v2net.Destination, payload *alloc.Buffer, ray ray.OutboundRay) error { defer ray.OutboundInput().Release() defer ray.OutboundOutput().Close() var rec *protocol.ServerSpec var conn internet.Connection err := retry.Timed(5, 100).On(func() error { rec = this.serverPicker.PickServer() rawConn, err := internet.Dial(this.meta.Address, rec.Destination(), this.meta.StreamSettings) if err != nil { return err } conn = rawConn return nil }) if err != nil { log.Error("VMess|Outbound: Failed to find an available destination:", err) return err } log.Info("VMess|Outbound: Tunneling request to ", target, " via ", rec.Destination()) command := protocol.RequestCommandTCP if target.IsUDP() { command = protocol.RequestCommandUDP } request := &protocol.RequestHeader{ Version: encoding.Version, User: rec.PickUser(), Command: command, Address: target.Address(), Port: target.Port(), Option: protocol.RequestOptionChunkStream, } defer conn.Close() conn.SetReusable(true) if conn.Reusable() { // Conn reuse may be disabled on transportation layer request.Option.Set(protocol.RequestOptionConnectionReuse) } input := ray.OutboundInput() output := ray.OutboundOutput() var requestFinish, responseFinish sync.Mutex requestFinish.Lock() responseFinish.Lock() session := encoding.NewClientSession(protocol.DefaultIDHash) go this.handleRequest(session, conn, request, payload, input, &requestFinish) go this.handleResponse(session, conn, request, rec.Destination(), output, &responseFinish) requestFinish.Lock() responseFinish.Lock() return nil }
func socks5UDPRequest(address v2net.Destination, payload []byte) []byte { request := make([]byte, 0, 1024) request = append(request, 0, 0, 0) request = appendAddress(request, address.Address()) request = address.Port().Bytes(request) request = append(request, payload...) return request }
// Private: Visible for testing. func (this *Router) ResolveIP(dest v2net.Destination) []v2net.Destination { ips := this.dnsServer.Get(dest.Address().Domain()) if len(ips) == 0 { return nil } dests := make([]v2net.Destination, len(ips)) for idx, ip := range ips { if dest.IsTCP() { dests[idx] = v2net.TCPDestination(v2net.IPAddress(ip), dest.Port()) } else { dests[idx] = v2net.UDPDestination(v2net.IPAddress(ip), dest.Port()) } } return dests }
func DialKCP(src v2net.Address, dest v2net.Destination) (internet.Connection, error) { udpDest := v2net.UDPDestination(dest.Address(), dest.Port()) log.Info("KCP|Dialer: Dialing KCP to ", udpDest) conn, err := internet.DialToDest(src, udpDest) if err != nil { log.Error("KCP|Dialer: Failed to dial to dest: ", err) return nil, err } cpip, err := effectiveConfig.GetAuthenticator() if err != nil { log.Error("KCP|Dialer: Failed to create authenticator: ", err) return nil, err } conv := uint16(atomic.AddUint32(&globalConv, 1)) session := NewConnection(conv, conn, conn.LocalAddr().(*net.UDPAddr), conn.RemoteAddr().(*net.UDPAddr), cpip) session.FetchInputFrom(conn) return session, nil }
func calcPto(dst v2net.Destination) string { if effectiveConfig.Pto != "" { return effectiveConfig.Pto } switch dst.Port().Value() { /* Since the value is not given explicitly, We are guessing it now. HTTP Port: 80 8080 8880 2052 2082 2086 2095 HTTPS Port: 443 2053 2083 2087 2096 8443 if the port you are using is not well-known, specify it to avoid this process. We will return "CRASH"turn "unknown" if we can't guess it, cause Dial to fail. */ case 80, 8080, 8880, 2052, 2082, 2086, 2095: return "ws" case 443, 2053, 2083, 2087, 2096, 8443: return "wss" default: return "unknown" } }
// Private: Visible for testing. func (this *FreedomConnection) ResolveIP(destination v2net.Destination) v2net.Destination { if !destination.Address().Family().IsDomain() { return destination } ips := this.dns.Get(destination.Address().Domain()) if len(ips) == 0 { log.Info("Freedom: DNS returns nil answer. Keep domain as is.") return destination } ip := ips[dice.Roll(len(ips))] var newDest v2net.Destination if destination.IsTCP() { newDest = v2net.TCPDestination(v2net.IPAddress(ip), destination.Port()) } else { newDest = v2net.UDPDestination(v2net.IPAddress(ip), destination.Port()) } log.Info("Freedom: Changing destination from ", destination, " to ", newDest) return newDest }
func (this *PortMatcher) Apply(dest v2net.Destination) bool { return this.port.Contains(dest.Port()) }
func (this *UDPHub) WriteTo(payload []byte, dest v2net.Destination) (int, error) { return this.conn.WriteToUDP(payload, &net.UDPAddr{ IP: dest.Address().IP(), Port: int(dest.Port()), }) }
func socks5Request(command byte, address v2net.Destination) []byte { request := []byte{socks5Version, command, 0} request = appendAddress(request, address.Address()) request = address.Port().Bytes(request) return request }