/// <summary> /// register a HTTP service, will forward message to the URL it has registered /// </summary> /// <param name="service"></param> /// <returns>true if success</returns> internal void RegisterHttpEndpoint(HttpEndpointBase service) { lock (staLock) { lock (m_endpoints) { lock (m_listeners) { if (!m_listeners.ContainsKey(service.Port)) { throw new Exception("Http Service is not initialized to listen port: " + service.Port); } if (service.IsSSL) { if (m_listeners[service.Port].PortInfo.ServerCertificate == null) { throw new Exception("Port " + service.Port.ToString() + " does not register a server certificate"); } } } // try to find duplicattion //if port is using if (m_endpoints.ContainsKey(service.Port)) { List <HttpEndpointBase> endpoints = m_endpoints[service.Port]; foreach (HttpEndpointBase b in endpoints) { foreach (string u in service.Urls) { foreach (string b_u in b.Urls) { //found duplicated url in same port if (0 == string.Compare(u.ToLower(), b_u.ToLower())) { throw new Exception("Duplicated Url is regsitered: " + u); } } } } } else { //if port is not using m_endpoints.Add(service.Port, new List <HttpEndpointBase>()); } m_endpoints[service.Port].Add(service); } } }
/// <summary> /// Tcp Client thread /// </summary> /// <param name="o"></param> private void ReceiveLoop(object o) { ManagedStream ms = o as ManagedStream; TimeSpan idleTime = TimeSpan.FromMilliseconds(0); TimeSpan sleepTime = TimeSpan.FromMilliseconds(200); Stream s; HttpEndpointBase usedEndpoint = null; TcpClient c = ms.LocalTcpClient; // id it's using SSL, must authenticate self as server firstly if (ms.PortInfo.IsSSL) { SslStream ssl = new SslStream(c.GetStream(), true); try { ssl.AuthenticateAsServer(ms.PortInfo.ServerCertificate, false, System.Security.Authentication.SslProtocols.Tls, false); } catch (Exception e) { lock (eventPipe) { ManagedEvent exp = new ManagedEvent(); exp.EventType = EventType.Exception; exp.Exception = e; eventPipe.Enqueue(exp); return; } } s = ssl; } else { s = c.GetStream(); } ms.LocalStream = s; using (s) { while (this.running && idleTime < this.idleTimeout) { // if no data available, wait for a while if (c.Available == 0) { Thread.Sleep(sleepTime); idleTime += sleepTime; } // if data coming else { idleTime = TimeSpan.FromMilliseconds(0); byte[] data; // receive data using (var t = new MemoryStream()) { var buf = new byte[c.ReceiveBufferSize]; lock (ms) { do { var bytes = s.Read(buf, 0, buf.Length); t.Write(buf, 0, bytes); } while (c.Available > 0); ms.LastUsed = DateTime.Now; } data = t.ToArray(); } // pack as ManagedEvent var e = new ManagedEvent(); e.Data = data; e.Sender = c.Client.RemoteEndPoint as IPEndPoint; e.EventType = EventType.IncomingRequest; //parse the endpoint string str = Encoding.UTF8.GetString(data); e.Text = str; // try to parse as http try { HttpRequest req = new HttpRequest(); req.Parse(e.Text); e.ParsedHttpRequest = req; } catch { } if (usedEndpoint == null) { if (e.ParsedHttpRequest == null) { //first message is not http e.EventType = EventType.Exception; e.Exception = new Exception("The 1st request from this context is not an HTTP Request"); } else { lock (m_endpoints) { if (m_endpoints.ContainsKey(ms.PortInfo.Port)) { List <HttpEndpointBase> hebs = m_endpoints[ms.PortInfo.Port]; // find specific endpoint var q = from r in hebs where ( from u in r.Urls where e.ParsedHttpRequest.RequestUrl.Path.ToLower().Contains(u.ToLower()) select u ).Count() > 0 select r; // if found if (q.Any()) { e.ServiceEndpoint = (HttpEndpointBase)q.First(); usedEndpoint = e.ServiceEndpoint; } } } } } else { e.ServiceEndpoint = usedEndpoint; } // if service is auto-run, dispatch to its own pipe if (e.ServiceEndpoint != null && e.ServiceEndpoint.AutoRun) { lock (e.ServiceEndpoint.eventPipe) { e.ServiceEndpoint.eventPipe.Enqueue(e); } } else { lock (eventPipe) { eventPipe.Enqueue(e); } } } } } }