mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2025-06-27 05:23:13 +00:00
Add project files.
This commit is contained in:
346
Esiur/Net/HTTP/HTTPConnection.cs
Normal file
346
Esiur/Net/HTTP/HTTPConnection.cs
Normal file
@ -0,0 +1,346 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Net;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Esiur.Net.Sockets;
|
||||
using Esiur.Data;
|
||||
using Esiur.Net.Packets;
|
||||
using Esiur.Misc;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Esiur.Net.HTTP
|
||||
{
|
||||
//[Serializable]
|
||||
public class HTTPConnection : NetworkConnection
|
||||
{
|
||||
/*
|
||||
public enum SendOptions : int
|
||||
{
|
||||
AllCalculateLength,
|
||||
AllDontCalculateLength,
|
||||
SpecifiedHeadersOnly,
|
||||
DataOnly
|
||||
}
|
||||
*/
|
||||
|
||||
public HTTPConnection()
|
||||
{
|
||||
Response = new HTTPResponsePacket();
|
||||
variables = new KeyList<string, object>();
|
||||
}
|
||||
|
||||
public void SetParent(HTTPServer Parent)
|
||||
{
|
||||
Server = Parent;
|
||||
}
|
||||
|
||||
//public bool HeadersSent;
|
||||
|
||||
|
||||
private KeyList<string, object> variables;
|
||||
private bool Busy = false;
|
||||
private DateTime RequestTime = DateTime.MinValue;
|
||||
|
||||
public bool WSMode;
|
||||
private HTTPServer Server;
|
||||
public WebsocketPacket WSRequest;
|
||||
public HTTPRequestPacket Request;
|
||||
public HTTPResponsePacket Response;
|
||||
|
||||
HTTPSession session;
|
||||
|
||||
public KeyList<string, object> Variables
|
||||
{
|
||||
get
|
||||
{
|
||||
return variables;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool IsBusy()
|
||||
{
|
||||
return Busy;
|
||||
}
|
||||
|
||||
|
||||
internal long Parse(byte[] data)
|
||||
{
|
||||
if (WSMode)
|
||||
{
|
||||
// now parse WS protocol
|
||||
WebsocketPacket ws = new WebsocketPacket();
|
||||
|
||||
var pSize = ws.Parse(data, 0, (uint)data.Length);
|
||||
|
||||
|
||||
if (pSize > 0)
|
||||
{
|
||||
WSRequest = ws;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HTTPRequestPacket rp = new HTTPRequestPacket();
|
||||
var pSize = rp.Parse(data, 0, (uint)data.Length);
|
||||
if (pSize > 0)
|
||||
{
|
||||
Request = rp;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
public override void Send(string Response)
|
||||
{
|
||||
Send(Response, SendOptions.AllCalculateLength);
|
||||
}
|
||||
|
||||
public void Send(string Message, SendOptions Options)
|
||||
{
|
||||
|
||||
if (Response.Handled)
|
||||
return;
|
||||
|
||||
if (Response != null)
|
||||
Send(Encoding.Default.GetBytes(Response), Options);
|
||||
else
|
||||
Send((byte[])null, Options);
|
||||
}
|
||||
|
||||
public void Send(MemoryStream ms)
|
||||
{
|
||||
Send(ms.ToArray(), SendOptions.AllCalculateLength);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
// close the connection
|
||||
if (Request.Headers["connection"].ToLower() != "keep-alive" & Connected)
|
||||
Close();
|
||||
}
|
||||
|
||||
public bool Upgrade()
|
||||
{
|
||||
if (IsWebsocketRequest())
|
||||
{
|
||||
string magicString = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
||||
string ret = Request.Headers["Sec-WebSocket-Key"] + magicString;
|
||||
// Compute the SHA1 hash
|
||||
SHA1 sha = SHA1.Create();
|
||||
byte[] sha1Hash = sha.ComputeHash(Encoding.UTF8.GetBytes(ret));
|
||||
Response.Headers["Upgrade"] = Request.Headers["Upgrade"];
|
||||
Response.Headers["Connection"] = Request.Headers["Connection"];// "Upgrade";
|
||||
Response.Headers["Sec-WebSocket-Accept"] = Convert.ToBase64String(sha1Hash);
|
||||
|
||||
if (Request.Headers.ContainsKey("Sec-WebSocket-Protocol"))
|
||||
Response.Headers["Sec-WebSocket-Protocol"] = Request.Headers["Sec-WebSocket-Protocol"];
|
||||
|
||||
//Response.Headers["Sec-WebSocket-Protocol"] = Request.Headers["Sec-WebSocket-Protocol"];
|
||||
//Response.Headers["Origin"] = Request.Headers["Origin"];
|
||||
|
||||
Response.Number = HTTPResponsePacket.ResponseCode.HTTP_SWITCHING;
|
||||
Response.Text = "Switching Protocols";
|
||||
WSMode = true;
|
||||
|
||||
//Send((byte[])null, SendOptions.AllDontCalculateLength);
|
||||
Send();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public HTTPServer Parent
|
||||
{
|
||||
get
|
||||
{
|
||||
return Server;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Send(string data)
|
||||
{
|
||||
Response.Message = Encoding.UTF8.GetBytes(data);
|
||||
Send();
|
||||
}
|
||||
|
||||
public override void Send(byte[] message)
|
||||
{
|
||||
Response.Message = message;
|
||||
Send();
|
||||
}
|
||||
|
||||
public void Send(HTTPResponsePacket.ComposeOptions Options = HTTPResponsePacket.ComposeOptions.AllCalculateLength)
|
||||
{
|
||||
if (Response.Handled)
|
||||
return;
|
||||
|
||||
Busy = true;
|
||||
|
||||
try
|
||||
{
|
||||
Response.Compose(Options);
|
||||
base.Send(Response.Data);
|
||||
|
||||
// Refresh the current session
|
||||
if (session != null)
|
||||
session.Refresh();
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
try
|
||||
{
|
||||
Close();// Server.CloseClient(Connection);
|
||||
}
|
||||
finally { }
|
||||
}
|
||||
finally
|
||||
{
|
||||
Busy = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void CreateNewSession()
|
||||
{
|
||||
if (session == null)
|
||||
{
|
||||
// Create a new one
|
||||
session = Server.CreateSession(Global.GenerateCode(12), 60 * 20);
|
||||
|
||||
HTTPResponsePacket.HTTPCookie cookie = new HTTPResponsePacket.HTTPCookie("SID", session.Id);
|
||||
cookie.Expires = DateTime.MaxValue;
|
||||
cookie.Path = "/";
|
||||
cookie.HttpOnly = true;
|
||||
|
||||
Response.Cookies.Add(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool IsWebsocketRequest()
|
||||
{
|
||||
if (Request.Headers.ContainsKey("connection")
|
||||
&& Request.Headers["connection"].ToLower().Contains("upgrade")
|
||||
&& Request.Headers.ContainsKey("upgrade")
|
||||
&& Request.Headers["upgrade"].ToLower() == "websocket"
|
||||
&& Request.Headers.ContainsKey("Sec-WebSocket-Version")
|
||||
&& Request.Headers["Sec-WebSocket-Version"] == "13"
|
||||
&& Request.Headers.ContainsKey("Sec-WebSocket-Key"))
|
||||
//&& Request.Headers.ContainsKey("Sec-WebSocket-Protocol"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void SendFile(string filename)
|
||||
{
|
||||
if (Response.Handled == true)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
//HTTP/1.1 200 OK
|
||||
//Server: Microsoft-IIS/5.0
|
||||
//Content-Location: http://127.0.0.1/index.html
|
||||
//Date: Wed, 10 Dec 2003 19:10:25 GMT
|
||||
//Content-Type: text/html
|
||||
//Accept-Ranges: bytes
|
||||
//Last-Modified: Mon, 22 Sep 2003 22:36:56 GMT
|
||||
//Content-Length: 1957
|
||||
|
||||
if (!File.Exists(filename))
|
||||
{
|
||||
Response.Number = HTTPResponsePacket.ResponseCode.HTTP_NOTFOUND;
|
||||
Send("File Not Found");//, SendOptions.AllCalculateLength);
|
||||
return;
|
||||
}
|
||||
|
||||
Busy = true;
|
||||
|
||||
System.DateTime FWD = File.GetLastWriteTime(filename);
|
||||
if (Request.Headers.ContainsKey("if-modified-since"))// != DateTime.Parse("12:00:00 AM"))
|
||||
{
|
||||
try
|
||||
{
|
||||
DateTime IMS = DateTime.Parse(Request.Headers["if-modified-since"]);
|
||||
if (FWD <= IMS)
|
||||
{
|
||||
Response.Number = HTTPResponsePacket.ResponseCode.HTTP_NOTMODIFIED;
|
||||
Response.Text = "Not Modified";
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (Response.Number == HTTPResponsePacket.ResponseCode.HTTP_NOTMODIFIED)
|
||||
{
|
||||
Send((byte[])null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fri, 30 Oct 2007 14:19:41 GMT
|
||||
Response.Headers["Last-Modified"] = FWD.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss");
|
||||
FileInfo fi = new FileInfo(filename);
|
||||
Response.Headers["Content-Length"] = fi.Length.ToString();
|
||||
Send(HTTPResponsePacket.ComposeOptions.SpecifiedHeadersOnly);
|
||||
using (var fs = new FileStream(filename, FileMode.Open))
|
||||
{
|
||||
var buffer = new byte[5000];
|
||||
var offset = 0;
|
||||
while (offset < fs.Length)
|
||||
{
|
||||
var n = fs.Read(buffer, offset, buffer.Length);
|
||||
offset += n;
|
||||
base.Send(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Busy = false;
|
||||
|
||||
return;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Busy = false;
|
||||
|
||||
try
|
||||
{
|
||||
Close();
|
||||
}
|
||||
finally { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
58
Esiur/Net/HTTP/HTTPFilter.cs
Normal file
58
Esiur/Net/HTTP/HTTPFilter.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Net;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Esiur.Data;
|
||||
using Esiur.Engine;
|
||||
using Esiur.Resource;
|
||||
|
||||
namespace Esiur.Net.HTTP
|
||||
{
|
||||
|
||||
public abstract class HTTPFilter : IResource
|
||||
{
|
||||
public Instance Instance
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public event DestroyedEvent OnDestroy;
|
||||
|
||||
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
|
||||
|
||||
/*
|
||||
public virtual void SessionModified(HTTPSession session, string key, object oldValue, object newValue)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void SessionExpired(HTTPSession session)
|
||||
{
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
public abstract bool Execute(HTTPConnection sender);
|
||||
|
||||
public virtual void ClientConnected(HTTPConnection HTTP)
|
||||
{
|
||||
//return false;
|
||||
}
|
||||
|
||||
public virtual void ClientDisconnected(HTTPConnection HTTP)
|
||||
{
|
||||
//return false;
|
||||
}
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
416
Esiur/Net/HTTP/HTTPServer.cs
Normal file
416
Esiur/Net/HTTP/HTTPServer.cs
Normal file
@ -0,0 +1,416 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Net;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Esiur.Net.Sockets;
|
||||
using Esiur.Data;
|
||||
using Esiur.Misc;
|
||||
using Esiur.Engine;
|
||||
using Esiur.Net.Packets;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Esiur.Resource;
|
||||
|
||||
namespace Esiur.Net.HTTP
|
||||
{
|
||||
public class HTTPServer : NetworkServer<HTTPConnection>, IResource
|
||||
{
|
||||
Dictionary<string, HTTPSession> sessions= new Dictionary<string, HTTPSession>();
|
||||
|
||||
public Instance Instance
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Storable]
|
||||
string ip
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
[Storable]
|
||||
ushort port
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Storable]
|
||||
uint timeout
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Storable]
|
||||
uint clock
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Storable]
|
||||
uint maxPost
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Storable]
|
||||
bool ssl
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Storable]
|
||||
string certificate
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
//public override void ClientConnected(TClient Sender)
|
||||
//{
|
||||
//}
|
||||
/*
|
||||
public DStringDictionary Configurations
|
||||
{
|
||||
get { return config; }
|
||||
}
|
||||
*/
|
||||
|
||||
public enum ResponseCodes : int
|
||||
{
|
||||
HTTP_OK = 200,
|
||||
HTTP_NOTFOUND = 404,
|
||||
HTTP_SERVERERROR = 500,
|
||||
HTTP_MOVED = 301,
|
||||
HTTP_NOTMODIFIED = 304,
|
||||
HTTP_REDIRECT = 307
|
||||
}
|
||||
|
||||
|
||||
public HTTPSession CreateSession(string id, int timeout)
|
||||
{
|
||||
var s = new HTTPSession();
|
||||
|
||||
s.Set(id, timeout);
|
||||
|
||||
|
||||
sessions.Add(id, s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
protected override void SessionModified(NetworkSession session, string key, object oldValue, object newValue)
|
||||
{
|
||||
foreach (var instance in Instance.Children)
|
||||
{
|
||||
var f = (HTTPFilter)instance;
|
||||
f.SessionModified(session as HTTPSession, key, oldValue, newValue);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//public override object InitializeLifetimeService()
|
||||
//{
|
||||
// return null;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static string MakeCookie(string Item, string Value, DateTime Expires, string Domain, string Path, bool HttpOnly)
|
||||
{
|
||||
|
||||
//Set-Cookie: ckGeneric=CookieBody; expires=Sun, 30-Dec-2001 21:00:00 GMT; domain=.com.au; path=/
|
||||
//Set-Cookie: SessionID=another; expires=Fri, 29 Jun 2006 20:47:11 UTC; path=/
|
||||
string Cookie = Item + "=" + Value;
|
||||
|
||||
if (Expires.Ticks != 0)
|
||||
{
|
||||
Cookie += "; expires=" + Expires.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss") + " GMT";
|
||||
}
|
||||
if (Domain != null)
|
||||
{
|
||||
Cookie += "; domain=" + Domain;
|
||||
}
|
||||
if (Path != null)
|
||||
{
|
||||
Cookie += "; path=" + Path;
|
||||
}
|
||||
if (HttpOnly)
|
||||
{
|
||||
Cookie += "; HttpOnly";
|
||||
}
|
||||
return Cookie;
|
||||
}
|
||||
|
||||
protected override void ClientDisconnected(HTTPConnection sender)
|
||||
{
|
||||
Console.WriteLine("OUT: " + this.Connections.Count);
|
||||
|
||||
foreach (IResource resource in Instance.Children)
|
||||
{
|
||||
if (resource is HTTPFilter)
|
||||
{
|
||||
(resource as HTTPFilter).ClientDisconnected(sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected override void DataReceived(HTTPConnection sender, NetworkBuffer data)
|
||||
{
|
||||
//Console.WriteLine(Data);
|
||||
// Initialize a new session
|
||||
//HTTPConnection HTTP = (HTTPConnection)sender.ExtraObject;
|
||||
|
||||
//string Data = System.Text.Encoding.Default.GetString(ReceivedData);
|
||||
|
||||
byte[] msg = data.Read();
|
||||
|
||||
|
||||
|
||||
|
||||
var BL = sender.Parse(msg);
|
||||
|
||||
if (BL == 0)
|
||||
{
|
||||
if (sender.Request.Method == HTTPRequestPacket.HTTPMethod.UNKNOWN)
|
||||
{
|
||||
sender.Close();
|
||||
return;
|
||||
}
|
||||
if (sender.Request.URL == "")
|
||||
{
|
||||
sender.Close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (BL == -1)
|
||||
{
|
||||
data.HoldForNextWrite(msg);
|
||||
return;
|
||||
}
|
||||
else if (BL < 0)
|
||||
{
|
||||
data.HoldFor(msg, (uint) (msg.Length - BL));
|
||||
return;
|
||||
}
|
||||
else if (BL > 0)
|
||||
{
|
||||
if (BL > maxPost)
|
||||
{
|
||||
sender.Send(
|
||||
"<html><body>POST method content is larger than "
|
||||
+ maxPost
|
||||
+ " bytes.</body></html>");
|
||||
|
||||
sender.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
data.HoldFor(msg, (uint)(msg.Length + BL));
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (BL < 0) // for security
|
||||
{
|
||||
sender.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (sender.IsWebsocketRequest() & !sender.WSMode)
|
||||
{
|
||||
sender.Upgrade();
|
||||
//return;
|
||||
}
|
||||
|
||||
|
||||
//return;
|
||||
|
||||
try
|
||||
{
|
||||
foreach (IResource resource in Instance.Children)
|
||||
{
|
||||
if (resource is HTTPFilter)
|
||||
{
|
||||
if ((resource as HTTPFilter).Execute(sender))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sender.Send("Bad Request");
|
||||
sender.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex.Message != "Thread was being aborted.")
|
||||
{
|
||||
|
||||
Global.Log("HTTPServer", LogType.Error, ex.ToString());
|
||||
|
||||
//Console.WriteLine(ex.ToString());
|
||||
//EventLog.WriteEntry("HttpServer", ex.ToString(), EventLogEntryType.Error);
|
||||
sender.Send(Return500(ex.Message));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private string Return500(string sMessage)
|
||||
{
|
||||
string sTMP = null;
|
||||
sTMP = "<HTML><HEAD><TITLE>500 Internal Server Error</TITLE></HEAD><br>\r\n";
|
||||
sTMP = sTMP + "<BODY BGCOLOR=" + (char)(34) + "#FFFFFF" + (char)(34) + " Text=" + (char)(34) + "#000000" + (char)(34) + " LINK=" + (char)(34) + "#0000FF" + (char)(34) + " VLINK=" + (char)(34) + "#000080" + (char)(34) + " ALINK=" + (char)(34) + "#008000" + (char)(34) + "><br>\r\n";
|
||||
sTMP = sTMP + "<b>500</b> Sorry - Internal Server Error<br>" + sMessage + "\r\n";
|
||||
sTMP = sTMP + "</BODY><br>\r\n";
|
||||
sTMP = sTMP + "</HTML><br>\r\n";
|
||||
return sTMP;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
protected override void SessionEnded(NetworkSession session)
|
||||
{
|
||||
// verify wether there are no active connections related to the session
|
||||
|
||||
foreach (HTTPConnection c in Connections)//.Values)
|
||||
{
|
||||
if (c.Session == session)
|
||||
{
|
||||
session.Refresh();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Instance instance in Instance.Children)
|
||||
{
|
||||
var f = (HTTPFilter)instance.Resource;
|
||||
f.SessionExpired((HTTPSession)session);
|
||||
}
|
||||
|
||||
base.SessionEnded((HTTPSession)session);
|
||||
//Sessions.Remove(Session.ID);
|
||||
//Session.Dispose();
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
public int TTL
|
||||
{
|
||||
get
|
||||
{
|
||||
return Timeout;// mTimeout;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
|
||||
{
|
||||
|
||||
if (trigger == ResourceTrigger.Initialize)
|
||||
{
|
||||
//var ip = (IPAddress)Instance.Attributes["ip"];
|
||||
//var port = (int)Instance.Attributes["port"];
|
||||
//var ssl = (bool)Instance.Attributes["ssl"];
|
||||
//var cert = (string)Instance.Attributes["certificate"];
|
||||
|
||||
//if (ip == null) ip = IPAddress.Any;
|
||||
|
||||
ISocket listener;
|
||||
IPAddress ipAdd;
|
||||
|
||||
if (ip == null)
|
||||
ipAdd = IPAddress.Any;
|
||||
else
|
||||
ipAdd = IPAddress.Parse(ip);
|
||||
|
||||
// if (ssl)
|
||||
// listener = new SSLSocket(new IPEndPoint(ipAdd, port), new X509Certificate2(certificate));
|
||||
// else
|
||||
listener = new TCPSocket(new IPEndPoint(ipAdd, port));
|
||||
|
||||
Start(listener,
|
||||
timeout,
|
||||
clock);
|
||||
}
|
||||
else if (trigger == ResourceTrigger.Terminate)
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
else if (trigger == ResourceTrigger.SystemReload)
|
||||
{
|
||||
Trigger(ResourceTrigger.Terminate);
|
||||
Trigger(ResourceTrigger.Initialize);
|
||||
}
|
||||
|
||||
return new AsyncReply<bool>(true);
|
||||
|
||||
}
|
||||
|
||||
protected override void ClientConnected(HTTPConnection sender)
|
||||
{
|
||||
//sender.SessionModified += SessionModified;
|
||||
//sender.SessionEnded += SessionExpired;
|
||||
sender.SetParent(this);
|
||||
|
||||
Console.WriteLine("IN: " + this.Connections.Count);
|
||||
|
||||
foreach (IResource resource in Instance.Children)
|
||||
{
|
||||
if (resource is HTTPFilter)
|
||||
{
|
||||
(resource as HTTPFilter).ClientConnected(sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/*
|
||||
public int LocalPort
|
||||
{
|
||||
get
|
||||
{
|
||||
return cServer.LocalPort;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
public HTTPServer(int Port)
|
||||
{
|
||||
cServer = new TServer();
|
||||
cServer.LocalPort = Port;
|
||||
cServer.StartServer();
|
||||
cServer.ClientConnected += new TServer.eClientConnected(ClientConnected);
|
||||
cServer.ClientDisConnected += new TServer.eClientDisConnected(ClientDisConnected);
|
||||
cServer.ClientIsSwitching += new TServer.eClientIsSwitching(ClientIsSwitching);
|
||||
cServer.DataReceived += new TServer.eDataReceived(DataReceived);
|
||||
|
||||
}*/
|
||||
|
||||
//~HTTPServer()
|
||||
//{
|
||||
// cServer.StopServer();
|
||||
//}
|
||||
}
|
||||
}
|
106
Esiur/Net/HTTP/HTTPSession.cs
Normal file
106
Esiur/Net/HTTP/HTTPSession.cs
Normal file
@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Net;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Esiur.Data;
|
||||
using Esiur.Misc;
|
||||
using Esiur.Engine;
|
||||
|
||||
namespace Esiur.Net.HTTP
|
||||
{
|
||||
public class HTTPSession : IDestructible //<T> where T : TClient
|
||||
{
|
||||
public delegate void SessionModifiedEvent(HTTPSession session, string key, object oldValue, object newValue);
|
||||
public delegate void SessionEndedEvent(HTTPSession session);
|
||||
|
||||
private string id;
|
||||
private Timer timer;
|
||||
private int timeout;
|
||||
DateTime creation;
|
||||
DateTime lastAction;
|
||||
|
||||
private KeyList<string, object> variables;
|
||||
|
||||
public event SessionEndedEvent OnEnd;
|
||||
public event SessionModifiedEvent OnModify;
|
||||
public event DestroyedEvent OnDestroy;
|
||||
|
||||
public KeyList<string, object> Variables
|
||||
{
|
||||
get { return variables; }
|
||||
}
|
||||
|
||||
public HTTPSession()
|
||||
{
|
||||
variables = new KeyList<string, object>();
|
||||
variables.OnModified += new KeyList<string, object>.Modified(VariablesModified);
|
||||
creation = DateTime.Now;
|
||||
}
|
||||
|
||||
internal void Set(string id, int timeout)
|
||||
{
|
||||
//modified = sessionModifiedEvent;
|
||||
//ended = sessionEndEvent;
|
||||
this.id = id;
|
||||
|
||||
if (this.timeout != 0)
|
||||
{
|
||||
this.timeout = timeout;
|
||||
timer = new Timer(OnSessionEndTimerCallback, null, TimeSpan.FromSeconds(timeout), TimeSpan.FromSeconds(0));
|
||||
creation = DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSessionEndTimerCallback(object o)
|
||||
{
|
||||
OnEnd?.Invoke(this);
|
||||
}
|
||||
|
||||
void VariablesModified(string key, object oldValue, object newValue)
|
||||
{
|
||||
OnModify?.Invoke(this, key, oldValue, newValue);
|
||||
}
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
OnDestroy?.Invoke(this);
|
||||
timer.Dispose();
|
||||
timer = null;
|
||||
}
|
||||
|
||||
internal void Refresh()
|
||||
{
|
||||
lastAction = DateTime.Now;
|
||||
timer.Change(TimeSpan.FromSeconds(timeout), TimeSpan.FromSeconds(0));
|
||||
}
|
||||
|
||||
public int Timeout // Seconds
|
||||
{
|
||||
get
|
||||
{
|
||||
return timeout;
|
||||
}
|
||||
set
|
||||
{
|
||||
timeout = value;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public string Id
|
||||
{
|
||||
get { return id; }
|
||||
}
|
||||
|
||||
public DateTime LastAction
|
||||
{
|
||||
get { return lastAction; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
51
Esiur/Net/HTTP/IIPoWS.cs
Normal file
51
Esiur/Net/HTTP/IIPoWS.cs
Normal file
@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Esiur.Resource;
|
||||
using Esiur.Net.IIP;
|
||||
using Esiur.Net.Sockets;
|
||||
using Esiur.Engine;
|
||||
|
||||
namespace Esiur.Net.HTTP
|
||||
{
|
||||
public class IIPoWS: HTTPFilter
|
||||
{
|
||||
public override bool Execute(HTTPConnection sender)
|
||||
{
|
||||
if (sender.Request.Filename.StartsWith("/iip/"))
|
||||
{
|
||||
// find the service
|
||||
var path = sender.Request.Filename.Substring(5);// sender.Request.Query["path"];
|
||||
|
||||
|
||||
Warehouse.Get(path).Then((r) =>
|
||||
{
|
||||
if (r is DistributedServer)
|
||||
{
|
||||
var httpServer = sender.Parent;
|
||||
var iipServer = r as DistributedServer;
|
||||
var tcpSocket = sender.Unassign();
|
||||
var wsSocket = new WSSocket(tcpSocket);
|
||||
httpServer.Connections.Remove(sender);
|
||||
var iipConnection = new DistributedConnection();
|
||||
iipConnection.Server = iipServer;
|
||||
iipConnection.Assign(wsSocket);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override AsyncReply<bool> Trigger(ResourceTrigger trigger)
|
||||
{
|
||||
return new AsyncReply<bool>(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user