github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/transport/internet/httpupgrade/hub.go (about) 1 package httpupgrade 2 3 import ( 4 "bufio" 5 "context" 6 "net/http" 7 "strings" 8 9 "github.com/v2fly/v2ray-core/v5/common" 10 "github.com/v2fly/v2ray-core/v5/common/net" 11 "github.com/v2fly/v2ray-core/v5/transport/internet" 12 "github.com/v2fly/v2ray-core/v5/transport/internet/transportcommon" 13 ) 14 15 type server struct { 16 addConn internet.ConnHandler 17 innnerListener net.Listener 18 } 19 20 func (s *server) Close() error { 21 return s.innnerListener.Close() 22 } 23 24 func (s *server) Addr() net.Addr { 25 return nil 26 } 27 28 func (s *server) Handle(conn net.Conn) (internet.Connection, error) { 29 connReader := bufio.NewReader(conn) 30 req, err := http.ReadRequest(connReader) 31 if err != nil { 32 return nil, err 33 } 34 connection := strings.ToLower(req.Header.Get("Connection")) 35 upgrade := strings.ToLower(req.Header.Get("Upgrade")) 36 if connection != "upgrade" || upgrade != "websocket" { 37 _ = conn.Close() 38 return nil, newError("unrecognized request") 39 } 40 resp := &http.Response{ 41 Status: "101 Switching Protocols", 42 StatusCode: 101, 43 Proto: "HTTP/1.1", 44 ProtoMajor: 1, 45 ProtoMinor: 1, 46 Header: http.Header{}, 47 } 48 resp.Header.Set("Connection", "upgrade") 49 resp.Header.Set("Upgrade", "websocket") 50 err = resp.Write(conn) 51 if err != nil { 52 _ = conn.Close() 53 return nil, err 54 } 55 return internet.Connection(conn), nil 56 } 57 58 func (s *server) keepAccepting() { 59 for { 60 conn, err := s.innnerListener.Accept() 61 if err != nil { 62 return 63 } 64 handledConn, err := s.Handle(conn) 65 if err != nil { 66 newError("failed to handle request").Base(err).WriteToLog() 67 continue 68 } 69 s.addConn(handledConn) 70 } 71 } 72 73 func listenHTTPUpgrade(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, addConn internet.ConnHandler) (internet.Listener, error) { 74 transportConfiguration := streamSettings.ProtocolSettings.(*Config) 75 _ = transportConfiguration 76 serverInstance := &server{addConn: addConn} 77 78 listener, err := transportcommon.ListenWithSecuritySettings(ctx, address, port, streamSettings) 79 if err != nil { 80 return nil, newError("failed to listen on ", address, ":", port).Base(err) 81 } 82 serverInstance.innnerListener = listener 83 go serverInstance.keepAccepting() 84 return serverInstance, nil 85 } 86 87 func init() { 88 common.Must(internet.RegisterTransportListener(protocolName, listenHTTPUpgrade)) 89 }