Example #1
0
        private async Task <UploadFileStream> handleRequest(RequestParameters requestParameters,
                                                            HttpResponseSender responseSender)
        {
            UploadFileStream ret = null;

            if (requestParameters.endPoint == "/upload.json")
            {
                if (requestParameters.method != "POST")
                {
                    throw new Http400Exception();
                }
                ret = new UploadFileStream(requestParameters.boundary);
            }
            else if (requestParameters.method == "GET" &&
                     requestParameters.endPoint.StartsWith("/downloads/"))
            {
                await responseSender.serveMediaFile(requestParameters.endPoint);
            }
            else if (requestParameters.method == "GET")
            {
                await responseSender.serveStaticFile(requestParameters.endPoint);
            }
            else
            {
                throw new Http404Exception();
            }

            return(ret);
        }
        public Func <HttpRequest, HttpResponse, ClaimsPrincipal, RouteData, Func <Task>, Task> UserInRoles(
            string[] roles)
        {
            return(async(request, response, user, routeData, next) =>
            {
                if (user == null || !user.Identity.IsAuthenticated)
                {
                    await HttpResponseSender.SendErrorAsync(
                        response,
                        new UnauthorizedException(
                            null, "NOT_SIGNED",
                            "User must be signed in to perform this operation"
                            ).WithStatus(401)
                        );
                }
                else
                {
                    var authorized = false;

                    foreach (var role in roles)
                    {
                        if (user.IsInRole(role))
                        {
                            authorized = true;
                            break;
                        }
                    }

                    if (!authorized)
                    {
                        await HttpResponseSender.SendErrorAsync(
                            response,
                            new UnauthorizedException(
                                null, "NOT_IN_ROLE",
                                "User must be " + String.Join(" or ", roles) + " to perform this operation"
                                ).WithDetails("roles", roles).WithStatus(403)
                            );
                    }
                    else
                    {
                        await next();
                    }
                }
            });
        }
Example #3
0
 public Func <HttpRequest, HttpResponse, ClaimsPrincipal, RouteData, Func <Task>, Task> Signed()
 {
     return
         (async(request, response, user, routeData, next) =>
     {
         if (user == null || !user.Identity.IsAuthenticated)
         {
             await HttpResponseSender.SendErrorAsync(
                 response,
                 new UnauthorizedException(
                     null, "NOT_SIGNED",
                     "User must be signed in to perform this operation"
                     ).WithStatus(401)
                 );
         }
         else
         {
             await next();
         }
     });
 }
Example #4
0
        public Func <HttpRequest, HttpResponse, ClaimsPrincipal, RouteData, Func <Task>, Task> OwnerOrAdmin(
            string idParam = "user_id")
        {
            return(async(request, response, user, routeData, next) =>
            {
                if (user == null || !user.Identity.IsAuthenticated)
                {
                    await HttpResponseSender.SendErrorAsync(
                        response,
                        new UnauthorizedException(
                            null, "NOT_SIGNED",
                            "User must be signed in to perform this operation"
                            ).WithStatus(401)
                        );
                }
                else
                {
                    var identity = user.Identity as ClaimsIdentity;
                    var userIdClaim = identity?.Claims.FirstOrDefault(c =>
                                                                      c.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier");
                    var isAdmin = user.IsInRole("Admin") || user.IsInRole("admin");

                    if (!request.Query.TryGetValue(idParam, out StringValues userId) ||
                        userIdClaim?.Value != userId.ToString() && !isAdmin)
                    {
                        await HttpResponseSender.SendErrorAsync(
                            response,
                            new UnauthorizedException(
                                null, "FORBIDDEN",
                                "Only data owner can perform this operation"
                                ).WithStatus(403)
                            );
                    }
                    else
                    {
                        await next();
                    }
                }
            });
        }
        private void CloseConnection(HttpResponseSender clientContext)
        {
            using (EneterTrace.Entering())
            {
                if (!clientContext.IsDisposed)
                {
                    try
                    {
                        // Send close connection message.
                        object anEncodedMessage = myProtocolFormatter.EncodeCloseConnectionMessage(clientContext.ResponseReceiverId);
                        clientContext.SendResponseMessage(anEncodedMessage);
                    }
                    catch (Exception err)
                    {
                        EneterTrace.Warning("failed to send the close message.", err);
                    }

                    // Note: the client context will be removed by the timer.
                    //       The reason is the client can still poll for messages which are stored in the HttpResponseSender.
                    clientContext.Dispose();
                }
            }
        }
Example #6
0
        private async void ProcessRequestAsync(StreamSocket socket)
        {
            HttpResponseSender responseSender = new HttpResponseSender(socket);

            try
            {
                using (IInputStream input = socket.InputStream)
                {
                    byte[]  data   = new byte[BufferSize];
                    IBuffer buffer = data.AsBuffer();

                    MemoryStream     headerStream     = new MemoryStream();
                    UploadFileStream uploadFileStream = null;

                    RequestParameters requestParameters = null;
                    bool  headerParsed          = false;
                    ulong payloadLengthReceived = 0;
                    while (true)
                    {
                        buffer = await input.ReadAsync(buffer, BufferSize, InputStreamOptions.Partial);

                        if (buffer.Length == 0)
                        {
                            break; // Connection closed.
                        }
                        if (headerParsed)
                        {
                            if (uploadFileStream != null)
                            {
                                await uploadFileStream.WriteAsync(buffer);
                            }
                            payloadLengthReceived += buffer.Length;
                        }
                        else
                        {
                            await headerStream.WriteAsync(buffer.ToArray(), 0, (int)buffer.Length);

                            headerParsed = parseHeader(headerStream.ToArray(), out requestParameters);
                            Debug.WriteLine("hasHeader: " + headerParsed);

                            if (headerParsed)
                            {
                                uploadFileStream = await handleRequest(requestParameters, responseSender);

                                if (uploadFileStream != null)
                                {
                                    ulong length = buffer.Length - requestParameters.payloadOffset;
                                    if (length > 0)
                                    {
                                        IBuffer tempPayloadBuffer = headerStream.ToArray().AsBuffer(
                                            (int)requestParameters.payloadOffset, (int)length);
                                        await uploadFileStream.WriteAsync(tempPayloadBuffer);

                                        payloadLengthReceived += length;
                                    }
                                }
                            }
                        }

                        // End of request with a payload upload
                        if (uploadFileStream != null &&
                            payloadLengthReceived == requestParameters.payloadLength)
                        {
                            await responseSender.simpleOK();

                            // TODO: remove the file if it cannot be indexed?
                            bool success = await Locator.MediaLibrary.DiscoverMediaItemOrWaitAsync(
                                uploadFileStream.getStorageFile(), false);

                            if (success == false)
                            {
                                await uploadFileStream.getStorageFile().DeleteAsync();
                            }
                            break;
                        }

                        // End of request without required payload
                        if (uploadFileStream == null && headerParsed)
                        {
                            break;
                        }
                    }
                }
            }
            catch (Http400Exception)
            {
                await responseSender.error400();
            }
            catch (Http404Exception)
            {
                await responseSender.error404();
            }
            catch (System.IO.FileNotFoundException)
            {
                await responseSender.error404();
            }
            catch (System.Runtime.InteropServices.COMException)
            {
                // Assume the socket was closed, so don't send an error back
                return;
            }
            catch
            {
                await responseSender.error500();
            }
        }
        private void HandleConnection(HttpListenerContext httpRequestContext)
        {
            using (EneterTrace.Entering())
            {
                // If polling. (when client polls to get response messages)
                if (httpRequestContext.Request.HttpMethod.ToUpperInvariant() == "GET")
                {
                    // Get responseReceiverId.
                    string[] aQueryItems = httpRequestContext.Request.Url.Query.Split('&');
                    if (aQueryItems.Length > 0)
                    {
                        string aResponseReceiverId = aQueryItems[0].Substring(4);

                        // Find the client.
                        HttpResponseSender aClientContext;
                        using (ThreadLock.Lock(myConnectedClients))
                        {
                            aClientContext = myConnectedClients.FirstOrDefault(x => x.ResponseReceiverId == aResponseReceiverId);
                        }

                        if (aClientContext != null)
                        {
                            // Response collected messages.
                            byte[] aMessages = aClientContext.DequeueCollectedMessages();
                            if (aMessages != null)
                            {
                                httpRequestContext.SendResponseMessage(aMessages);
                            }
                        }
                        else
                        {
                            // Note: This happens when the polling runs and the connection is not open yet.
                            //       It is a normal situation because the polling thread on the client starts
                            //       slightly before the connection is open.
                        }
                    }
                    else
                    {
                        EneterTrace.Warning("Incorrect query format detected for HTTP GET request.");

                        // The request was not processed.
                        httpRequestContext.Response.StatusCode = 404;
                    }
                }
                else
                // Client sends a request message.
                {
                    byte[] aMessage = httpRequestContext.GetRequestMessage();

                    IPEndPoint anEndPoint = httpRequestContext.Request.RemoteEndPoint;
                    string     aClientIp  = (anEndPoint != null) ? anEndPoint.Address.ToString() : "";

                    ProtocolMessage aProtocolMessage = myProtocolFormatter.DecodeMessage(aMessage);

                    bool anIsProcessingOk = true;
                    if (aProtocolMessage != null && !string.IsNullOrEmpty(aProtocolMessage.ResponseReceiverId))
                    {
                        MessageContext aMessageContext = new MessageContext(aProtocolMessage, aClientIp);

                        if (aProtocolMessage.MessageType == EProtocolMessageType.OpenConnectionRequest)
                        {
                            using (ThreadLock.Lock(myConnectedClients))
                            {
                                HttpResponseSender aClientContext = myConnectedClients.FirstOrDefault(x => x.ResponseReceiverId == aProtocolMessage.ResponseReceiverId);
                                if (aClientContext != null && aClientContext.IsDisposed)
                                {
                                    // The client with the same id exists but was closed and disposed.
                                    // It is just that the timer did not remove it. So delete it now.
                                    myConnectedClients.Remove(aClientContext);

                                    // Indicate the new client context shall be created.
                                    aClientContext = null;
                                }

                                if (aClientContext == null)
                                {
                                    aClientContext = new HttpResponseSender(aProtocolMessage.ResponseReceiverId, aClientIp);
                                    myConnectedClients.Add(aClientContext);

                                    // If this is the only sender then start the timer measuring the inactivity to detect if the client is disconnected.
                                    // If it is not the only sender, then the timer is already running.
                                    if (myConnectedClients.Count == 1)
                                    {
                                        myResponseReceiverInactivityTimer.Change(myResponseReceiverInactivityTimeout, -1);
                                    }
                                }
                                else
                                {
                                    EneterTrace.Warning(TracedObject + "could not open connection for client '" + aProtocolMessage.ResponseReceiverId + "' because the client with same id is already connected.");
                                    anIsProcessingOk = false;
                                }
                            }
                        }
                        else if (aProtocolMessage.MessageType == EProtocolMessageType.CloseConnectionRequest)
                        {
                            using (ThreadLock.Lock(myConnectedClients))
                            {
                                HttpResponseSender aClientContext = myConnectedClients.FirstOrDefault(x => x.ResponseReceiverId == aProtocolMessage.ResponseReceiverId);

                                if (aClientContext != null)
                                {
                                    // Note: the disconnection comes from the client.
                                    //       It means the client closed the connection and will not poll anymore.
                                    //       Therefore the client context can be removed.
                                    myConnectedClients.Remove(aClientContext);
                                    aClientContext.Dispose();
                                }
                            }
                        }

                        if (anIsProcessingOk)
                        {
                            NotifyMessageContext(aMessageContext);
                        }
                    }

                    if (!anIsProcessingOk)
                    {
                        // The request was not processed.
                        httpRequestContext.Response.StatusCode = 404;
                    }
                }
            }
        }