| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- package internal
- import (
- "io"
- "net"
- "sync"
- "time"
- v2net "v2ray.com/core/common/net"
- )
- // ConnectionID is the ID of a connection.
- type ConnectionID struct {
- Local v2net.Address
- Remote v2net.Address
- RemotePort v2net.Port
- }
- // NewConnectionID creates a new ConnectionId.
- func NewConnectionID(source v2net.Address, dest v2net.Destination) ConnectionID {
- return ConnectionID{
- Local: source,
- Remote: dest.Address,
- RemotePort: dest.Port,
- }
- }
- // Reuser determines whether a connection can be reused or not.
- type Reuser struct {
- // userEnabled indicates connection-reuse enabled by user.
- userEnabled bool
- // appEnabled indicates connection-reuse enabled by app.
- appEnabled bool
- }
- // ReuseConnection returns a tracker for tracking connection reusability.
- func ReuseConnection(reuse bool) *Reuser {
- return &Reuser{
- userEnabled: reuse,
- appEnabled: reuse,
- }
- }
- // Connection is an implementation of net.Conn with re-usability.
- type Connection struct {
- sync.RWMutex
- id ConnectionID
- conn net.Conn
- listener ConnectionRecyler
- reuser *Reuser
- }
- // NewConnection creates a new connection.
- func NewConnection(id ConnectionID, conn net.Conn, manager ConnectionRecyler, reuser *Reuser) *Connection {
- return &Connection{
- id: id,
- conn: conn,
- listener: manager,
- reuser: reuser,
- }
- }
- // Read implements net.Conn.Read().
- func (v *Connection) Read(b []byte) (int, error) {
- conn := v.underlyingConn()
- if conn == nil {
- return 0, io.EOF
- }
- return conn.Read(b)
- }
- // Write implement net.Conn.Write().
- func (v *Connection) Write(b []byte) (int, error) {
- conn := v.underlyingConn()
- if conn == nil {
- return 0, io.ErrClosedPipe
- }
- return conn.Write(b)
- }
- // Close implements net.Conn.Close(). If the connection is reusable, the underlying connection will be recycled.
- func (v *Connection) Close() error {
- if v == nil {
- return io.ErrClosedPipe
- }
- v.Lock()
- defer v.Unlock()
- if v.conn == nil {
- return io.ErrClosedPipe
- }
- if v.Reusable() {
- v.listener.Put(v.id, v.conn)
- return nil
- }
- err := v.conn.Close()
- v.conn = nil
- return err
- }
- // LocalAddr implements net.Conn.LocalAddr().
- func (v *Connection) LocalAddr() net.Addr {
- conn := v.underlyingConn()
- if conn == nil {
- return nil
- }
- return conn.LocalAddr()
- }
- // RemoteAddr implements net.Conn.RemoteAddr().
- func (v *Connection) RemoteAddr() net.Addr {
- conn := v.underlyingConn()
- if conn == nil {
- return nil
- }
- return conn.RemoteAddr()
- }
- // SetDeadline implements net.Conn.SetDeadline().
- func (v *Connection) SetDeadline(t time.Time) error {
- conn := v.underlyingConn()
- if conn == nil {
- return nil
- }
- return conn.SetDeadline(t)
- }
- // SetReadDeadline implements net.Conn.SetReadDeadline().
- func (v *Connection) SetReadDeadline(t time.Time) error {
- conn := v.underlyingConn()
- if conn == nil {
- return nil
- }
- return conn.SetReadDeadline(t)
- }
- // SetWriteDeadline implements net.Conn.SetWriteDeadline().
- func (v *Connection) SetWriteDeadline(t time.Time) error {
- conn := v.underlyingConn()
- if conn == nil {
- return nil
- }
- return conn.SetWriteDeadline(t)
- }
- // SetReusable implements internet.Reusable.SetReusable().
- func (v *Connection) SetReusable(reusable bool) {
- if v == nil {
- return
- }
- v.reuser.appEnabled = reusable
- }
- // Reusable implements internet.Reusable.Reusable().
- func (v *Connection) Reusable() bool {
- if v == nil {
- return false
- }
- return v.reuser.userEnabled && v.reuser.appEnabled
- }
- // SysFd implement internet.SysFd.SysFd().
- func (v *Connection) SysFd() (int, error) {
- conn := v.underlyingConn()
- if conn == nil {
- return 0, io.ErrClosedPipe
- }
- return GetSysFd(conn)
- }
- func (v *Connection) underlyingConn() net.Conn {
- if v == nil {
- return nil
- }
- v.RLock()
- defer v.RUnlock()
- return v.conn
- }
|