Example #1
0
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)

}
Example #2
0
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()
}
Example #3
0
// 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)
}
Example #4
0
// 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()
	}
}
Example #5
0
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
}
Example #6
0
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.")
}