package socket import ( "context" "tunnel/pkg/server/env" "tunnel/pkg/server/queue" ) type deferSocket struct { dialSocket } type deferConn struct { s *deferSocket e env.Env ctx context.Context cancel func() conn chan *conn } func (s *deferSocket) New(env env.Env) (Conn, error) { ctx, cancel := context.WithCancel(context.TODO()) c := &deferConn{ s: s, e: env, conn: make(chan *conn), ctx: ctx, cancel: cancel, } return c, nil } func (c *deferConn) String() string { return "defer" } func (c *deferConn) Send(wq queue.Q) error { conn := <-c.conn if conn == nil { return nil } return conn.Send(wq) } func (c *deferConn) Recv(rq queue.Q) error { // TODO: and context check r := rq.Reader() if _, err := r.Read(nil); err != nil { c.conn <- nil return nil } conn, err := dial(c.ctx, c.e, c.s.Proto, c.s.Addr) if err != nil { c.conn <- nil return err } go func() { <-c.ctx.Done() conn.Close() }() c.conn <- conn return queue.IoCopy(r, conn) } func (c *deferConn) Close() error { c.cancel() return nil } func init() { register("defer", "deferred 'dial' after first sending", deferSocket{}) }