func ListenUDP(address v2net.Address, port v2net.Port, option ListenOption) (*UDPHub, error) { if option.Concurrency < 1 { option.Concurrency = 1 } udpConn, err := net.ListenUDP("udp", &net.UDPAddr{ IP: address.IP(), Port: int(port), }) if err != nil { return nil, err } if option.ReceiveOriginalDest { fd, err := internal.GetSysFd(udpConn) if err != nil { log.Warning("UDP|Listener: Failed to get fd: ", err) return nil, err } err = SetOriginalDestOptions(fd) if err != nil { log.Warning("UDP|Listener: Failed to set socket options: ", err) return nil, err } } hub := &UDPHub{ conn: udpConn, queue: NewUDPPayloadQueue(option), option: option, cancel: signal.NewCloseSignal(), } go hub.start() return hub, nil }
func (s *Server) Process(ctx context.Context, network v2net.Network, conn internet.Connection) error { conn.SetReusable(false) timedReader := v2net.NewTimeOutReader(s.config.Timeout, conn) reader := bufio.OriginalReaderSize(timedReader, 2048) request, err := http.ReadRequest(reader) if err != nil { if errors.Cause(err) != io.EOF { log.Warning("HTTP: Failed to read http request: ", err) } return err } log.Info("HTTP: Request to Method [", request.Method, "] Host [", request.Host, "] with URL [", request.URL, "]") defaultPort := v2net.Port(80) if strings.ToLower(request.URL.Scheme) == "https" { defaultPort = v2net.Port(443) } host := request.Host if len(host) == 0 { host = request.URL.Host } dest, err := parseHost(host, defaultPort) if err != nil { log.Warning("HTTP: Malformed proxy host (", host, "): ", err) return err } log.Access(conn.RemoteAddr(), request.URL, log.AccessAccepted, "") ctx = proxy.ContextWithDestination(ctx, dest) if strings.ToUpper(request.Method) == "CONNECT" { return s.handleConnect(ctx, request, reader, conn) } else { return s.handlePlainHTTP(ctx, request, reader, conn) } }
func ListenUDP(address v2net.Address, port v2net.Port, option ListenOption) (*UDPHub, error) { udpConn, err := net.ListenUDP("udp", &net.UDPAddr{ IP: address.IP(), Port: int(port), }) if err != nil { return nil, err } if option.ReceiveOriginalDest { fd, err := internal.GetSysFd(udpConn) if err != nil { log.Warning("UDP|Listener: Failed to get fd: ", err) return nil, err } err = SetOriginalDestOptions(fd) if err != nil { log.Warning("UDP|Listener: Failed to set socket options: ", err) return nil, err } } hub := &UDPHub{ conn: udpConn, option: option, } go hub.start() return hub, nil }
func parseIP(s string) *router.CIDR { var addr, mask string i := strings.Index(s, "/") if i < 0 { addr = s } else { addr = s[:i] mask = s[i+1:] } ip := v2net.ParseAddress(addr) switch ip.Family() { case v2net.AddressFamilyIPv4: bits := uint32(32) if len(mask) > 0 { bits64, err := strconv.ParseUint(mask, 10, 32) if err != nil { return nil } bits = uint32(bits64) } if bits > 32 { log.Warning("Router: invalid network mask: ", bits) return nil } return &router.CIDR{ Ip: []byte(ip.IP()), Prefix: bits, } case v2net.AddressFamilyIPv6: bits := uint32(128) if len(mask) > 0 { bits64, err := strconv.ParseUint(mask, 10, 32) if err != nil { return nil } bits = uint32(bits64) } if bits > 128 { log.Warning("Router: invalid network mask: ", bits) return nil } return &router.CIDR{ Ip: []byte(ip.IP()), Prefix: bits, } default: log.Warning("Router: unsupported address: ", s) return nil } }
func (v *VMessInboundHandler) generateCommand(ctx context.Context, request *protocol.RequestHeader) protocol.ResponseCommand { if v.detours != nil { tag := v.detours.To if v.inboundHandlerManager != nil { handler, err := v.inboundHandlerManager.GetHandler(ctx, tag) if err != nil { log.Warning("VMess|Inbound: Failed to get detour handler: ", tag, err) return nil } proxyHandler, port, availableMin := handler.GetRandomInboundProxy() inboundHandler, ok := proxyHandler.(*VMessInboundHandler) if ok { if availableMin > 255 { availableMin = 255 } log.Info("VMessIn: Pick detour handler for port ", port, " for ", availableMin, " minutes.") user := inboundHandler.GetUser(request.User.Email) if user == nil { return nil } account, _ := user.GetTypedAccount() return &protocol.CommandSwitchAccount{ Port: port, ID: account.(*vmess.InternalAccount).ID.UUID(), AlterIds: uint16(len(account.(*vmess.InternalAccount).AlterIDs)), Level: user.Level, ValidMin: byte(availableMin), } } } } return nil }
func Dial(src v2net.Address, dest v2net.Destination, options internet.DialerOptions) (internet.Connection, error) { log.Info("WebSocket|Dailer: Creating connection to ", dest) if src == nil { src = v2net.AnyIP } networkSettings, err := options.Stream.GetEffectiveNetworkSettings() if err != nil { return nil, err } wsSettings := networkSettings.(*Config) id := src.String() + "-" + dest.NetAddr() var conn *wsconn if dest.Network == v2net.Network_TCP && wsSettings.ConnectionReuse.IsEnabled() { connt := globalCache.Get(id) if connt != nil { conn = connt.(*wsconn) } } if conn == nil { var err error conn, err = wsDial(src, dest, options) if err != nil { log.Warning("WebSocket|Dialer: Dial failed: ", err) return nil, err } } return NewConnection(id, conn, globalCache, wsSettings), nil }
func (this *DefaultDispatcher) DispatchToOutbound(meta *proxy.InboundHandlerMeta, session *proxy.SessionInfo) ray.InboundRay { direct := ray.NewRay() dispatcher := this.ohm.GetDefaultHandler() destination := session.Destination if this.router != nil { if tag, err := this.router.TakeDetour(destination); err == nil { if handler := this.ohm.GetHandler(tag); handler != nil { log.Info("DefaultDispatcher: Taking detour [", tag, "] for [", destination, "].") dispatcher = handler } else { log.Warning("DefaultDispatcher: Nonexisting tag: ", tag) } } else { log.Info("DefaultDispatcher: Default route for ", destination) } } if meta.AllowPassiveConnection { go dispatcher.Dispatch(destination, alloc.NewLocalBuffer(32).Clear(), direct) } else { go this.FilterPacketAndDispatch(destination, direct, dispatcher) } return direct }
// Start starts the Point server, and return any error during the process. // In the case of any errors, the state of the server is unpredicatable. func (this *Point) Start() error { if this.port <= 0 { log.Error("Point: Invalid port ", this.port) return common.ErrBadConfiguration } err := retry.Timed(100 /* times */, 100 /* ms */).On(func() error { err := this.ich.Start() if err != nil { return err } log.Warning("Point: started on port ", this.port) return nil }) if err != nil { return err } for _, detourHandler := range this.idh { err := detourHandler.Start() if err != nil { return err } } return nil }
func ListenTCP(address v2net.Address, port v2net.Port, callback ConnectionHandler, settings *StreamConfig) (*TCPHub, error) { var listener Listener var err error options := ListenOptions{ Stream: settings, } switch settings.Network { case v2net.Network_TCP: listener, err = TCPListenFunc(address, port, options) case v2net.Network_KCP: listener, err = KCPListenFunc(address, port, options) case v2net.Network_WebSocket: listener, err = WSListenFunc(address, port, options) case v2net.Network_RawTCP: listener, err = RawTCPListenFunc(address, port, options) default: log.Error("Internet|Listener: Unknown stream type: ", settings.Network) err = ErrUnsupportedStreamType } if err != nil { log.Warning("Internet|Listener: Failed to listen on ", address, ":", port) return nil, err } hub := &TCPHub{ listener: listener, connCallback: callback, } go hub.start() return hub, nil }
func (v *Server) handleConnection(connection internet.Connection) { defer connection.Close() timedReader := v2net.NewTimeOutReader(v.config.Timeout, connection) reader := bufio.NewReader(timedReader) defer reader.Release() writer := bufio.NewWriter(connection) defer writer.Release() auth, auth4, err := protocol.ReadAuthentication(reader) if err != nil && errors.Cause(err) != protocol.Socks4Downgrade { if errors.Cause(err) != io.EOF { log.Warning("Socks: failed to read authentication: ", err) } return } clientAddr := v2net.DestinationFromAddr(connection.RemoteAddr()) if err != nil && err == protocol.Socks4Downgrade { v.handleSocks4(clientAddr, reader, writer, auth4) } else { v.handleSocks5(clientAddr, reader, writer, auth) } }
func (v *Server) handleSocks4(clientAddr v2net.Destination, reader *bufio.BufferedReader, writer *bufio.BufferedWriter, auth protocol.Socks4AuthenticationRequest) error { result := protocol.Socks4RequestGranted if auth.Command == protocol.CmdBind { result = protocol.Socks4RequestRejected } socks4Response := protocol.NewSocks4AuthenticationResponse(result, auth.Port, auth.IP[:]) socks4Response.Write(writer) if result == protocol.Socks4RequestRejected { log.Warning("Socks: Unsupported socks 4 command ", auth.Command) log.Access(clientAddr, "", log.AccessRejected, ErrUnsupportedSocksCommand) return ErrUnsupportedSocksCommand } reader.SetCached(false) writer.SetCached(false) dest := v2net.TCPDestination(v2net.IPAddress(auth.IP[:]), auth.Port) session := &proxy.SessionInfo{ Source: clientAddr, Destination: dest, Inbound: v.meta, } log.Access(clientAddr, dest, log.AccessAccepted, "") v.transport(reader, writer, session) return nil }
func (v *VMessOutboundHandler) handleResponse(session *encoding.ClientSession, conn internet.Connection, request *protocol.RequestHeader, dest v2net.Destination, output buf.Writer, finish *sync.Mutex) { defer finish.Unlock() reader := bufio.NewReader(conn) defer reader.Release() header, err := session.DecodeResponseHeader(reader) if err != nil { conn.SetReusable(false) log.Warning("VMess|Outbound: Failed to read response from ", request.Destination(), ": ", err) return } v.handleCommand(dest, header.Command) conn.SetReusable(header.Option.Has(protocol.ResponseOptionConnectionReuse)) reader.SetCached(false) bodyReader := session.DecodeResponseBody(request, reader) defer bodyReader.Release() if err := buf.PipeUntilEOF(bodyReader, output); err != nil { conn.SetReusable(false) } return }
func (h *Handler) Dial(ctx context.Context, dest v2net.Destination) (internet.Connection, error) { if h.senderSettings != nil { if h.senderSettings.ProxySettings.HasTag() { tag := h.senderSettings.ProxySettings.Tag handler := h.outboundManager.GetHandler(tag) if handler != nil { log.Info("Proxyman|OutboundHandler: Proxying to ", tag) ctx = proxy.ContextWithDestination(ctx, dest) stream := ray.NewRay(ctx) go handler.Dispatch(ctx, stream) return NewConnection(stream), nil } log.Warning("Proxyman|OutboundHandler: Failed to get outbound handler with tag: ", tag) } if h.senderSettings.Via != nil { ctx = internet.ContextWithDialerSource(ctx, h.senderSettings.Via.AsAddress()) } if h.senderSettings != nil { ctx = internet.ContextWithStreamSettings(ctx, h.senderSettings.StreamSettings) } } return internet.Dial(ctx, dest) }
func (v *DefaultDispatcher) DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay { direct := ray.NewRay() dispatcher := v.ohm.GetDefaultHandler() destination := session.Destination if v.router != nil { if tag, err := v.router.TakeDetour(session); err == nil { if handler := v.ohm.GetHandler(tag); handler != nil { log.Info("DefaultDispatcher: Taking detour [", tag, "] for [", destination, "].") dispatcher = handler } else { log.Warning("DefaultDispatcher: Nonexisting tag: ", tag) } } else { log.Info("DefaultDispatcher: Default route for ", destination) } } if session.Inbound != nil && session.Inbound.AllowPassiveConnection { go dispatcher.Dispatch(destination, buf.NewLocal(32), direct) } else { go v.FilterPacketAndDispatch(destination, direct, dispatcher) } return direct }
func (this *Server) handlePlainHTTP(request *http.Request, session *proxy.SessionInfo, reader *bufio.Reader, writer io.Writer) { if len(request.URL.Host) <= 0 { response := this.GenerateResponse(400, "Bad Request") response.Write(writer) return } request.Host = request.URL.Host StripHopByHopHeaders(request) ray := this.packetDispatcher.DispatchToOutbound(session) defer ray.InboundInput().Close() defer ray.InboundOutput().Release() var finish sync.WaitGroup finish.Add(1) go func() { defer finish.Done() requestWriter := v2io.NewBufferedWriter(v2io.NewChainWriter(ray.InboundInput())) err := request.Write(requestWriter) if err != nil { log.Warning("HTTP: Failed to write request: ", err) return } requestWriter.Flush() }() finish.Add(1) go func() { defer finish.Done() responseReader := bufio.NewReader(v2io.NewChanReader(ray.InboundOutput())) response, err := http.ReadResponse(responseReader, request) if err != nil { log.Warning("HTTP: Failed to read response: ", err) response = this.GenerateResponse(503, "Service Unavailable") } responseWriter := v2io.NewBufferedWriter(writer) err = response.Write(responseWriter) if err != nil { log.Warning("HTTP: Failed to write response: ", err) return } responseWriter.Flush() }() finish.Wait() }
func (this *FreedomConnection) Dispatch(destination v2net.Destination, payload *alloc.Buffer, ray ray.OutboundRay) error { log.Info("Freedom: Opening connection to ", destination) defer payload.Release() defer ray.OutboundInput().Release() defer ray.OutboundOutput().Close() var conn internet.Connection if this.domainStrategy == Config_USE_IP && destination.Address.Family().IsDomain() { destination = this.ResolveIP(destination) } err := retry.ExponentialBackoff(5, 100).On(func() error { rawConn, err := internet.Dial(this.meta.Address, destination, this.meta.GetDialerOptions()) if err != nil { return err } conn = rawConn return nil }) if err != nil { log.Warning("Freedom: Failed to open connection to ", destination, ": ", err) return err } defer conn.Close() input := ray.OutboundInput() output := ray.OutboundOutput() if !payload.IsEmpty() { conn.Write(payload.Value) } go func() { v2writer := v2io.NewAdaptiveWriter(conn) defer v2writer.Release() v2io.Pipe(input, v2writer) if tcpConn, ok := conn.(*tcp.RawConnection); ok { tcpConn.CloseWrite() } }() var reader io.Reader = conn timeout := this.timeout if destination.Network == v2net.Network_UDP { timeout = 16 } if timeout > 0 { reader = v2net.NewTimeOutReader(timeout /* seconds */, conn) } v2reader := v2io.NewAdaptiveReader(reader) v2io.Pipe(v2reader, output) v2reader.Release() ray.OutboundOutput().Close() return nil }
func (this *Point) GetHandler(tag string) (proxy.InboundHandler, int) { handler, found := this.taggedInboundHandlers[tag] if !found { log.Warning("V2Ray: Unable to find an inbound handler with tag: ", tag) return nil, 0 } return handler.GetConnectionHandler() }
func CreateNetworkConfig(network v2net.Network) (interface{}, error) { creator, ok := globalNetworkConfigCreatorCache[network] if !ok { log.Warning("Internet: Network config creator not found: ", network) return nil, ErrUnconfiguredNetwork } return creator(), nil }
// Start starts the Point server, and return any error during the process. // In the case of any errors, the state of the server is unpredicatable. func (v *Point) Start() error { ihm := proxyman.InboundHandlerManagerFromSpace(v.space) if err := ihm.Start(); err != nil { return err } log.Warning("V2Ray started.") return nil }
func ReadAuthentication(reader io.Reader) (auth Socks5AuthenticationRequest, auth4 Socks4AuthenticationRequest, err error) { buffer := make([]byte, 256) nBytes, err := reader.Read(buffer) if err != nil { return } if nBytes < 2 { log.Warning("Socks: expected 2 bytes read, but only ", nBytes, " bytes read") err = transport.ErrCorruptedPacket return } if buffer[0] == socks4Version { auth4.Version = buffer[0] auth4.Command = buffer[1] auth4.Port = v2net.PortFromBytes(buffer[2:4]) copy(auth4.IP[:], buffer[4:8]) err = Socks4Downgrade return } auth.version = buffer[0] if auth.version != socksVersion { log.Warning("Socks: Unknown protocol version ", auth.version) err = proxy.ErrInvalidProtocolVersion return } auth.nMethods = buffer[1] if auth.nMethods <= 0 { log.Warning("Socks: Zero length of authentication methods") err = proxy.ErrInvalidAuthentication return } if nBytes-2 != int(auth.nMethods) { log.Warning("Socks: Unmatching number of auth methods, expecting ", auth.nMethods, ", but got ", nBytes) err = proxy.ErrInvalidAuthentication return } copy(auth.authMethods[:], buffer[2:nBytes]) return }
func (ws *wsconn) getNewReadBuffer() error { _, r, err := ws.wsc.NextReader() if err != nil { log.Warning("WS transport: ws connection NewFrameReader return ", err) ws.connClosing = true ws.Close() return err } ws.readBuffer = bufio.NewReader(r) return nil }
func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, reader io.Reader, writer io.Writer) error { if len(request.URL.Host) <= 0 { response := generateResponse(400, "Bad Request") return response.Write(writer) } request.Host = request.URL.Host StripHopByHopHeaders(request) ray := s.packetDispatcher.DispatchToOutbound(ctx) input := ray.InboundInput() output := ray.InboundOutput() requestDone := signal.ExecuteAsync(func() error { defer input.Close() requestWriter := bufio.NewWriter(buf.NewBytesWriter(ray.InboundInput())) err := request.Write(requestWriter) if err != nil { return err } if err := requestWriter.Flush(); err != nil { return err } return nil }) responseDone := signal.ExecuteAsync(func() error { responseReader := bufio.OriginalReader(buf.NewBytesReader(ray.InboundOutput())) response, err := http.ReadResponse(responseReader, request) if err != nil { log.Warning("HTTP: Failed to read response: ", err) response = generateResponse(503, "Service Unavailable") } responseWriter := bufio.NewWriter(writer) if err := response.Write(responseWriter); err != nil { return err } if err := responseWriter.Flush(); err != nil { return err } return nil }) if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil { log.Info("HTTP|Server: Connecton ending with ", err) input.CloseError() output.CloseError() return err } return nil }
// Start starts the Point server, and return any error during the process. // In the case of any errors, the state of the server is unpredicatable. func (this *Point) Start() error { for _, inbound := range this.inboundHandlers { err := inbound.Start() if err != nil { return err } } log.Warning("V2Ray started.") return nil }
func (v *Config) BuildCertificates() []tls.Certificate { certs := make([]tls.Certificate, 0, len(v.Certificate)) for _, entry := range v.Certificate { keyPair, err := tls.X509KeyPair(entry.Certificate, entry.Key) if err != nil { log.Warning("TLS: ignoring invalid X509 key pair: ", err) continue } certs = append(certs, keyPair) } return certs }
func (this *Config) GetInternalHosts() map[string]net.IP { hosts := make(map[string]net.IP) for domain, ipOrDomain := range this.GetHosts() { address := ipOrDomain.AsAddress() if address.Family().IsDomain() { log.Warning("DNS: Ignoring domain address in static hosts: ", address.Domain()) continue } hosts[domain] = address.IP() } return hosts }
func ReadRequest(reader io.Reader) (request *Socks5Request, err error) { buffer := alloc.NewSmallBuffer() defer buffer.Release() _, err = io.ReadFull(reader, buffer.Value[:4]) if err != nil { return } request = &Socks5Request{ Version: buffer.Value[0], Command: buffer.Value[1], // buffer[2] is a reserved field AddrType: buffer.Value[3], } switch request.AddrType { case AddrTypeIPv4: _, err = io.ReadFull(reader, request.IPv4[:]) if err != nil { return } case AddrTypeDomain: _, err = io.ReadFull(reader, buffer.Value[0:1]) if err != nil { return } domainLength := buffer.Value[0] _, err = io.ReadFull(reader, buffer.Value[:domainLength]) if err != nil { return } request.Domain = string(append([]byte(nil), buffer.Value[:domainLength]...)) case AddrTypeIPv6: _, err = io.ReadFull(reader, request.IPv6[:]) if err != nil { return } default: log.Warning("Socks: Unexpected address type ", request.AddrType) err = transport.ErrCorruptedPacket return } _, err = io.ReadFull(reader, buffer.Value[:2]) if err != nil { return } request.Port = v2net.PortFromBytes(buffer.Value[:2]) return }
func (v *OutboundProxy) Dial(src v2net.Address, dest v2net.Destination, options internet.DialerOptions) (internet.Connection, error) { handler := v.outboundManager.GetHandler(options.Proxy.Tag) if handler == nil { log.Warning("Proxy: Failed to get outbound handler with tag: ", options.Proxy.Tag) return internet.Dial(src, dest, internet.DialerOptions{ Stream: options.Stream, }) } log.Info("Proxy: Dialing to ", dest) stream := ray.NewRay() go handler.Dispatch(dest, nil, stream) return NewProxyConnection(src, dest, stream), nil }
func (v *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection) error { source := proxy.SourceFromContext(ctx) reader := buf.NewReader(conn) for { payload, err := reader.Read() if err != nil { break } request, data, err := DecodeUDPPacket(v.user, payload) if err != nil { log.Info("Shadowsocks|Server: Skipping invalid UDP packet from: ", source, ": ", err) log.Access(source, "", log.AccessRejected, err) payload.Release() continue } if request.Option.Has(RequestOptionOneTimeAuth) && v.account.OneTimeAuth == Account_Disabled { log.Info("Shadowsocks|Server: Client payload enables OTA but server doesn't allow it.") payload.Release() continue } if !request.Option.Has(RequestOptionOneTimeAuth) && v.account.OneTimeAuth == Account_Enabled { log.Info("Shadowsocks|Server: Client payload disables OTA but server forces it.") payload.Release() continue } dest := request.Destination() log.Access(source, dest, log.AccessAccepted, "") log.Info("Shadowsocks|Server: Tunnelling request to ", dest) ctx = protocol.ContextWithUser(ctx, request.User) v.udpServer.Dispatch(ctx, dest, data, func(payload *buf.Buffer) { defer payload.Release() data, err := EncodeUDPPacket(request, payload) if err != nil { log.Warning("Shadowsocks|Server: Failed to encode UDP packet: ", err) return } defer data.Release() conn.Write(data.Bytes()) }) } return nil }
func (this *Server) handleConnection(conn internet.Connection) { defer conn.Close() timedReader := v2net.NewTimeOutReader(this.config.Timeout, conn) reader := bufio.NewReaderSize(timedReader, 2048) request, err := http.ReadRequest(reader) if err != nil { if err != io.EOF { log.Warning("HTTP: Failed to read http request: ", err) } return } log.Info("HTTP: Request to Method [", request.Method, "] Host [", request.Host, "] with URL [", request.URL, "]") defaultPort := v2net.Port(80) if strings.ToLower(request.URL.Scheme) == "https" { defaultPort = v2net.Port(443) } host := request.Host if len(host) == 0 { host = request.URL.Host } dest, err := parseHost(host, defaultPort) if err != nil { log.Warning("HTTP: Malformed proxy host (", host, "): ", err) return } log.Access(conn.RemoteAddr(), request.URL, log.AccessAccepted, "") session := &proxy.SessionInfo{ Source: v2net.DestinationFromAddr(conn.RemoteAddr()), Destination: dest, Inbound: this.meta, } if strings.ToUpper(request.Method) == "CONNECT" { this.handleConnect(request, session, reader, conn) } else { this.handlePlainHTTP(request, session, reader, conn) } }
func ReadUDPRequest(packet []byte) (*Socks5UDPRequest, error) { if len(packet) < 5 { return nil, transport.ErrCorruptedPacket } request := new(Socks5UDPRequest) // packet[0] and packet[1] are reserved request.Fragment = packet[2] addrType := packet[3] var dataBegin int switch addrType { case AddrTypeIPv4: if len(packet) < 10 { return nil, transport.ErrCorruptedPacket } ip := packet[4:8] request.Port = v2net.PortFromBytes(packet[8:10]) request.Address = v2net.IPAddress(ip) dataBegin = 10 case AddrTypeIPv6: if len(packet) < 22 { return nil, transport.ErrCorruptedPacket } ip := packet[4:20] request.Port = v2net.PortFromBytes(packet[20:22]) request.Address = v2net.IPAddress(ip) dataBegin = 22 case AddrTypeDomain: domainLength := int(packet[4]) if len(packet) < 5+domainLength+2 { return nil, transport.ErrCorruptedPacket } domain := string(packet[5 : 5+domainLength]) request.Port = v2net.PortFromBytes(packet[5+domainLength : 5+domainLength+2]) request.Address = v2net.ParseAddress(domain) dataBegin = 5 + domainLength + 2 default: log.Warning("Unknown address type ", addrType) return nil, ErrorUnknownAddressType } if len(packet) > dataBegin { request.Data = alloc.NewBuffer().Clear().Append(packet[dataBegin:]) } return request, nil }