Exemplo n.º 1
0
        private void HandleLogout(HttpListenerContext context)
        {
            var token = RestMethods.GetToken(context.Request);

            if (!_tokens.TryRemove(token, out var id))
            {
                RestMethods.WriteError(context.Response, HttpStatusCode.Unauthorized, "Authorization failed");
                return;
            }
            _users.TryRemove(id, out var user);
            _usernames.TryRemove(user.Username, out id);

            SendToAllSubscribers(WebSocketJsonType.DeletedResource, new DeletedItem
            {
                Item = user,
                Type = WebSocketJsonType.User
            });

            context.Response.StatusCode = (int)HttpStatusCode.NoContent;
            context.Response.OutputStream.Close();
        }
Exemplo n.º 2
0
        private void Subscribe(HttpListenerContext context)
        {
            if (!context.Request.IsWebSocketRequest)
            {
                RestMethods.WriteError(context.Response, HttpStatusCode.BadRequest, "not web socket request");
                return;
            }

            if (!RestMethods.ParseQuery(context.Request.Url.Query, out Dictionary <string, string> query) ||
                query == null || query.Count == 0 || !query.ContainsKey("token"))
            {
                RestMethods.WriteError(context.Response, HttpStatusCode.BadRequest, "missing token parameter");
                return;
            }

            var wsContext = context.AcceptWebSocketAsync(null).Result;

            if (!_tokens.TryGetValue(query["token"], out int userId))
            {
                RestMethods.WriteError(context.Response, HttpStatusCode.Unauthorized, "no match for token value");
                return;
            }

            var segment = ConvertToBytesWithType(WebSocketJsonType.Users, _users.Values);

            wsContext.WebSocket.SendAsync(segment, WebSocketMessageType.Binary, false, CancellationToken.None).Wait();

            lock (_webSockets)
            {
                var cancellationTask = wsContext.WebSocket.ReceiveAsync(new ArraySegment <byte>(new byte[1024]), CancellationToken.None);
                _webSockets.Add(wsContext.WebSocket, new Pair <int, Task>
                {
                    First  = userId,
                    Second = cancellationTask
                });
            }
        }
Exemplo n.º 3
0
        private void HandleLogin(HttpListenerContext context)
        {
            LoginRequest request;

            try
            {
                request = RestMethods.ReadBody <LoginRequest>(context.Request);
            }
            catch (ArgumentException e)
            {
                RestMethods.WriteError(context.Response, HttpStatusCode.BadRequest, e.Message);
                return;
            }

            if (_usernames.TryGetValue(request.Username, out int id))
            {
                if (_users[id].Online)
                {
                    context.Response.AppendHeader(HttpResponseHeader.WwwAuthenticate.ToString(), "Token realm = 'Username is already in use'");
                    RestMethods.WriteError(context.Response, HttpStatusCode.Unauthorized, "username is already in use");
                    return;
                }

                _users.TryRemove(id, out _);
                _usernames.TryRemove(request.Username, out id);
                _tokens.TryRemove(_tokens.First(tokenId => tokenId.Value == id).Key, out id);
            }

            lock (this)
            {
                id = ++_userId;
            }

            var token = Convert.ToBase64String(Guid.NewGuid().ToByteArray())
                        .TrimEnd(Padding)
                        .Replace('+', '-')
                        .Replace('/', '_');

            var loginResponse = new LoginResponse
            {
                Username = request.Username,
                Id       = id,
                Online   = true,
                Token    = token
            };

            var user = new User
            {
                Username = loginResponse.Username,
                Id       = id,
                Online   = true
            };

            lock (_usernames)
            {
                if (!_usernames.TryAdd(loginResponse.Username, id))
                {
                    context.Response.AppendHeader(HttpResponseHeader.WwwAuthenticate.ToString(), "Token realm = 'Username is already in use'");
                    RestMethods.WriteError(context.Response, HttpStatusCode.Unauthorized, "username is already in use");
                }
                _users.TryAdd(id, user);
                _tokens.TryAdd(token, id);
            }

            SendToAllSubscribers(WebSocketJsonType.User, user);

            RestMethods.WriteToResponse(context.Response, loginResponse);
        }
Exemplo n.º 4
0
        void Run()
        {
            Router router = new Router();

            RestMethods restMethods = new RestMethods(VerifyToken);

            router.AddHandler("/subscribe", HttpMethod.Get, Subscribe);

            router.AddHandler("/login", HttpMethod.Post, HandleLogin);
            router.AddHandler("/logout", HttpMethod.Post, HandleLogout);

            router.AddHandler("/users", HttpMethod.Get,
                              (context) =>
            {
                restMethods.PerformGet <User>(context, GetUsersByQuery);
            }
                              );
            router.AddHandler("/users/" + Router.IntegerUrlParameter, HttpMethod.Get,
                              (context) => restMethods.PerformGetById <User>(context, _users.TryGetValue,
                                                                             context.Request.Url.Segments[2])
                              );

            router.AddHandler("/messages", HttpMethod.Post,
                              (context) => restMethods.PerformPost <Message>(context, AddMessage)
                              );
            router.AddHandler("/messages", HttpMethod.Get,
                              (context) =>
            {
                restMethods.PerformGet <Message>(context, GetMessagesByQuery);
            }
                              );
            router.AddHandler("/messages/" + Router.IntegerUrlParameter, HttpMethod.Get,
                              (context) => restMethods.PerformGetById <Message>(context, _messages.TryGetValue,
                                                                                context.Request.Url.Segments[2])
                              );
            router.AddHandler("/messages/" + Router.IntegerUrlParameter, HttpMethod.Delete,
                              (context) => restMethods.PerformDelete(context,
                                                                     DeleteMessage, context.Request.Url.Segments[2])
                              );

            using (HttpListener httpListener = new HttpListener())
            {
                httpListener.Prefixes.Add("http://localhost:" + _port + "/");
                httpListener.Start();

                while (true)
                {
                    var context = httpListener.GetContext();
                    var request = context.Request;
                    var t       = new Thread(() =>
                    {
                        if (router.TryGetHandler(request, out HandlerFunc handler))
                        {
                            handler(context);
                        }
                        else
                        {
                            RestMethods.WriteError(context.Response, HttpStatusCode.BadRequest, "no handler provided");
                        }
                    });
                    t.Start();
                }
            }
        }
Exemplo n.º 5
0
        private bool VerifyToken(HttpListenerRequest request)
        {
            var token = RestMethods.GetToken(request);

            return(_tokens.ContainsKey(token));
        }