2023-02-24 09:54:54 +08:00
|
|
|
package callback
|
|
|
|
|
|
|
|
import (
|
2023-04-01 20:56:49 +08:00
|
|
|
"github.com/Dreamacro/clash/common/buf"
|
|
|
|
N "github.com/Dreamacro/clash/common/net"
|
2023-02-24 09:54:54 +08:00
|
|
|
C "github.com/Dreamacro/clash/constant"
|
|
|
|
)
|
|
|
|
|
2023-04-01 20:56:49 +08:00
|
|
|
type firstWriteCallBackConn struct {
|
2023-02-24 09:54:54 +08:00
|
|
|
C.Conn
|
2023-04-01 20:56:49 +08:00
|
|
|
callback func(error)
|
2023-02-24 09:54:54 +08:00
|
|
|
written bool
|
|
|
|
}
|
|
|
|
|
2023-04-01 20:56:49 +08:00
|
|
|
func (c *firstWriteCallBackConn) Write(b []byte) (n int, err error) {
|
2023-02-24 09:54:54 +08:00
|
|
|
defer func() {
|
|
|
|
if !c.written {
|
|
|
|
c.written = true
|
2023-04-01 20:56:49 +08:00
|
|
|
c.callback(err)
|
2023-02-24 09:54:54 +08:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
return c.Conn.Write(b)
|
|
|
|
}
|
|
|
|
|
2023-04-01 20:56:49 +08:00
|
|
|
func (c *firstWriteCallBackConn) Upstream() any {
|
2023-02-24 09:54:54 +08:00
|
|
|
return c.Conn
|
|
|
|
}
|
2023-04-01 20:56:49 +08:00
|
|
|
|
|
|
|
type extendedConn interface {
|
|
|
|
C.Conn
|
|
|
|
N.ExtendedConn
|
|
|
|
}
|
|
|
|
|
|
|
|
type firstWriteCallBackExtendedConn struct {
|
|
|
|
extendedConn
|
|
|
|
callback func(error)
|
|
|
|
written bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *firstWriteCallBackExtendedConn) Write(b []byte) (n int, err error) {
|
|
|
|
defer func() {
|
|
|
|
if !c.written {
|
|
|
|
c.written = true
|
|
|
|
c.callback(err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
return c.extendedConn.Write(b)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *firstWriteCallBackExtendedConn) WriteBuffer(buffer *buf.Buffer) (err error) {
|
|
|
|
defer func() {
|
|
|
|
if !c.written {
|
|
|
|
c.written = true
|
|
|
|
c.callback(err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
return c.extendedConn.WriteBuffer(buffer)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *firstWriteCallBackExtendedConn) Upstream() any {
|
|
|
|
return c.extendedConn
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewFirstWriteCallBackConn(c C.Conn, callback func(error)) C.Conn {
|
|
|
|
if c, ok := c.(extendedConn); ok {
|
|
|
|
return &firstWriteCallBackExtendedConn{
|
|
|
|
extendedConn: c,
|
|
|
|
callback: callback,
|
|
|
|
written: false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return &firstWriteCallBackConn{
|
|
|
|
Conn: c,
|
|
|
|
callback: callback,
|
|
|
|
written: false,
|
|
|
|
}
|
|
|
|
}
|