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(); } } }); }
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(); } }); }
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(); } } }
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; } } } }