github.com/xxf098/lite-proxy@v0.15.1-0.20230422081941-12c69f323218/transport/ssr/obfs/random_head.go (about)

     1  package obfs
     2  
     3  import (
     4  	"encoding/binary"
     5  	"hash/crc32"
     6  	"math/rand"
     7  	"net"
     8  
     9  	"github.com/xxf098/lite-proxy/common/pool"
    10  )
    11  
    12  func init() {
    13  	register("random_head", newRandomHead, 0)
    14  }
    15  
    16  type randomHead struct {
    17  	*Base
    18  }
    19  
    20  func newRandomHead(b *Base) Obfs {
    21  	return &randomHead{Base: b}
    22  }
    23  
    24  type randomHeadConn struct {
    25  	net.Conn
    26  	*randomHead
    27  	hasSentHeader bool
    28  	rawTransSent  bool
    29  	rawTransRecv  bool
    30  	buf           []byte
    31  }
    32  
    33  func (r *randomHead) StreamConn(c net.Conn) net.Conn {
    34  	return &randomHeadConn{Conn: c, randomHead: r}
    35  }
    36  
    37  func (c *randomHeadConn) Read(b []byte) (int, error) {
    38  	if c.rawTransRecv {
    39  		return c.Conn.Read(b)
    40  	}
    41  	buf := pool.Get(pool.RelayBufferSize)
    42  	defer pool.Put(buf)
    43  	c.Conn.Read(buf)
    44  	c.rawTransRecv = true
    45  	c.Write(nil)
    46  	return 0, nil
    47  }
    48  
    49  func (c *randomHeadConn) Write(b []byte) (int, error) {
    50  	if c.rawTransSent {
    51  		return c.Conn.Write(b)
    52  	}
    53  	c.buf = append(c.buf, b...)
    54  	if !c.hasSentHeader {
    55  		c.hasSentHeader = true
    56  		dataLength := rand.Intn(96) + 4
    57  		buf := pool.Get(dataLength + 4)
    58  		defer pool.Put(buf)
    59  		rand.Read(buf[:dataLength])
    60  		binary.LittleEndian.PutUint32(buf[dataLength:], 0xffffffff-crc32.ChecksumIEEE(buf[:dataLength]))
    61  		_, err := c.Conn.Write(buf)
    62  		return len(b), err
    63  	}
    64  	if c.rawTransRecv {
    65  		_, err := c.Conn.Write(c.buf)
    66  		c.buf = nil
    67  		c.rawTransSent = true
    68  		return len(b), err
    69  	}
    70  	return len(b), nil
    71  }