| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- package shadowsocks
- import (
- "bytes"
- "io"
- "github.com/v2ray/v2ray-core/common/alloc"
- "github.com/v2ray/v2ray-core/common/log"
- v2net "github.com/v2ray/v2ray-core/common/net"
- "github.com/v2ray/v2ray-core/proxy"
- "github.com/v2ray/v2ray-core/transport"
- )
- const (
- AddrTypeIPv4 = 1
- AddrTypeIPv6 = 4
- AddrTypeDomain = 3
- )
- type Request struct {
- Address v2net.Address
- Port v2net.Port
- OTA bool
- UDPPayload *alloc.Buffer
- }
- func (this *Request) Release() {
- this.Address = nil
- if this.UDPPayload != nil {
- this.UDPPayload.Release()
- }
- }
- func (this *Request) DetachUDPPayload() *alloc.Buffer {
- payload := this.UDPPayload
- this.UDPPayload = nil
- return payload
- }
- func ReadRequest(reader io.Reader, auth *Authenticator, udp bool) (*Request, error) {
- buffer := alloc.NewSmallBuffer()
- defer buffer.Release()
- _, err := io.ReadFull(reader, buffer.Value[:1])
- if err != nil {
- if err != io.EOF {
- log.Warning("Shadowsocks: Failed to read address type: ", err)
- return nil, transport.ErrCorruptedPacket
- }
- return nil, err
- }
- lenBuffer := 1
- request := new(Request)
- addrType := (buffer.Value[0] & 0x0F)
- if (buffer.Value[0] & 0x10) == 0x10 {
- request.OTA = true
- }
- switch addrType {
- case AddrTypeIPv4:
- _, err := io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+4])
- if err != nil {
- log.Warning("Shadowsocks: Failed to read IPv4 address: ", err)
- return nil, transport.ErrCorruptedPacket
- }
- request.Address = v2net.IPAddress(buffer.Value[lenBuffer : lenBuffer+4])
- lenBuffer += 4
- case AddrTypeIPv6:
- _, err := io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+16])
- if err != nil {
- log.Warning("Shadowsocks: Failed to read IPv6 address: ", err)
- return nil, transport.ErrCorruptedPacket
- }
- request.Address = v2net.IPAddress(buffer.Value[lenBuffer : lenBuffer+16])
- lenBuffer += 16
- case AddrTypeDomain:
- _, err := io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+1])
- if err != nil {
- log.Warning("Shadowsocks: Failed to read domain lenth: ", err)
- return nil, transport.ErrCorruptedPacket
- }
- domainLength := int(buffer.Value[lenBuffer])
- lenBuffer++
- _, err = io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+domainLength])
- if err != nil {
- log.Warning("Shadowsocks: Failed to read domain: ", err)
- return nil, transport.ErrCorruptedPacket
- }
- request.Address = v2net.DomainAddress(string(buffer.Value[lenBuffer : lenBuffer+domainLength]))
- lenBuffer += domainLength
- default:
- log.Warning("Shadowsocks: Unknown address type: ", addrType)
- return nil, transport.ErrCorruptedPacket
- }
- _, err = io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+2])
- if err != nil {
- log.Warning("Shadowsocks: Failed to read port: ", err)
- return nil, transport.ErrCorruptedPacket
- }
- request.Port = v2net.PortFromBytes(buffer.Value[lenBuffer : lenBuffer+2])
- lenBuffer += 2
- var authBytes []byte
- if udp {
- nBytes, err := reader.Read(buffer.Value[lenBuffer:])
- if err != nil {
- log.Warning("Shadowsocks: Failed to read UDP payload: ", err)
- return nil, transport.ErrCorruptedPacket
- }
- buffer.Slice(0, lenBuffer+nBytes)
- if request.OTA {
- authBytes = buffer.Value[lenBuffer+nBytes-AuthSize:]
- request.UDPPayload = alloc.NewSmallBuffer().Clear().Append(buffer.Value[lenBuffer : lenBuffer+nBytes-AuthSize])
- lenBuffer = lenBuffer + nBytes - AuthSize
- } else {
- request.UDPPayload = alloc.NewSmallBuffer().Clear().Append(buffer.Value[lenBuffer:])
- }
- } else {
- if request.OTA {
- authBytes = buffer.Value[lenBuffer : lenBuffer+AuthSize]
- _, err = io.ReadFull(reader, authBytes)
- if err != nil {
- log.Warning("Shadowsocks: Failed to read OTA: ", err)
- return nil, transport.ErrCorruptedPacket
- }
- }
- }
- if request.OTA {
- actualAuth := auth.Authenticate(nil, buffer.Value[0:lenBuffer])
- if !bytes.Equal(actualAuth, authBytes) {
- log.Warning("Shadowsocks: Invalid OTA.")
- return nil, proxy.ErrInvalidAuthentication
- }
- }
- return request, nil
- }
|