/// <summary> /// Dispose of the cache instance. /// </summary> public void Dispose() { _queue.Dispose(); _lock.Take(); foreach (var entry in _lookup) { _onRemoved.Run(entry.Value.ArgD); } _lookup = null; _lock.Release(); }
/// <summary> /// On a new web client connecting to the site server. /// </summary> protected virtual void OnConnection(HttpConnection connection) { if (connection == null) { return; } try { if (connection.Client == null) { connection.Dispose(); return; } // subscribe to the client web requests connection.Client.OnReceive = new ActionSet <HttpRequest>(OnRequest); connection.Client.OnError = new ActionSet <Exception, HttpConnection>(OnReceiveError, null, connection); // has the callback been assigned? yes, run it if (_onConnection != null) { _onConnection.Run(connection); } } catch (Exception ex) { Log.Error("Error OnConnection.", ex); } }
/// <summary> /// On a new tcp client connection. /// </summary> protected void OnClient(TcpClient tcpClient) { // are we still running? no, skip if (_stopped) { return; } // does the socket indicate connection? if (tcpClient.Connected) { // yes, create a new connection for the tcp client var connection = new HttpConnection(this, tcpClient); // add the connection Connections.Add(connection); // run the client callback if (_onConnection != null) { _onConnection.Run(connection); } } else { // dispose of the client tcpClient.Close(); } }
//----------------------------------// /// <summary> /// Process an exception occurance. /// </summary> protected void ProcessError(Exception ex) { if (_onError.Action == null) { _lock.Take(); if (_onError.Action == null) { Log.Error("Exception in udp connection.", ex); _errors.Add(ex); _lock.Release(); } else { _lock.Release(); _onError.Run(ex); } } else { _onError.Run(ex); } }
/// <summary> /// Get a udp connection to the specified endpoint. /// </summary> public UdpConnection GetConnection(IPEndPoint remoteEndpoint) { // has the server been stopped? yes, throw if (_stopped) { throw new InvalidOperationException("The server is stopped."); } // try get an existing connection for the specified endpoint UdpConnection connection; if (_connections.TakeItem().TryGetValue(remoteEndpoint, out connection)) { _connections.Release(); return(connection); } try { // create the new connection connection = new UdpConnection(this, _socket, remoteEndpoint); connection.OnError = new ActionSet <Exception, UdpConnection>(OnConnectionError, (Exception)null, connection); } catch (Exception ex) { Log.Error("Exception creating connection from '" + _socket.LocalEndPoint + "' to '" + remoteEndpoint + "'.", ex); return(null); } // add the new connection to the collection _connections.Item.Add(remoteEndpoint, connection); _connections.Release(); // run callback on connection _onConnection.Run(connection); // return the new connnection return(connection); }
/// <summary> /// On a client being accepted by the listenner. /// </summary> private void OnAcceptClient(IAsyncResult result) { if (_stopped) { return; } try { TcpClient client = _listener.EndAcceptTcpClient(result); _onClient.Run(client); } catch (Exception ex) { Log.Error("Accepting client exception.", ex); } ManagerUpdate.Control.AddSingle(Listen); }
/// <summary> /// Add a request. /// </summary> internal void AddRequest(HttpRequest request) { _lock.Take(); // yes, has the callback method been assigned? if (OnRequest.Action == null) { // no, add to the backlog of requests _requests.Add(request); _lock.Release(); } else { // yes, run the callback immediately _lock.Release(); OnRequest.Run(request); } }
/// <summary> /// Run the route callback. /// </summary> public void Run(string path, HttpRequest request) { OnResolve.Run(path, request); }
/// <summary> /// Resolve the specified path. /// </summary> public void Resolve(string path, HttpMethod method, HttpRequest value) { path = path.ToLowercase(); // get the index of the start of the params int subPathIndex = path.IndexOf(Chars.Question); string paramsSegment = null; string[] segments; // was the params index found? if (subPathIndex == -1) { // split the path into segments segments = path.Split(Chars.ForwardSlash); } else { // split the path into path and params Struct <string, string> sections = path.Split(subPathIndex, 0, -1); // split the path into segments segments = sections.ArgA.Split(Chars.ForwardSlash); // persist the params segment paramsSegment = sections.ArgB; } int index = 0; if (segments[index] == string.Empty) { ++index; } Route route = null; var builder = StringBuilderCache.Get(); bool first = true; subPathIndex = 0; // iterate while (index < segments.Length) { if (first) { first = false; } else { builder.Append(Chars.ForwardSlash); } builder.Append(segments[index]); ++index; // does the path have a callback? ArrayRig <Route> routes; if (_routes.TryGetValue(builder.ToString(), out routes)) { // yes, check the method foreach (var r in routes) { if (r.Methods.Is(method)) { // persist the longest path with callback route = r; subPathIndex = builder.Length; } } } } // get the sub path string subPath; if (subPathIndex == 0) { subPath = builder.ToString(); } else if (builder.Length == subPathIndex) { subPath = string.Empty; } else { subPath = builder.ToString(subPathIndex + 1, builder.Length - subPathIndex - 1); } StringBuilderCache.Set(builder); // has the callback been set? if (route == null) { // no, has the default callback been set? if (DefaultCallback == null) { // no, log the error Log.Error("No default callback set. Request for '" + path + "' went unresolved."); return; } // set the default callback DefaultCallback.Run(subPath, value); } else { // run route callback route.Run(subPath, value); } }
/// <summary> /// On data being received by the local end point. /// </summary> internal void OnReceived(IPEndPoint endpoint, byte[] bytes, int count) { // should the client receive? if (_disposed) { // no, cache the buffer BufferCache.Set(bytes); // skip return; } // should the endpoint be received from? if (RemoteEndPoint.Port != endpoint.Port || !RemoteEndPoint.Address.Equals(endpoint.Address)) { // no, cache the buffer BufferCache.Set(bytes); // log a warning Log.Warning("Connection " + this + " received from incorrect endoint '" + endpoint + "'."); return; } // reset the timeout if (_timeoutTimer != null) { _timeoutTimer.Reset(_timeoutMilliseconds); } int index = 0; _lock.Take(); try { // while the bytes received haven't been completely parsed while (count != 0) { // try passing the received bytes to the current request int added = _message.TryAdd(bytes, index, count); // has the request been completed? if (_message.Complete) { // has the callback on requests been specified? if (_onMessage.Action == null) { // no, add to the backlog collection _messages.Add(_message); } else { // yes, run the callback _onMessage.Run(_message); } // construct a new message to receive bytes _message = new UdpMessage(this); } else if (added == -1) { _lock.Release(); // no, there was an error, possibly with the format of the request // callback with the error ProcessError(new Exception(_message.ErrorMessage)); // re-allocate the buffer BufferCache.Set(bytes); return; } // increment the index index += added; // decrement the number of bytes received that are still to be processed count -= added; } _lock.Release(); } catch (Exception ex) { // replace a potentially corrupt message _message.Dispose(); _message = new UdpMessage(this); _lock.Release(); Log.Error("Exception processing message.", ex); // process the exception ProcessError(ex); return; } }
//----------------------------------// /// <summary> /// On a web request from a client. /// </summary> protected virtual void OnRequest(HttpRequest request) { // is the client allowed the specified resource? if (!ResolvePath(request)) { // no, is the not authenticated callback set? if (_onAccessDenied != null) { // yes, run it _onAccessDenied.Run(request); return; } // log the access denial Log.Warning("Access to unauthorized resource '" + request.RequestPath + "' from '" + request.Connection + "'."); // send the default error page to the client SendErrorPage(request.Connection, "Invalid page request '" + request.RequestPath + "'."); // skip the remaining process return; } // get the page web resource WebResource resource = GetResource(request.RequestPath); // dispose of the web request request.Dispose(); // is the resource valid? if (resource.Valid) { // yes, is there a default wrapper for the resource? if (_configuration["Wrappers"].DictionarySet) { // get the wrapper node for the resource mime type Node wrapperNode = _configuration["Wrappers"][resource.MimeType]; if (wrapperNode.Set) { // yes, get the default wrapper new ElementParser(ResolvePath(wrapperNode.String), new ActionSet <ElementParser, HttpConnection, WebResource>(OnWrapperParsed)).Run(); return; } } // just start sending the resource request.Connection.Send(resource); } else { // no, has the invalid resource callback been assigned? if (_onInvalidResource.Action != null) { // yes, run the callback _onInvalidResource.ArgA = request; _onInvalidResource.Run(); // skip error page return; } // send an error page in response SendErrorPage(request.Connection, "Invalid page request '" + resource.Path + "'"); } }