github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/net/proxy/shadowsocksr/obfs/random_head.go (about)

     1  package obfs
     2  
     3  import (
     4  	crand "crypto/rand"
     5  	"math/rand/v2"
     6  	"net"
     7  
     8  	ssr "github.com/Asutorufa/yuhaiin/pkg/net/proxy/shadowsocksr/utils"
     9  	"github.com/Asutorufa/yuhaiin/pkg/utils/pool"
    10  )
    11  
    12  type randomHead struct {
    13  	rawTransSent     bool
    14  	rawTransReceived bool
    15  	hasSentHeader    bool
    16  	dataBuffer       []byte
    17  
    18  	net.Conn
    19  }
    20  
    21  func newRandomHead(conn net.Conn, _ Obfs) net.Conn { return &randomHead{Conn: conn} }
    22  
    23  func (r *randomHead) encode(data []byte) (encodedData []byte) {
    24  	if r.rawTransSent {
    25  		return data
    26  	}
    27  
    28  	if r.hasSentHeader {
    29  		if len(data) > 0 {
    30  			r.dataBuffer = append(r.dataBuffer, data...)
    31  		} else {
    32  			encodedData = r.dataBuffer
    33  			r.dataBuffer = nil
    34  			r.rawTransSent = true
    35  		}
    36  
    37  		return
    38  	}
    39  
    40  	size := rand.IntN(96) + 8
    41  	encodedData = make([]byte, size)
    42  	_, _ = crand.Read(encodedData)
    43  	ssr.SetCRC32(encodedData, size)
    44  	r.dataBuffer = append(r.dataBuffer, data...)
    45  	r.hasSentHeader = true
    46  	return
    47  }
    48  
    49  func (r *randomHead) Write(b []byte) (int, error) {
    50  	if r.rawTransSent {
    51  		return r.Conn.Write(b)
    52  	}
    53  
    54  	_, err := r.Conn.Write(r.encode(b))
    55  	return len(b), err
    56  }
    57  
    58  func (r *randomHead) Read(b []byte) (n int, err error) {
    59  	if r.rawTransReceived {
    60  		return r.Conn.Read(b)
    61  	}
    62  
    63  	buf := pool.GetBytes(pool.DefaultSize)
    64  	defer pool.PutBytes(buf)
    65  	r.Conn.Read(buf)
    66  	r.rawTransReceived = true
    67  	r.Conn.Write(nil)
    68  	return 0, nil
    69  }
    70  
    71  func (r *randomHead) GetOverhead() int { return 0 }