relay-server/ingress/handler.go
2025-12-23 16:38:32 +03:00

83 lines
1.5 KiB
Go

package ingress
import (
"log"
"net"
"relay/registry"
"relay/util"
tunnelpb "relay/proto/tunnel"
)
func handleClientTCP(conn net.Conn) {
defer conn.Close()
sni, hello, err := peekClientHello(conn)
if err != nil {
log.Println("peek failed:", err)
return
}
log.Println("Client SNI:", sni)
registry.Global.Mu.Lock()
dev := registry.Global.Domains[sni]
log.Println("Known domains:", util.Keys(registry.Global.Domains))
registry.Global.Mu.Unlock()
if dev == nil {
log.Println("No device bound for domain:", sni)
conn.Write([]byte("HTTP/1.1 503 No device\r\n\r\n"))
return
}
streamID := dev.AllocateStreamID()
done := dev.AddStream(streamID, conn)
log.Printf("Client [%s] → device (stream %d)\n", sni, streamID)
dev.SendFrame(&tunnelpb.Frame{
Type: tunnelpb.FrameType_FRAME_OPEN,
StreamId: streamID,
Payload: []byte(sni),
})
dev.SendFrame(&tunnelpb.Frame{
Type: tunnelpb.FrameType_FRAME_DATA,
StreamId: streamID,
Payload: hello,
})
go func() {
buf := util.BufPool.Get().([]byte)
defer util.BufPool.Put(buf)
for {
n, err := conn.Read(buf)
if err != nil {
dev.SendFrame(&tunnelpb.Frame{
Type: tunnelpb.FrameType_FRAME_CLOSE,
StreamId: streamID,
})
dev.RemoveStream(streamID)
return
}
dev.SendFrame(&tunnelpb.Frame{
Type: tunnelpb.FrameType_FRAME_DATA,
StreamId: streamID,
Payload: append([]byte(nil), buf[:n]...),
})
}
}()
select {
case <-done:
case <-dev.Done():
}
dev.RemoveStream(streamID)
}