func (wp websocketProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { logger.Debug("Upgrading websocket connection.") oconn, err := upgrader.Upgrade(w, r, nil) if err != nil { logger.Error(err) return } defer oconn.Close() r.URL.Host = config.Destination r.URL.Scheme = "ws" dialer := websocket.Dialer{ HandshakeTimeout: time.Second, ReadBufferSize: 1024, WriteBufferSize: 1024, Subprotocols: websocket.Subprotocols(r), } logger.Debug("Dialing", r.URL.String(), "...") iconn, _, err := dialer.Dial(r.URL.String(), nil) if err != nil { logger.Error(err) return } defer iconn.Close() logger.Debug("Connected!") go wp.Copy(oconn, iconn) wp.Copy(iconn, oconn) }
func chatHandler(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { http.Error(w, "Invalid request for this endpoint", 405) } ws, err := upgrader.Upgrade(w, r, http.Header{ "Sec-websocket-Protocol": websocket.Subprotocols(r), }) if err != nil { log.Println("Error Upgrading: ", err.Error()) return } cli := NewClient(server, ws) cli.Handle() }
// ServeHTTP implements `http.Handler` interface, which serves HTTP requests. func (sc *SocketCrutch) ServeHTTP(rw http.ResponseWriter, req *http.Request) { log.Debugf("handling %s http request %s", req.Method, req.URL) if sc.handshakeHandler != nil { if ok := sc.handshakeHandler(rw, req); !ok { log.Debug("custom handshake failed") http.Error(rw, "handshake failed", http.StatusForbidden) return } } if atomic.LoadInt32(&sc.connectCounter)+1 > sc.config.maxConnections { log.Debug("too many connections") http.Error(rw, "too many connections", http.StatusServiceUnavailable) return } // Upgrade websocket connection. protocols := websocket.Subprotocols(req) var responseHeader http.Header = nil if len(protocols) > 0 { responseHeader = http.Header{"Sec-Websocket-Protocol": {protocols[0]}} } ws, err := sc.upgrader.Upgrade(rw, req, responseHeader) if err != nil { log.Debugf("failed to upgrade websocket: %v", err) if _, ok := err.(websocket.HandshakeError); !ok { sc.errorHandler(nil, err) log.Errorf("unknown error while upgrade websocket: %v", err) } return } sc.createClient(ws, req) }
// Handler creates a handler function for this router, that can be used with the // http-package to handle WebSocket-Connections. func (router *Router) Handler() func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { // Check if method used was GET. if r.Method != "GET" { http.Error(w, "Method not allowed", 405) return } // Disallow cross-origin connections. if len(router.Origins) > 0 { originFound := false for _, origin := range router.Origins { if r.Header.Get("Origin") == origin { originFound = true break } } if !originFound { http.Error(w, "Origin not allowed", 403) return } } else { if len(r.Header.Get("Access-Control-Allow-Origin")) > 0 { allowedOrigin := r.Header.Get("Access-Control-Allow-Origin") if allowedOrigin != "*" { if r.URL.Scheme+"://"+r.Host != allowedOrigin { http.Error(w, "Origin not allwed", 403) return } } } } // Check if handshake callback verifies upgrade. if !router.handshakeFunc(w, r) { http.Error(w, "Authorization failed", 403) return } // Upgrade websocket connection. protocols := websocket.Subprotocols(r) var responseHeader http.Header = nil if len(protocols) > 0 { responseHeader = http.Header{"Sec-Websocket-Protocol": {protocols[0]}} } socket, err := websocket.Upgrade(w, r, responseHeader, 1024, 1024) // Check if handshake was successful if _, ok := err.(websocket.HandshakeError); ok { http.Error(w, "Not a websocket handshake", 400) return } else if err != nil { log.Println(err) return } // Create the connection. conn := newConnection(socket, router) // if router.connExtensionConstructor.IsValid() { conn.extend(router.connExtensionConstructor.Call([]reflect.Value{reflect.ValueOf(conn)})[0].Interface()) } // Connection established with possible extension, so callback router.connectionFunc(conn, r) // And start reading and writing routines. conn.run() } }
func (this *Websockify) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/websockify" { this.fileserver.ServeHTTP(w, r) return } // check token tokenCookie, err := r.Cookie("token") if err != nil { if this.Debug { log.Printf("Token cookie error (%s): %s", r.RemoteAddr, err.Error()) } return } target := this.tokens[tokenCookie.Value] if target == nil { if this.Debug { log.Printf("Invalid token (%s): %s", r.RemoteAddr, tokenCookie.Value) } return } // try upgrade connection useBinary := false responseHeader := make(http.Header) requestedSubprotocols := websocket.Subprotocols(r) if len(requestedSubprotocols) > 0 { // pick base64 or binary subprotocol if available // otherwise arbitrarily pick the first one and hope for the best pickedSubprotocol := "" for _, subprotocol := range requestedSubprotocols { if subprotocol == "base64" { pickedSubprotocol = "base64" break } else if subprotocol == "binary" { pickedSubprotocol = "binary" useBinary = true break } } if pickedSubprotocol == "" { pickedSubprotocol = requestedSubprotocols[0] if this.Debug { log.Printf("Warning: client %s did not offer base64 or binary subprotocols, falling back to %s", r.RemoteAddr, pickedSubprotocol) } } responseHeader.Set("Sec-Websocket-Protocol", pickedSubprotocol) } conn, err := this.upgrader.Upgrade(w, r, responseHeader) if err != nil { log.Printf("websockify error (%s): %s", r.RemoteAddr, err.Error()) return } defer conn.Close() if this.Debug { log.Printf("Initializing connection from %s to %s", r.RemoteAddr, target.ipport) } sock, err := net.Dial("tcp", target.ipport) if err != nil { if this.Debug { log.Print(err) } return } defer sock.Close() done := make(chan bool, 2) go func() { defer func() { done <- true }() wbuf := make([]byte, 32*1024) for { messageType, p, err := conn.ReadMessage() if err != nil { return } var fwdbuf []byte if messageType == websocket.TextMessage { n, _ := base64.StdEncoding.Decode(wbuf, p) fwdbuf = wbuf[:n] } else if messageType == websocket.BinaryMessage { fwdbuf = p } if fwdbuf != nil { _, err = sock.Write(fwdbuf) if err != nil { return } } } }() go func() { defer func() { done <- true }() rbuf := make([]byte, 8192) wbuf := make([]byte, len(rbuf)*2) for { n, err := sock.Read(rbuf) if err != nil { return } if n > 0 { var err error if useBinary { err = conn.WriteMessage(websocket.BinaryMessage, rbuf[:n]) } else { base64.StdEncoding.Encode(wbuf, rbuf[:n]) err = conn.WriteMessage(websocket.TextMessage, wbuf[:base64.StdEncoding.EncodedLen(n)]) } if err != nil { return } } } }() <-done }
func (g *GameServer) serverConnect(w http.ResponseWriter, r *http.Request) { doE := func(code int, err string) { w.Header().Set("Content-Type", "application/json") j, _ := json.Marshal(map[string]interface{}{"code": code, "error": err}) w.WriteHeader(code) w.Write(j) } if r.URL.Path == "/connect" { if r.Method != "GET" { doE(405, "Method not allowed.") return } if g.conf.Origin != nil { found := false for _, cl := range g.conf.Origin { if strings.ToLower(r.Header.Get("Origin")) == cl { found = true break } } if !found { doE(403, "Origin not allowed") } } username := r.FormValue("name") if username == "" { doE(400, "Invalid name.") } password := r.FormValue("pass") register := r.FormValue("register") protocol := "" validProtocol := false for _, p := range g.protocols { for _, rp := range websocket.Subprotocols(r) { if p == rp { protocol = p validProtocol = true break } } if validProtocol { break } } var headers map[string][]string = nil if validProtocol { headers = map[string][]string{ "Sec-Websocket-Protocol": []string{protocol}, } } else if len(websocket.Subprotocols(r)) != 0 { headers = map[string][]string{ "Sec-Websocket-Protocol": []string{websocket.Subprotocols(r)[0]}, } } ws, err := websocket.Upgrade(w, r, headers, 1024, 1024) if _, ok := err.(websocket.HandshakeError); ok { doE(405, "Not a websocket handshake.") return } else if err != nil { log.Println(err) doE(500, err.Error()) return } if !validProtocol { ws.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(CLOSE_INVALID_PROTO, "Invalid protocol ("+strings.Join(websocket.Subprotocols(r), ",")+")."), time.Now().Add(10*time.Second)) return } user, uerr := g.datastore.GetUser(username) if uerr == nil { if !user.CheckPassword(password) { ws.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(CLOSE_INVALID_PASS, "Invalid password."), time.Now().Add(10*time.Second)) return } } else if uerr == datastore.ErrUserNotFound { if g.conf.ForceAuth && password == "" { ws.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(CLOSE_INVALID_PASS, "Invalid password."), time.Now().Add(10*time.Second)) return } if password != "" { if register != "" { user = datastore.NewUser(username, password) } else { ws.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(CLOSE_INVALID_USER, "Invalid user."), time.Now().Add(10*time.Second)) return } } user = datastore.NewUser(username, "") user.Temporary = true } else { ws.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(1011, "Server error."), time.Now().Add(10*time.Second)) return } if g.conf.Slots != 0 { if atomic.AddInt64(&g.NoUsers, 1) > int64(g.conf.Slots) { ws.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(CLOSE_NO_SLOTS, "No available slots."), time.Now().Add(10*time.Second)) atomic.AddInt64(&g.NoUsers, -1) return } } else { atomic.AddInt64(&g.NoUsers, 1) } defer atomic.AddInt64(&g.NoUsers, -1) player := NewPlayer(ws, user) g.GameLobby.Register(player) user.Status = &datastore.UserStatus{ Server: g.getServerInfo().Address(), Location: LOCATION_LOBBY, } g.datastore.PutUser(user) if user.Temporary { defer g.datastore.DeleteUser(user) } player.Listen() return } doE(404, "Not found.") }