mirror of
https://github.com/go-i2p/go-meta-listener.git
synced 2025-06-07 09:03:15 -04:00
69 lines
2.0 KiB
Go
69 lines
2.0 KiB
Go
package meta
|
|
|
|
import (
|
|
"net"
|
|
"time"
|
|
)
|
|
|
|
// handleListener runs in a separate goroutine for each added listener
|
|
// and forwards accepted connections to the connCh channel.
|
|
func (ml *MetaListener) handleListener(id string, listener net.Listener) {
|
|
defer func() {
|
|
log.Printf("Listener goroutine for %s exiting", id)
|
|
ml.listenerWg.Done()
|
|
}()
|
|
|
|
for {
|
|
// First check if the MetaListener is closed
|
|
select {
|
|
case <-ml.closeCh:
|
|
log.Printf("MetaListener closed, stopping %s listener", id)
|
|
return
|
|
default:
|
|
}
|
|
|
|
// Set a deadline for Accept to prevent blocking indefinitely
|
|
if deadline, ok := listener.(interface{ SetDeadline(time.Time) error }); ok {
|
|
deadline.SetDeadline(time.Now().Add(1 * time.Second))
|
|
}
|
|
|
|
conn, err := listener.Accept()
|
|
if err != nil {
|
|
// Check if this is a timeout error (which we expect due to our deadline)
|
|
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
|
continue
|
|
}
|
|
|
|
// Check if this is any other temporary error
|
|
if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
|
|
log.Printf("Temporary error in %s listener: %v, retrying in 100ms", id, err)
|
|
time.Sleep(100 * time.Millisecond)
|
|
continue
|
|
}
|
|
|
|
log.Printf("Permanent error in %s listener: %v, stopping", id, err)
|
|
ml.mu.Lock()
|
|
delete(ml.listeners, id)
|
|
ml.mu.Unlock()
|
|
return
|
|
}
|
|
|
|
// If we reach here, we have a valid connection
|
|
log.Printf("Listener %s accepted connection from %s", id, conn.RemoteAddr())
|
|
|
|
// Try to forward the connection, but don't block indefinitely
|
|
select {
|
|
case ml.connCh <- ConnResult{Conn: conn, src: id}:
|
|
log.Printf("Connection from %s successfully forwarded via %s", conn.RemoteAddr(), id)
|
|
case <-ml.closeCh:
|
|
log.Printf("MetaListener closing while forwarding connection, closing connection")
|
|
conn.Close()
|
|
return
|
|
case <-time.After(5 * time.Second):
|
|
// If we can't forward within 5 seconds, something is seriously wrong
|
|
log.Printf("WARNING: Connection forwarding timed out, closing connection from %s", conn.RemoteAddr())
|
|
conn.Close()
|
|
}
|
|
}
|
|
}
|