2023-11-03 11:00:40 +08:00
|
|
|
package net
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"net"
|
2025-04-10 01:16:54 +08:00
|
|
|
|
|
|
|
"github.com/metacubex/mihomo/common/contextutils"
|
2023-11-03 11:00:40 +08:00
|
|
|
)
|
|
|
|
|
2025-04-10 23:32:26 +08:00
|
|
|
// SetupContextForConn is a helper function that starts connection I/O interrupter.
|
|
|
|
// if ctx be canceled before done called, it will close the connection.
|
|
|
|
// should use like this:
|
|
|
|
//
|
|
|
|
// func streamConn(ctx context.Context, conn net.Conn) (_ net.Conn, err error) {
|
|
|
|
// if ctx.Done() != nil {
|
|
|
|
// done := N.SetupContextForConn(ctx, conn)
|
|
|
|
// defer done(&err)
|
|
|
|
// }
|
|
|
|
// conn, err := xxx
|
|
|
|
// return conn, err
|
|
|
|
// }
|
2023-11-03 11:00:40 +08:00
|
|
|
func SetupContextForConn(ctx context.Context, conn net.Conn) (done func(*error)) {
|
2025-04-10 01:16:54 +08:00
|
|
|
stopc := make(chan struct{})
|
|
|
|
stop := contextutils.AfterFunc(ctx, func() {
|
|
|
|
// Close the connection, discarding the error
|
|
|
|
_ = conn.Close()
|
|
|
|
close(stopc)
|
|
|
|
})
|
2023-11-03 11:00:40 +08:00
|
|
|
return func(inputErr *error) {
|
2025-04-10 01:16:54 +08:00
|
|
|
if !stop() {
|
|
|
|
// The AfterFunc was started, wait for it to complete.
|
|
|
|
<-stopc
|
|
|
|
if ctxErr := ctx.Err(); ctxErr != nil && inputErr != nil {
|
|
|
|
// Return context error to user.
|
2025-04-10 23:32:26 +08:00
|
|
|
*inputErr = ctxErr
|
2025-04-10 01:16:54 +08:00
|
|
|
}
|
2023-11-03 11:00:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|