mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2025-06-27 05:23:13 +00:00
Rename
This commit is contained in:
313
Esiur/Net/Packets/HTTPRequestPacket.cs
Normal file
313
Esiur/Net/Packets/HTTPRequestPacket.cs
Normal file
@ -0,0 +1,313 @@
|
||||
|
||||
/*
|
||||
|
||||
Copyright (c) 2017 Ahmed Kh. Zamil
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Esiur.Misc;
|
||||
using Esiur.Data;
|
||||
using System.Net;
|
||||
|
||||
namespace Esiur.Net.Packets
|
||||
{
|
||||
public class HTTPRequestPacket : Packet
|
||||
{
|
||||
|
||||
public enum HTTPMethod:byte
|
||||
{
|
||||
GET,
|
||||
POST,
|
||||
HEAD,
|
||||
PUT,
|
||||
DELETE,
|
||||
OPTIONS,
|
||||
TRACE,
|
||||
CONNECT,
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
public StringKeyList Query;
|
||||
public HTTPMethod Method;
|
||||
public StringKeyList Headers;
|
||||
|
||||
public bool WSMode;
|
||||
|
||||
public string Version;
|
||||
public StringKeyList Cookies; // String
|
||||
public string URL; /// With query
|
||||
public string Filename; /// Without query
|
||||
//public byte[] PostContents;
|
||||
public KeyList<string, object> PostForms;
|
||||
public byte[] Message;
|
||||
|
||||
|
||||
private HTTPMethod getMethod(string method)
|
||||
{
|
||||
switch (method.ToLower())
|
||||
{
|
||||
case "get":
|
||||
return HTTPMethod.GET;
|
||||
case "post":
|
||||
return HTTPMethod.POST;
|
||||
case "head":
|
||||
return HTTPMethod.HEAD;
|
||||
case "put":
|
||||
return HTTPMethod.PUT;
|
||||
case "delete":
|
||||
return HTTPMethod.DELETE;
|
||||
case "options":
|
||||
return HTTPMethod.OPTIONS;
|
||||
case "trace":
|
||||
return HTTPMethod.TRACE;
|
||||
case "connect":
|
||||
return HTTPMethod.CONNECT;
|
||||
default:
|
||||
return HTTPMethod.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "HTTPRequestPacket"
|
||||
+ "\n\tVersion: " + Version
|
||||
+ "\n\tMethod: " + Method
|
||||
+ "\n\tURL: " + URL
|
||||
+ "\n\tMessage: " + (Message != null ? Message.Length.ToString() : "NULL");
|
||||
}
|
||||
|
||||
public override long Parse(byte[] data, uint offset, uint ends)
|
||||
{
|
||||
string[] sMethod = null;
|
||||
string[] sLines = null;
|
||||
|
||||
uint headerSize = 0;
|
||||
|
||||
for (uint i = offset; i < ends - 3; i++)
|
||||
{
|
||||
if (data[i] == '\r' && data[i + 1] == '\n'
|
||||
&& data[i + 2] == '\r' && data[i + 3] == '\n')
|
||||
{
|
||||
sLines = Encoding.ASCII.GetString(data, (int)offset,(int)( i - offset)).Split(new string[] { "\r\n" },
|
||||
StringSplitOptions.None);
|
||||
|
||||
headerSize = i + 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (headerSize == 0)
|
||||
return -1;
|
||||
|
||||
Cookies = new StringKeyList();
|
||||
PostForms = new KeyList<string, object>();
|
||||
Query = new StringKeyList();
|
||||
Headers = new StringKeyList();
|
||||
|
||||
sMethod = sLines[0].Split(' ');
|
||||
Method = getMethod(sMethod[0].Trim());
|
||||
|
||||
if (sMethod.Length == 3)
|
||||
{
|
||||
sMethod[1] = WebUtility.UrlDecode(sMethod[1]);
|
||||
if (sMethod[1].Length >= 7)
|
||||
{
|
||||
if (sMethod[1].StartsWith("http://"))
|
||||
{
|
||||
sMethod[1] = sMethod[1].Substring(sMethod[1].IndexOf("/", 7));
|
||||
}
|
||||
}
|
||||
|
||||
URL = sMethod[1].Trim();
|
||||
|
||||
if (URL.IndexOf("?", 0) != -1)
|
||||
{
|
||||
Filename = URL.Split(new char[] { '?' }, 2)[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
Filename = URL;
|
||||
}
|
||||
|
||||
if (Filename.IndexOf("%", 0) != -1)
|
||||
{
|
||||
Filename = WebUtility.UrlDecode(Filename);
|
||||
}
|
||||
|
||||
Version = sMethod[2].Trim();
|
||||
}
|
||||
|
||||
// Read all headers
|
||||
|
||||
for (int i = 1; i < sLines.Length; i++)
|
||||
{
|
||||
if (sLines[i] == String.Empty)
|
||||
{
|
||||
// Invalid header
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sLines[i].IndexOf(':') == -1)
|
||||
{
|
||||
// Invalid header
|
||||
return 0;
|
||||
}
|
||||
|
||||
string[] header = sLines[i].Split(new char[] { ':' }, 2);
|
||||
|
||||
header[0] = header[0].ToLower();
|
||||
Headers[header[0]] = header[1].Trim();
|
||||
|
||||
if (header[0] == "cookie")
|
||||
{
|
||||
string[] cookies = header[1].Split(';');
|
||||
|
||||
foreach (string cookie in cookies)
|
||||
{
|
||||
if (cookie.IndexOf('=') != -1)
|
||||
{
|
||||
string[] splitCookie = cookie.Split('=');
|
||||
splitCookie[0] = splitCookie[0].Trim();
|
||||
splitCookie[1] = splitCookie[1].Trim();
|
||||
if (!(Cookies.ContainsKey(splitCookie[0].Trim())))
|
||||
Cookies.Add(splitCookie[0], splitCookie[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(Cookies.ContainsKey(cookie.Trim())))
|
||||
{
|
||||
Cookies.Add(cookie.Trim(), String.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Query String
|
||||
if (URL.IndexOf("?", 0) != -1)
|
||||
{
|
||||
string[] SQ = URL.Split(new char[] { '?' }, 2)[1].Split('&');
|
||||
foreach (string S in SQ)
|
||||
{
|
||||
if (S.IndexOf("=", 0) != -1)
|
||||
{
|
||||
string[] qp = S.Split(new char[] { '=' }, 2);
|
||||
|
||||
if (!Query.ContainsKey(WebUtility.UrlDecode(qp[0])))
|
||||
{
|
||||
Query.Add(WebUtility.UrlDecode(qp[0]), WebUtility.UrlDecode(qp[1]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(Query.ContainsKey(WebUtility.UrlDecode(S))))
|
||||
{
|
||||
Query.Add(WebUtility.UrlDecode(S), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Post Content-Length
|
||||
if (Method == HTTPMethod.POST)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
uint postSize = uint.Parse((string)Headers["content-length"]);
|
||||
|
||||
// check limit
|
||||
if (postSize > data.Length - headerSize)
|
||||
return -(postSize - (data.Length - headerSize));
|
||||
|
||||
|
||||
if (
|
||||
Headers["content-type"] == null
|
||||
|| Headers["content-type"] == ""
|
||||
|| Headers["content-type"].StartsWith("application/x-www-form-urlencoded"))
|
||||
{
|
||||
string[] PostVars = null;
|
||||
PostVars = Encoding.UTF8.GetString(data, (int)headerSize, (int)postSize).Split('&');
|
||||
for (int J = 0; J < PostVars.Length; J++)
|
||||
{
|
||||
if (PostVars[J].IndexOf("=") != -1)
|
||||
{
|
||||
string key = WebUtility.HtmlDecode(
|
||||
WebUtility.UrlDecode(PostVars[J].Split(new char[] { '=' }, 2)[0]));
|
||||
if (PostForms.Contains(key))
|
||||
PostForms[key] = WebUtility.HtmlDecode(
|
||||
WebUtility.UrlDecode(PostVars[J].Split(new char[] { '=' }, 2)[1]));
|
||||
else
|
||||
PostForms.Add(key, WebUtility.HtmlDecode(
|
||||
WebUtility.UrlDecode(PostVars[J].Split(new char[] { '=' }, 2)[1])));
|
||||
}
|
||||
else
|
||||
if (PostForms.Contains("unknown"))
|
||||
PostForms["unknown"] = PostForms["unknown"]
|
||||
+ "&" + WebUtility.HtmlDecode(WebUtility.UrlDecode(PostVars[J]));
|
||||
else
|
||||
PostForms.Add("unknown", WebUtility.HtmlDecode(WebUtility.UrlDecode(PostVars[J])));
|
||||
}
|
||||
}
|
||||
else if (Headers["content-type"].StartsWith("multipart/form-data"))
|
||||
{
|
||||
int st = 1;
|
||||
int ed = 0;
|
||||
string strBoundry = "--" + Headers["content-type"].Substring(
|
||||
Headers["content-type"].IndexOf("boundary=", 0) + 9);
|
||||
|
||||
string[] sc = Encoding.UTF8.GetString(data, (int)headerSize, (int)postSize).Split(
|
||||
new string[] { strBoundry }, StringSplitOptions.None);
|
||||
|
||||
|
||||
for (int j = 1; j < sc.Length - 1; j++)
|
||||
{
|
||||
string[] ps = sc[j].Split(new string[] { "\r\n\r\n" }, 2, StringSplitOptions.None);
|
||||
ps[1] = ps[1].Substring(0, ps[1].Length - 2); // remove the empty line
|
||||
st = ps[0].IndexOf("name=", 0) + 6;
|
||||
ed = ps[0].IndexOf("\"", st);
|
||||
PostForms.Add(ps[0].Substring(st, ed - st), ps[1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//PostForms.Add(Headers["content-type"], Encoding.Default.GetString( ));
|
||||
Message = DC.Clip(data, headerSize, postSize);
|
||||
}
|
||||
|
||||
return headerSize + postSize;
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return headerSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
304
Esiur/Net/Packets/HTTPResponsePacket.cs
Normal file
304
Esiur/Net/Packets/HTTPResponsePacket.cs
Normal file
@ -0,0 +1,304 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2017 Ahmed Kh. Zamil
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Esiur.Misc;
|
||||
using Esiur.Data;
|
||||
|
||||
namespace Esiur.Net.Packets
|
||||
{
|
||||
public class HTTPResponsePacket : Packet
|
||||
{
|
||||
|
||||
public enum ComposeOptions : int
|
||||
{
|
||||
AllCalculateLength,
|
||||
AllDontCalculateLength,
|
||||
SpecifiedHeadersOnly,
|
||||
DataOnly
|
||||
}
|
||||
|
||||
public enum ResponseCode : int
|
||||
{
|
||||
Switching= 101,
|
||||
OK = 200,
|
||||
Created = 201,
|
||||
Accepted = 202,
|
||||
NoContent = 204,
|
||||
MovedPermanently = 301,
|
||||
Found = 302,
|
||||
SeeOther = 303,
|
||||
NotModified = 304,
|
||||
TemporaryRedirect = 307,
|
||||
BadRequest = 400,
|
||||
Unauthorized = 401,
|
||||
Forbidden = 403,
|
||||
NotFound = 404,
|
||||
MethodNotAllowed = 405,
|
||||
NotAcceptable = 406,
|
||||
PreconditionFailed = 412,
|
||||
UnsupportedMediaType = 415,
|
||||
InternalServerError = 500,
|
||||
NotImplemented = 501,
|
||||
}
|
||||
|
||||
public struct HTTPCookie
|
||||
{
|
||||
public string Name;
|
||||
public string Value;
|
||||
public DateTime Expires;
|
||||
public string Path;
|
||||
public bool HttpOnly;
|
||||
public string Domain;
|
||||
|
||||
public HTTPCookie(string name, string value)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Value = value;
|
||||
this.Path = null;
|
||||
this.Expires = DateTime.MinValue;
|
||||
this.HttpOnly = false;
|
||||
this.Domain = null;
|
||||
}
|
||||
|
||||
public HTTPCookie(string name, string value, DateTime expires)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Value = value;
|
||||
this.Expires = expires;
|
||||
this.HttpOnly = false;
|
||||
this.Domain = null;
|
||||
this.Path = null;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
//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=/
|
||||
var cookie = Name + "=" + 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;
|
||||
}
|
||||
}
|
||||
|
||||
public StringKeyList Headers = new StringKeyList(true);
|
||||
public string Version = "HTTP/1.1";
|
||||
|
||||
public byte[] Message;
|
||||
public ResponseCode Number;
|
||||
public string Text;
|
||||
|
||||
public List<HTTPCookie> Cookies = new List<HTTPCookie>();
|
||||
public bool Handled;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "HTTPResponsePacket"
|
||||
+ "\n\tVersion: " + Version
|
||||
//+ "\n\tMethod: " + Method
|
||||
//+ "\n\tURL: " + URL
|
||||
+ "\n\tMessage: " + (Message != null ? Message.Length.ToString() : "NULL");
|
||||
}
|
||||
|
||||
private string MakeHeader(ComposeOptions options)
|
||||
{
|
||||
string header = $"{Version} {(int)Number} {Text}\r\nServer: Esiur {Global.Version}\r\nDate: {DateTime.Now.ToUniversalTime().ToString("r")}\r\n";
|
||||
|
||||
if (options == ComposeOptions.AllCalculateLength)
|
||||
Headers["Content-Length"] = Message?.Length.ToString() ?? "0";
|
||||
|
||||
foreach (var kv in Headers)
|
||||
header += kv.Key + ": " + kv.Value + "\r\n";
|
||||
|
||||
|
||||
// Set-Cookie: ckGeneric=CookieBody; expires=Sun, 30-Dec-2007 21:00:00 GMT; path=/
|
||||
// Set-Cookie: ASPSESSIONIDQABBDSQA=IPDPMMMALDGFLMICEJIOCIPM; path=/
|
||||
|
||||
foreach (var Cookie in Cookies)
|
||||
header += "Set-Cookie: " + Cookie.ToString() + "\r\n";
|
||||
|
||||
|
||||
header += "\r\n";
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
|
||||
public bool Compose(ComposeOptions options)
|
||||
{
|
||||
List<byte> msg = new List<byte>();
|
||||
|
||||
if (options != ComposeOptions.DataOnly)
|
||||
{
|
||||
msg.AddRange(Encoding.UTF8.GetBytes(MakeHeader(options)));
|
||||
}
|
||||
|
||||
if (options != ComposeOptions.SpecifiedHeadersOnly)
|
||||
{
|
||||
if (Message != null)
|
||||
msg.AddRange(Message);
|
||||
}
|
||||
|
||||
Data = msg.ToArray();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool Compose()
|
||||
{
|
||||
return Compose(ComposeOptions.AllDontCalculateLength);
|
||||
}
|
||||
|
||||
public override long Parse(byte[] data, uint offset, uint ends)
|
||||
{
|
||||
string[] sMethod = null;
|
||||
string[] sLines = null;
|
||||
|
||||
uint headerSize = 0;
|
||||
|
||||
for (uint i = offset; i < ends - 3; i++)
|
||||
{
|
||||
if (data[i] == '\r' && data[i + 1] == '\n'
|
||||
&& data[i + 2] == '\r' && data[i + 3] == '\n')
|
||||
{
|
||||
sLines = Encoding.ASCII.GetString(data, (int)offset, (int)(i - offset)).Split(new string[] { "\r\n" },
|
||||
StringSplitOptions.None);
|
||||
|
||||
headerSize = i + 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (headerSize == 0)
|
||||
return -1;
|
||||
|
||||
//Cookies = new DStringDictionary();
|
||||
//Headers = new DStringDictionary(true);
|
||||
|
||||
sMethod = sLines[0].Split(' ');
|
||||
|
||||
if (sMethod.Length == 3)
|
||||
{
|
||||
Version = sMethod[0].Trim();
|
||||
Number = (ResponseCode)(Convert.ToInt32(sMethod[1].Trim()));
|
||||
Text = sMethod[2];
|
||||
}
|
||||
|
||||
// Read all headers
|
||||
|
||||
for (int i = 1; i < sLines.Length; i++)
|
||||
{
|
||||
if (sLines[i] == String.Empty)
|
||||
{
|
||||
// Invalid header
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sLines[i].IndexOf(':') == -1)
|
||||
{
|
||||
// Invalid header
|
||||
return 0;
|
||||
}
|
||||
|
||||
string[] header = sLines[i].Split(new char[] { ':' }, 2);
|
||||
|
||||
header[0] = header[0].ToLower();
|
||||
Headers[header[0]] = header[1].Trim();
|
||||
|
||||
//Set-Cookie: NAME=VALUE; expires=DATE;
|
||||
|
||||
if (header[0] == "set-cookie")
|
||||
{
|
||||
string[] cookie = header[1].Split(';');
|
||||
|
||||
if (cookie.Length >= 1)
|
||||
{
|
||||
string[] splitCookie = cookie[0].Split('=');
|
||||
HTTPCookie c = new HTTPCookie(splitCookie[0], splitCookie[1]);
|
||||
|
||||
for (int j = 1; j < cookie.Length; j++)
|
||||
{
|
||||
splitCookie = cookie[j].Split('=');
|
||||
switch (splitCookie[0].ToLower())
|
||||
{
|
||||
case "domain":
|
||||
c.Domain = splitCookie[1];
|
||||
break;
|
||||
case "path":
|
||||
c.Path = splitCookie[1];
|
||||
break;
|
||||
case "httponly":
|
||||
c.HttpOnly = true;
|
||||
break;
|
||||
case "expires":
|
||||
// Wed, 13-Jan-2021 22:23:01 GMT
|
||||
c.Expires = DateTime.Parse(splitCookie[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Content-Length
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
uint contentLength = uint.Parse((string)Headers["content-length"]);
|
||||
|
||||
// check limit
|
||||
if (contentLength > data.Length - headerSize)
|
||||
{
|
||||
return contentLength - (data.Length - headerSize);
|
||||
}
|
||||
|
||||
Message = DC.Clip(data, offset, contentLength);
|
||||
|
||||
return headerSize + contentLength;
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
412
Esiur/Net/Packets/IIPAuthPacket.cs
Normal file
412
Esiur/Net/Packets/IIPAuthPacket.cs
Normal file
@ -0,0 +1,412 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2017 Ahmed Kh. Zamil
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
using Esiur.Data;
|
||||
using Esiur.Security.Authority;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Esiur.Net.Packets
|
||||
{
|
||||
class IIPAuthPacket : Packet
|
||||
{
|
||||
public enum IIPAuthPacketCommand : byte
|
||||
{
|
||||
Action = 0,
|
||||
Declare,
|
||||
Acknowledge,
|
||||
Error,
|
||||
}
|
||||
|
||||
public enum IIPAuthPacketAction : byte
|
||||
{
|
||||
// Authenticate
|
||||
AuthenticateHash,
|
||||
|
||||
|
||||
//Challenge,
|
||||
//CertificateRequest,
|
||||
//CertificateReply,
|
||||
//EstablishRequest,
|
||||
//EstablishReply
|
||||
|
||||
NewConnection = 0x20,
|
||||
ResumeConnection,
|
||||
|
||||
ConnectionEstablished = 0x28
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public IIPAuthPacketCommand Command
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public IIPAuthPacketAction Action
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public byte ErrorCode { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
public AuthenticationMethod LocalMethod
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public byte[] SourceInfo
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public byte[] Hash
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public byte[] SessionId
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public AuthenticationMethod RemoteMethod
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string Domain
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public long CertificateId
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string LocalUsername
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string RemoteUsername
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public byte[] LocalPassword
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public byte[] RemotePassword
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public byte[] LocalToken
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public byte[] RemoteToken
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public byte[] AsymetricEncryptionKey
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public byte[] LocalNonce
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public byte[] RemoteNonce
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public ulong RemoteTokenIndex { get; set; }
|
||||
|
||||
private uint dataLengthNeeded;
|
||||
|
||||
bool NotEnough(uint offset, uint ends, uint needed)
|
||||
{
|
||||
if (offset + needed > ends)
|
||||
{
|
||||
dataLengthNeeded = needed - (ends - offset);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Command.ToString() + " " + Action.ToString();
|
||||
}
|
||||
|
||||
public override long Parse(byte[] data, uint offset, uint ends)
|
||||
{
|
||||
var oOffset = offset;
|
||||
|
||||
if (NotEnough(offset, ends, 1))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Command = (IIPAuthPacketCommand)(data[offset] >> 6);
|
||||
|
||||
if (Command == IIPAuthPacketCommand.Action)
|
||||
{
|
||||
Action = (IIPAuthPacketAction)(data[offset++] & 0x3f);
|
||||
|
||||
if (Action == IIPAuthPacketAction.AuthenticateHash)
|
||||
{
|
||||
if (NotEnough(offset, ends, 32))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Hash = data.Clip(offset, 32);
|
||||
|
||||
//var hash = new byte[32];
|
||||
//Buffer.BlockCopy(data, (int)offset, hash, 0, 32);
|
||||
//Hash = hash;
|
||||
|
||||
offset += 32;
|
||||
}
|
||||
else if (Action == IIPAuthPacketAction.NewConnection)
|
||||
{
|
||||
if (NotEnough(offset, ends, 2))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var length = data.GetUInt16(offset);
|
||||
|
||||
offset += 2;
|
||||
|
||||
if (NotEnough(offset, ends, length))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
SourceInfo = data.Clip(offset, length);
|
||||
|
||||
//var sourceInfo = new byte[length];
|
||||
//Buffer.BlockCopy(data, (int)offset, sourceInfo, 0, length);
|
||||
//SourceInfo = sourceInfo;
|
||||
|
||||
offset += 32;
|
||||
}
|
||||
else if (Action == IIPAuthPacketAction.ResumeConnection
|
||||
|| Action == IIPAuthPacketAction.ConnectionEstablished)
|
||||
{
|
||||
//var sessionId = new byte[32];
|
||||
|
||||
if (NotEnough(offset, ends, 32))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
SessionId = data.Clip(offset, 32);
|
||||
|
||||
//Buffer.BlockCopy(data, (int)offset, sessionId, 0, 32);
|
||||
//SessionId = sessionId;
|
||||
|
||||
offset += 32;
|
||||
}
|
||||
}
|
||||
else if (Command == IIPAuthPacketCommand.Declare)
|
||||
{
|
||||
RemoteMethod = (AuthenticationMethod)((data[offset] >> 4) & 0x3);
|
||||
LocalMethod = (AuthenticationMethod)((data[offset] >> 2) & 0x3);
|
||||
var encrypt = ((data[offset++] & 0x2) == 0x2);
|
||||
|
||||
|
||||
if (NotEnough(offset, ends, 1))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var domainLength = data[offset++];
|
||||
if (NotEnough(offset, ends, domainLength))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var domain = data.GetString(offset, domainLength);
|
||||
|
||||
Domain = domain;
|
||||
|
||||
offset += domainLength;
|
||||
|
||||
|
||||
if (RemoteMethod == AuthenticationMethod.Credentials)
|
||||
{
|
||||
if (LocalMethod == AuthenticationMethod.None)
|
||||
{
|
||||
if (NotEnough(offset, ends, 33))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
//var remoteNonce = new byte[32];
|
||||
//Buffer.BlockCopy(data, (int)offset, remoteNonce, 0, 32);
|
||||
//RemoteNonce = remoteNonce;
|
||||
|
||||
RemoteNonce = data.Clip(offset, 32);
|
||||
|
||||
offset += 32;
|
||||
|
||||
var length = data[offset++];
|
||||
|
||||
if (NotEnough(offset, ends, length))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
RemoteUsername = data.GetString(offset, length);
|
||||
|
||||
|
||||
offset += length;
|
||||
}
|
||||
}
|
||||
else if (RemoteMethod == AuthenticationMethod.Token)
|
||||
{
|
||||
if (LocalMethod == AuthenticationMethod.None)
|
||||
{
|
||||
if (NotEnough(offset, ends, 37))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
RemoteNonce = data.Clip(offset, 32);
|
||||
|
||||
offset += 32;
|
||||
|
||||
RemoteTokenIndex = data.GetUInt64(offset);
|
||||
offset += 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (encrypt)
|
||||
{
|
||||
if (NotEnough(offset, ends, 2))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var keyLength = data.GetUInt16(offset);
|
||||
|
||||
offset += 2;
|
||||
|
||||
if (NotEnough(offset, ends, keyLength))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
//var key = new byte[keyLength];
|
||||
//Buffer.BlockCopy(data, (int)offset, key, 0, keyLength);
|
||||
//AsymetricEncryptionKey = key;
|
||||
|
||||
AsymetricEncryptionKey = data.Clip(offset, keyLength);
|
||||
|
||||
offset += keyLength;
|
||||
}
|
||||
}
|
||||
else if (Command == IIPAuthPacketCommand.Acknowledge)
|
||||
{
|
||||
RemoteMethod = (AuthenticationMethod)((data[offset] >> 4) & 0x3);
|
||||
LocalMethod = (AuthenticationMethod)((data[offset] >> 2) & 0x3);
|
||||
var encrypt = ((data[offset++] & 0x2) == 0x2);
|
||||
|
||||
if (NotEnough(offset, ends, 1))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
|
||||
if (RemoteMethod == AuthenticationMethod.Credentials
|
||||
|| RemoteMethod == AuthenticationMethod.Token)
|
||||
{
|
||||
if (LocalMethod == AuthenticationMethod.None)
|
||||
{
|
||||
if (NotEnough(offset, ends, 32))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
RemoteNonce = data.Clip(offset, 32);
|
||||
offset += 32;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (encrypt)
|
||||
{
|
||||
if (NotEnough(offset, ends, 2))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var keyLength = data.GetUInt16(offset);
|
||||
|
||||
offset += 2;
|
||||
|
||||
if (NotEnough(offset, ends, keyLength))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
//var key = new byte[keyLength];
|
||||
//Buffer.BlockCopy(data, (int)offset, key, 0, keyLength);
|
||||
//AsymetricEncryptionKey = key;
|
||||
|
||||
AsymetricEncryptionKey = data.Clip(offset, keyLength);
|
||||
|
||||
offset += keyLength;
|
||||
}
|
||||
}
|
||||
else if (Command == IIPAuthPacketCommand.Error)
|
||||
{
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
offset++;
|
||||
ErrorCode = data[offset++];
|
||||
|
||||
|
||||
var cl = data.GetUInt16(offset);
|
||||
offset += 2;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ErrorMessage = data.GetString(offset, cl);
|
||||
offset += cl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
return offset - oOffset;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
823
Esiur/Net/Packets/IIPPacket.cs
Normal file
823
Esiur/Net/Packets/IIPPacket.cs
Normal file
@ -0,0 +1,823 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2017 Ahmed Kh. Zamil
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
using Esiur.Data;
|
||||
using Esiur.Core;
|
||||
using Esiur.Misc;
|
||||
using Esiur.Net.Packets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Esiur.Net.Packets
|
||||
{
|
||||
class IIPPacket : Packet
|
||||
{
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var rt = Command.ToString();
|
||||
|
||||
if (Command == IIPPacketCommand.Event)
|
||||
{
|
||||
rt += " " + Event.ToString();
|
||||
//if (Event == IIPPacketEvent.AttributesUpdated)
|
||||
// rt +=
|
||||
}
|
||||
else if (Command == IIPPacketCommand.Request)
|
||||
{
|
||||
rt += " " + Action.ToString();
|
||||
if (Action == IIPPacketAction.AttachResource)
|
||||
{
|
||||
rt += " CID: " + CallbackId + " RID: " + ResourceId;
|
||||
}
|
||||
}
|
||||
else if (Command == IIPPacketCommand.Reply)
|
||||
rt += " " + Action.ToString();
|
||||
else if (Command == IIPPacketCommand.Report)
|
||||
rt += " " + Report.ToString();
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public enum IIPPacketCommand : byte
|
||||
{
|
||||
Event = 0,
|
||||
Request,
|
||||
Reply,
|
||||
Report,
|
||||
}
|
||||
|
||||
public enum IIPPacketEvent : byte
|
||||
{
|
||||
// Event Manage
|
||||
ResourceReassigned = 0,
|
||||
ResourceDestroyed,
|
||||
ChildAdded,
|
||||
ChildRemoved,
|
||||
Renamed,
|
||||
// Event Invoke
|
||||
PropertyUpdated = 0x10,
|
||||
EventOccurred,
|
||||
|
||||
// Attribute
|
||||
AttributesUpdated = 0x18
|
||||
}
|
||||
|
||||
public enum IIPPacketAction : byte
|
||||
{
|
||||
// Request Manage
|
||||
AttachResource = 0,
|
||||
ReattachResource,
|
||||
DetachResource,
|
||||
CreateResource,
|
||||
DeleteResource,
|
||||
AddChild,
|
||||
RemoveChild,
|
||||
RenameResource,
|
||||
|
||||
// Request Inquire
|
||||
TemplateFromClassName = 0x8,
|
||||
TemplateFromClassId,
|
||||
TemplateFromResourceId,
|
||||
QueryLink,
|
||||
ResourceHistory,
|
||||
ResourceChildren,
|
||||
ResourceParents,
|
||||
|
||||
// Request Invoke
|
||||
InvokeFunctionArrayArguments = 0x10,
|
||||
GetProperty,
|
||||
GetPropertyIfModified,
|
||||
SetProperty,
|
||||
InvokeFunctionNamedArguments,
|
||||
|
||||
// Request Attribute
|
||||
GetAllAttributes = 0x18,
|
||||
UpdateAllAttributes,
|
||||
ClearAllAttributes,
|
||||
GetAttributes,
|
||||
UpdateAttributes,
|
||||
ClearAttributes
|
||||
}
|
||||
|
||||
public enum IIPPacketReport : byte
|
||||
{
|
||||
ManagementError,
|
||||
ExecutionError,
|
||||
ProgressReport = 0x8,
|
||||
ChunkStream = 0x9
|
||||
}
|
||||
|
||||
|
||||
public IIPPacketReport Report
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public IIPPacketCommand Command
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public IIPPacketAction Action
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public IIPPacketEvent Event
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public IIPPacketCommand PreviousCommand
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public IIPPacketAction PreviousAction
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public IIPPacketEvent PreviousEvent
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
|
||||
public uint ResourceId { get; set; }
|
||||
public uint NewResourceId { get; set; }
|
||||
//public uint ParentId { get; set; }
|
||||
public uint ChildId { get; set; }
|
||||
public uint StoreId { get; set; }
|
||||
|
||||
public ulong ResourceAge { get; set; }
|
||||
public byte[] Content { get; set; }
|
||||
public ushort ErrorCode { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
public string ClassName { get; set; }
|
||||
public string ResourceLink { get; set; }
|
||||
public Guid ClassId { get; set; }
|
||||
public byte MethodIndex { get; set; }
|
||||
public string MethodName { get; set; }
|
||||
public uint CallbackId { get; set; }
|
||||
public int ProgressValue { get; set; }
|
||||
public int ProgressMax { get; set; }
|
||||
public DateTime FromDate { get; set; }
|
||||
public DateTime ToDate { get; set; }
|
||||
public ulong FromAge { get; set; }
|
||||
public ulong ToAge { get; set; }
|
||||
|
||||
private uint dataLengthNeeded;
|
||||
private uint originalOffset;
|
||||
|
||||
public override bool Compose()
|
||||
{
|
||||
return base.Compose();
|
||||
}
|
||||
|
||||
bool NotEnough(uint offset, uint ends, uint needed)
|
||||
{
|
||||
if (offset + needed > ends)
|
||||
{
|
||||
dataLengthNeeded = needed - (ends - offset);
|
||||
//dataLengthNeeded = needed - (ends - originalOffset);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public override long Parse(byte[] data, uint offset, uint ends)
|
||||
{
|
||||
originalOffset = offset;
|
||||
|
||||
if (NotEnough(offset, ends, 1))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
PreviousCommand = Command;
|
||||
|
||||
Command = (IIPPacketCommand)(data[offset] >> 6);
|
||||
|
||||
if (Command == IIPPacketCommand.Event)
|
||||
{
|
||||
Event = (IIPPacketEvent)(data[offset++] & 0x3f);
|
||||
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
}
|
||||
else if (Command == IIPPacketCommand.Report)
|
||||
{
|
||||
Report = (IIPPacketReport)(data[offset++] & 0x3f);
|
||||
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
CallbackId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
PreviousAction = Action;
|
||||
Action = (IIPPacketAction)(data[offset++] & 0x3f);
|
||||
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
CallbackId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
}
|
||||
|
||||
if (Command == IIPPacketCommand.Event)
|
||||
{
|
||||
if (Event == IIPPacketEvent.ResourceReassigned)
|
||||
{
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
NewResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
}
|
||||
else if (Event == IIPPacketEvent.ResourceDestroyed)
|
||||
{
|
||||
// nothing to parse
|
||||
}
|
||||
else if (Event == IIPPacketEvent.ChildAdded
|
||||
|| Event == IIPPacketEvent.ChildRemoved)
|
||||
{
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ChildId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
}
|
||||
else if (Event == IIPPacketEvent.Renamed)
|
||||
{
|
||||
if (NotEnough(offset, ends, 2))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var cl = data.GetUInt16(offset);
|
||||
offset += 2;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Content = data.Clip(offset, cl);
|
||||
|
||||
offset += cl;
|
||||
}
|
||||
else if (Event == IIPPacketEvent.PropertyUpdated)
|
||||
{
|
||||
if (NotEnough(offset, ends, 2))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
MethodIndex = data[offset++];
|
||||
|
||||
var dt = (DataType)data[offset++];
|
||||
var size = dt.Size();// Codec.SizeOf(dt);
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var cl = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Content = data.Clip(offset - 5, cl + 5);
|
||||
offset += cl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NotEnough(offset, ends, (uint)size))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Content = data.Clip(offset - 1, (uint)size + 1);
|
||||
offset += (uint)size;
|
||||
}
|
||||
}
|
||||
else if (Event == IIPPacketEvent.EventOccurred)
|
||||
{
|
||||
if (NotEnough(offset, ends, 5))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
MethodIndex = data[offset++];
|
||||
|
||||
var cl = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Content = data.Clip(offset, cl);
|
||||
offset += cl;
|
||||
|
||||
}
|
||||
// Attribute
|
||||
else if (Event == IIPPacketEvent.AttributesUpdated)
|
||||
{
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var cl = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Content = data.Clip(offset, cl);
|
||||
|
||||
offset += cl;
|
||||
}
|
||||
}
|
||||
else if (Command == IIPPacketCommand.Request)
|
||||
{
|
||||
if (Action == IIPPacketAction.AttachResource)
|
||||
{
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
}
|
||||
else if (Action == IIPPacketAction.ReattachResource)
|
||||
{
|
||||
if (NotEnough(offset, ends, 12))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
ResourceAge = data.GetUInt64(offset);
|
||||
offset += 8;
|
||||
|
||||
}
|
||||
else if (Action == IIPPacketAction.DetachResource)
|
||||
{
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
}
|
||||
else if (Action == IIPPacketAction.CreateResource)
|
||||
{
|
||||
if (NotEnough(offset, ends, 12))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
StoreId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
var cl = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
this.Content = data.Clip(offset, cl);
|
||||
}
|
||||
else if (Action == IIPPacketAction.DeleteResource)
|
||||
{
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
}
|
||||
else if (Action == IIPPacketAction.AddChild
|
||||
|| Action == IIPPacketAction.RemoveChild)
|
||||
{
|
||||
if (NotEnough(offset, ends, 8))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
ChildId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
}
|
||||
else if (Action == IIPPacketAction.RenameResource)
|
||||
{
|
||||
if (NotEnough(offset, ends, 6))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
var cl = data.GetUInt16(offset);
|
||||
offset += 2;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Content = data.Clip(offset, cl);
|
||||
offset += cl;
|
||||
}
|
||||
else if (Action == IIPPacketAction.TemplateFromClassName)
|
||||
{
|
||||
if (NotEnough(offset, ends, 1))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var cl = data[offset++];
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ClassName = data.GetString(offset, cl);
|
||||
offset += cl;
|
||||
|
||||
}
|
||||
else if (Action == IIPPacketAction.TemplateFromClassId)
|
||||
{
|
||||
if (NotEnough(offset, ends, 16))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ClassId = data.GetGuid(offset);
|
||||
offset += 16;
|
||||
|
||||
}
|
||||
else if (Action == IIPPacketAction.TemplateFromResourceId)
|
||||
{
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
}
|
||||
else if (Action == IIPPacketAction.QueryLink)
|
||||
{
|
||||
if (NotEnough(offset, ends, 2))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var cl = data.GetUInt16(offset);
|
||||
offset += 2;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceLink = data.GetString(offset, cl);
|
||||
offset += cl;
|
||||
}
|
||||
else if (Action == IIPPacketAction.ResourceChildren
|
||||
|| Action == IIPPacketAction.ResourceParents)
|
||||
{
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
}
|
||||
else if (Action == IIPPacketAction.ResourceHistory)
|
||||
{
|
||||
if (NotEnough(offset, ends, 20))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
FromDate = data.GetDateTime(offset);
|
||||
offset += 8;
|
||||
|
||||
ToDate = data.GetDateTime(offset);
|
||||
offset += 8;
|
||||
|
||||
}
|
||||
else if (Action == IIPPacketAction.InvokeFunctionArrayArguments
|
||||
|| Action == IIPPacketAction.InvokeFunctionNamedArguments)
|
||||
{
|
||||
if (NotEnough(offset, ends, 9))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
MethodIndex = data[offset++];
|
||||
|
||||
var cl = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Content = data.Clip(offset, cl);
|
||||
offset += cl;
|
||||
|
||||
}
|
||||
else if (Action == IIPPacketAction.GetProperty)
|
||||
{
|
||||
if (NotEnough(offset, ends, 5))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
MethodIndex = data[offset++];
|
||||
|
||||
}
|
||||
else if (Action == IIPPacketAction.GetPropertyIfModified)
|
||||
{
|
||||
if (NotEnough(offset, ends, 9))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
MethodIndex = data[offset++];
|
||||
|
||||
ResourceAge = data.GetUInt64(offset);
|
||||
offset += 8;
|
||||
|
||||
}
|
||||
else if (Action == IIPPacketAction.SetProperty)
|
||||
{
|
||||
if (NotEnough(offset, ends, 6))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
MethodIndex = data[offset++];
|
||||
|
||||
|
||||
var dt = (DataType)data[offset++];
|
||||
var size = dt.Size();// Codec.SizeOf(dt);
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var cl = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Content = data.Clip(offset - 5, cl + 5);
|
||||
offset += cl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NotEnough(offset, ends, (uint)size))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Content = data.Clip(offset - 1, (uint)size + 1);
|
||||
offset += (uint)size;
|
||||
}
|
||||
}
|
||||
// Attributes
|
||||
else if (Action == IIPPacketAction.UpdateAllAttributes
|
||||
|| Action == IIPPacketAction.GetAttributes
|
||||
|| Action == IIPPacketAction.UpdateAttributes
|
||||
|| Action == IIPPacketAction.ClearAttributes)
|
||||
{
|
||||
if (NotEnough(offset, ends, 8))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
var cl = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Content = data.Clip(offset, cl);
|
||||
offset += cl;
|
||||
}
|
||||
}
|
||||
else if (Command == IIPPacketCommand.Reply)
|
||||
{
|
||||
if (Action == IIPPacketAction.AttachResource
|
||||
|| Action == IIPPacketAction.ReattachResource)
|
||||
{
|
||||
|
||||
if (NotEnough(offset, ends, 26))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ClassId = data.GetGuid(offset);
|
||||
offset += 16;
|
||||
|
||||
ResourceAge = data.GetUInt64(offset);
|
||||
offset += 8;
|
||||
|
||||
uint cl = data.GetUInt16(offset);
|
||||
offset += 2;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ResourceLink = data.GetString(offset, cl);
|
||||
offset += cl;
|
||||
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
cl = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Content = data.Clip(offset, cl);
|
||||
offset += cl;
|
||||
}
|
||||
else if (Action == IIPPacketAction.DetachResource)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
else if (Action == IIPPacketAction.CreateResource)
|
||||
{
|
||||
if (NotEnough(offset, ends, 20))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
//ClassId = data.GetGuid(offset);
|
||||
//offset += 16;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
}
|
||||
else if (Action == IIPPacketAction.DetachResource)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
// Inquire
|
||||
else if (Action == IIPPacketAction.TemplateFromClassName
|
||||
|| Action == IIPPacketAction.TemplateFromClassId
|
||||
|| Action == IIPPacketAction.TemplateFromResourceId
|
||||
|| Action == IIPPacketAction.QueryLink
|
||||
|| Action == IIPPacketAction.ResourceChildren
|
||||
|| Action == IIPPacketAction.ResourceParents
|
||||
|| Action == IIPPacketAction.ResourceHistory
|
||||
// Attribute
|
||||
|| Action == IIPPacketAction.GetAllAttributes
|
||||
|| Action == IIPPacketAction.GetAttributes)
|
||||
{
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var cl = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Content = data.Clip(offset, cl);
|
||||
offset += cl;
|
||||
}
|
||||
else if (Action == IIPPacketAction.InvokeFunctionArrayArguments
|
||||
|| Action == IIPPacketAction.InvokeFunctionNamedArguments
|
||||
|| Action == IIPPacketAction.GetProperty
|
||||
|| Action == IIPPacketAction.GetPropertyIfModified)
|
||||
{
|
||||
if (NotEnough(offset, ends, 1))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var dt = (DataType)data[offset++];
|
||||
var size = dt.Size();// Codec.SizeOf(dt);
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var cl = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Content = data.Clip(offset - 5, cl + 5);
|
||||
offset += cl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NotEnough(offset, ends, (uint)size))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Content = data.Clip(offset - 1, (uint)size + 1);
|
||||
offset += (uint)size;
|
||||
}
|
||||
}
|
||||
else if (Action == IIPPacketAction.SetProperty)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
else if (Command == IIPPacketCommand.Report)
|
||||
{
|
||||
if (Report == IIPPacketReport.ManagementError)
|
||||
{
|
||||
if (NotEnough(offset, ends, 2))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ErrorCode = data.GetUInt16(offset);
|
||||
offset += 2;
|
||||
}
|
||||
else if (Report == IIPPacketReport.ExecutionError)
|
||||
{
|
||||
if (NotEnough(offset, ends, 2))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ErrorCode = data.GetUInt16(offset);
|
||||
offset += 2;
|
||||
|
||||
if (NotEnough(offset, ends, 2))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var cl = data.GetUInt16(offset);
|
||||
offset += 2;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ErrorMessage = data.GetString(offset, cl);
|
||||
offset += cl;
|
||||
}
|
||||
else if (Report == IIPPacketReport.ProgressReport)
|
||||
{
|
||||
if (NotEnough(offset, ends, 8))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
ProgressValue = data.GetInt32(offset);
|
||||
offset += 4;
|
||||
ProgressMax = data.GetInt32(offset);
|
||||
offset += 4;
|
||||
}
|
||||
else if (Report == IIPPacketReport.ChunkStream)
|
||||
{
|
||||
if (NotEnough(offset, ends, 1))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var dt = (DataType)data[offset++];
|
||||
var size = dt.Size();// Codec.SizeOf(dt);
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
if (NotEnough(offset, ends, 4))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
var cl = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
if (NotEnough(offset, ends, cl))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Content = data.Clip(offset - 5, cl + 5);
|
||||
offset += cl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NotEnough(offset, ends, (uint)size))
|
||||
return -dataLengthNeeded;
|
||||
|
||||
Content = data.Clip(offset - 1, (uint)size + 1);
|
||||
offset += (uint)size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return offset - originalOffset;
|
||||
}
|
||||
}
|
||||
}
|
22
Esiur/Net/Packets/IIPPacketAttachInfo.cs
Normal file
22
Esiur/Net/Packets/IIPPacketAttachInfo.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Net.Packets
|
||||
{
|
||||
struct IIPPacketAttachInfo
|
||||
{
|
||||
public string Link;
|
||||
public ulong Age;
|
||||
public byte[] Content;
|
||||
public Guid ClassId;
|
||||
|
||||
public IIPPacketAttachInfo(Guid classId, ulong age, string link, byte[] content)
|
||||
{
|
||||
ClassId = classId;
|
||||
Age = age;
|
||||
Content = content;
|
||||
Link = link;
|
||||
}
|
||||
}
|
||||
}
|
369
Esiur/Net/Packets/Packet.cs
Normal file
369
Esiur/Net/Packets/Packet.cs
Normal file
@ -0,0 +1,369 @@
|
||||
|
||||
/********************************************************************************\
|
||||
* Uruky Project *
|
||||
* *
|
||||
* Copyright (C) 2006 Ahmed Zamil - ahmed@dijlh.com *
|
||||
* http://www.dijlh.com *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy *
|
||||
* of this software and associated documentation files (the "Software"), to deal *
|
||||
* in the Software without restriction, including without limitation the rights *
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
|
||||
* copies of the Software, and to permit persons to whom the Software is *
|
||||
* furnished to do so, subject to the following conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all *
|
||||
* copies or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
|
||||
* SOFTWARE. *
|
||||
* *
|
||||
* File: Packet.cs *
|
||||
* Description: Ethernet/ARP/IPv4/TCP/UDP Packet Decoding & Encoding Class *
|
||||
* Compatibility: .Net Framework 2.0 / Mono 1.1.8 *
|
||||
* *
|
||||
\********************************************************************************/
|
||||
|
||||
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using Esiur.Misc;
|
||||
using Esiur.Net.DataLink;
|
||||
using System.Net.NetworkInformation;
|
||||
using Esiur.Data;
|
||||
|
||||
namespace Esiur.Net.Packets
|
||||
{
|
||||
internal static class Functions
|
||||
{
|
||||
public static void AddData(ref byte[] dest, byte[] src)
|
||||
{
|
||||
int I = 0;
|
||||
if (src == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (dest != null)
|
||||
{
|
||||
I = dest.Length;
|
||||
Array.Resize(ref dest, dest.Length + src.Length);
|
||||
//dest = (byte[])Resize(dest, dest.Length + src.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
dest = new byte[src.Length];
|
||||
}
|
||||
Array.Copy(src, 0, dest, I, src.Length);
|
||||
}
|
||||
|
||||
/*
|
||||
public static Array Resize(Array array, int newSize)
|
||||
{
|
||||
Type myType = Type.GetType(array.GetType().FullName.TrimEnd('[', ']'));
|
||||
Array nA = Array.CreateInstance(myType, newSize);
|
||||
Array.Copy(array, nA, (newSize > array.Length ? array.Length : newSize));
|
||||
return nA;
|
||||
} */
|
||||
|
||||
//Computes the checksum used in IP, ARP..., ie the
|
||||
// "The 16 bit one's complement of the one 's complement sum
|
||||
//of all 16 bit words" as seen in RFCs
|
||||
// Returns a 4 characters hex string
|
||||
// data's lenght must be multiple of 4, else zero padding
|
||||
public static ushort IP_CRC16(byte[] data)
|
||||
{
|
||||
ulong Sum = 0;
|
||||
bool Padding = false;
|
||||
/// * Padding if needed
|
||||
if (data.Length % 2 != 0)
|
||||
{
|
||||
Array.Resize(ref data, data.Length + 1);
|
||||
//data = (byte[])Resize(data, data.Length + 1);
|
||||
Padding = true;
|
||||
}
|
||||
int count = data.Length;
|
||||
///* add 16-bit words */
|
||||
while (count > 0) //1)
|
||||
{
|
||||
///* this is the inner loop */
|
||||
Sum += GetInteger(data[count - 2], data[count - 1]);
|
||||
///* Fold 32-bit sum to 16-bit */
|
||||
while (Sum >> 16 != 0)
|
||||
{
|
||||
Sum = (Sum & 0XFFFF) + (Sum >> 16);
|
||||
}
|
||||
count -= 2;
|
||||
}
|
||||
/// * reverse padding
|
||||
if (Padding)
|
||||
{
|
||||
Array.Resize(ref data, data.Length - 1);
|
||||
//data = (byte[])Resize(data, data.Length - 1);
|
||||
}
|
||||
///* Return one's compliment of final sum.
|
||||
//return (ushort)(ushort.MaxValue - (ushort)Sum);
|
||||
return (ushort)(~Sum);
|
||||
}
|
||||
|
||||
public static ushort GetInteger(byte B1, byte B2)
|
||||
{
|
||||
return BitConverter.ToUInt16(new byte[] { B2, B1 }, 0);
|
||||
//return System.Convert.ToUInt16("&h" + GetHex(B1) + GetHex(B2));
|
||||
}
|
||||
|
||||
public static uint GetLong(byte B1, byte B2, byte B3, byte B4)
|
||||
{
|
||||
return BitConverter.ToUInt32(new byte[] { B4, B3, B2, B1 }, 0);
|
||||
//return System.Convert.ToUInt32("&h" + GetHex(B1) + GetHex(B2) + GetHex(B3) + GetHex(B4));
|
||||
}
|
||||
|
||||
public static string GetHex(byte B)
|
||||
{
|
||||
return (((B < 15) ? 0 + System.Convert.ToString(B, 16).ToUpper() : System.Convert.ToString(B, 16).ToUpper()));
|
||||
}
|
||||
|
||||
public static bool GetBit(uint B, byte Pos)
|
||||
{
|
||||
//return BitConverter.ToBoolean(BitConverter.GetBytes(B), Pos + 1);
|
||||
return (B & (uint)(Math.Pow(2, (Pos - 1)))) == (Math.Pow(2, (Pos - 1)));
|
||||
}
|
||||
|
||||
public static ushort RemoveBit(ushort I, byte Pos)
|
||||
{
|
||||
return (ushort)RemoveBit((uint)I, Pos);
|
||||
}
|
||||
|
||||
public static uint RemoveBit(uint I, byte Pos)
|
||||
{
|
||||
if (GetBit(I, Pos))
|
||||
{
|
||||
return I - (uint)(Math.Pow(2, (Pos - 1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return I;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SplitInteger(ushort I, ref byte BLeft, ref byte BRight)
|
||||
{
|
||||
byte[] b = BitConverter.GetBytes(I);
|
||||
BLeft = b[1];
|
||||
BRight = b[0];
|
||||
//BLeft = I >> 8;
|
||||
//BRight = (I << 8) >> 8;
|
||||
}
|
||||
|
||||
public static void SplitLong(uint I, ref byte BLeft, ref byte BLeftMiddle, ref byte BRightMiddle, ref byte BRight)
|
||||
{
|
||||
byte[] b = BitConverter.GetBytes(I);
|
||||
BLeft = b[3];
|
||||
BLeftMiddle = b[2];
|
||||
BRightMiddle = b[1];
|
||||
BRight = b[0];
|
||||
//BLeft = I >> 24;
|
||||
//BLeftMiddle = (I << 8) >> 24;
|
||||
//BRightMiddle = (I << 16) >> 24;
|
||||
//BRight = (I << 24) >> 24;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class PosixTime
|
||||
{
|
||||
ulong seconds;
|
||||
ulong microseconds;
|
||||
|
||||
PosixTime(ulong Seconds, ulong Microseconds)
|
||||
{
|
||||
seconds = Seconds;
|
||||
microseconds = Microseconds;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return seconds + "." + microseconds;
|
||||
}
|
||||
}
|
||||
|
||||
public class Packet
|
||||
{
|
||||
//public EtherServer2.EthernetSource Source;
|
||||
|
||||
public PacketSource Source;
|
||||
|
||||
public DateTime Timestamp;
|
||||
|
||||
public enum PPPType : ushort
|
||||
{
|
||||
IP = 0x0021, // Internet Protocol version 4 [RFC1332]
|
||||
SDTP = 0x0049, // Serial Data Transport Protocol (PPP-SDTP) [RFC1963]
|
||||
IPv6HeaderCompression = 0x004f, // IPv6 Header Compression
|
||||
IPv6 = 0x0057, // Internet Protocol version 6 [RFC5072]
|
||||
W8021dHelloPacket = 0x0201, // 802.1d Hello Packets [RFC3518]
|
||||
IPv6ControlProtocol = 0x8057, // IPv6 Control Protocol [RFC5072]
|
||||
}
|
||||
|
||||
public enum ProtocolType : ushort
|
||||
{
|
||||
IP = 0x800, // IPv4
|
||||
ARP = 0x806, // Address Resolution Protocol
|
||||
IPv6 = 0x86DD, // IPv6
|
||||
FrameRelayARP = 0x0808, // Frame Relay ARP [RFC1701]
|
||||
VINESLoopback = 0x0BAE, // VINES Loopback [RFC1701]
|
||||
VINESEcho = 0x0BAF, // VINES ECHO [RFC1701]
|
||||
TransEtherBridging = 0x6558, // TransEther Bridging [RFC1701]
|
||||
RawFrameRelay = 0x6559, // Raw Frame Relay [RFC1701]
|
||||
IEE8021QVLAN = 0x8100, // IEEE 802.1Q VLAN-tagged frames (initially Wellfleet)
|
||||
SNMP = 0x814C, // SNMP [JKR1]
|
||||
TCPIP_Compression = 0x876B, // TCP/IP Compression [RFC1144]
|
||||
IPAutonomousSystems = 0x876C, // IP Autonomous Systems [RFC1701]
|
||||
SecureData = 0x876D, // Secure Data [RFC1701]
|
||||
PPP = 0x880B, // PPP [IANA]
|
||||
MPLS = 0x8847, // MPLS [RFC5332]
|
||||
MPLS_UpstreamAssignedLabel = 0x8848, // MPLS with upstream-assigned label [RFC5332]
|
||||
PPPoEDiscoveryStage = 0x8863, // PPPoE Discovery Stage [RFC2516]
|
||||
PPPoESessionStage = 0x8864, // PPPoE Session Stage [RFC2516]
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
public static void GetPacketMACAddresses(Packet packet, out byte[] srcMAC, out byte[] dstMAC)
|
||||
{
|
||||
|
||||
// get the node address
|
||||
Packet root = packet.RootPacket;
|
||||
if (root is TZSPPacket)
|
||||
{
|
||||
|
||||
TZSPPacket tp = (TZSPPacket)root;
|
||||
if (tp.Protocol == TZSPPacket.TZSPEncapsulatedProtocol.Ethernet)
|
||||
{
|
||||
EthernetPacket ep = (EthernetPacket)tp.SubPacket;
|
||||
srcMAC = ep.SourceMAC;
|
||||
dstMAC = ep.DestinationMAC;
|
||||
}
|
||||
else if (tp.Protocol == TZSPPacket.TZSPEncapsulatedProtocol.IEEE802_11)
|
||||
{
|
||||
W802_11Packet wp = (W802_11Packet)tp.SubPacket;
|
||||
srcMAC = wp.SA;
|
||||
dstMAC = wp.DA;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcMAC = null;
|
||||
dstMAC = null;
|
||||
}
|
||||
}
|
||||
else if (root is EthernetPacket)
|
||||
{
|
||||
EthernetPacket ep = (EthernetPacket)root;
|
||||
srcMAC = ep.SourceMAC;
|
||||
dstMAC = ep.DestinationMAC;
|
||||
}
|
||||
else if (root is W802_11Packet)
|
||||
{
|
||||
W802_11Packet wp = (W802_11Packet)root;
|
||||
srcMAC = wp.SA;
|
||||
dstMAC = wp.DA;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcMAC = null;
|
||||
dstMAC = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void GetPacketAddresses(Packet packet, ref string srcMAC, ref string dstMAC, ref string srcIP, ref string dstIP)
|
||||
{
|
||||
|
||||
if (packet is TCPv4Packet)
|
||||
{
|
||||
if (packet.ParentPacket is IPv4Packet)
|
||||
{
|
||||
IPv4Packet ip = (IPv4Packet)packet.ParentPacket;
|
||||
srcIP = ip.SourceIP.ToString();
|
||||
dstIP = ip.DestinationIP.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
// get the node address
|
||||
Packet root = packet.RootPacket;
|
||||
if (root is TZSPPacket)
|
||||
{
|
||||
|
||||
TZSPPacket tp = (TZSPPacket)root;
|
||||
if (tp.Protocol == TZSPPacket.TZSPEncapsulatedProtocol.Ethernet)
|
||||
{
|
||||
EthernetPacket ep = (EthernetPacket)tp.SubPacket;
|
||||
srcMAC = DC.GetPhysicalAddress(ep.SourceMAC, 0).ToString();
|
||||
dstMAC = DC.GetPhysicalAddress(ep.DestinationMAC, 0).ToString();
|
||||
}
|
||||
else if (tp.Protocol == TZSPPacket.TZSPEncapsulatedProtocol.IEEE802_11)
|
||||
{
|
||||
W802_11Packet wp = (W802_11Packet)tp.SubPacket;
|
||||
srcMAC = DC.GetPhysicalAddress(wp.SA, 0).ToString();
|
||||
dstMAC = DC.GetPhysicalAddress(wp.DA, 0).ToString();
|
||||
}
|
||||
}
|
||||
else if (root is EthernetPacket)
|
||||
{
|
||||
EthernetPacket ep = (EthernetPacket)root;
|
||||
srcMAC = DC.GetPhysicalAddress(ep.SourceMAC, 0).ToString();
|
||||
dstMAC = DC.GetPhysicalAddress(ep.DestinationMAC, 0).ToString();
|
||||
}
|
||||
else if (root is W802_11Packet)
|
||||
{
|
||||
W802_11Packet wp = (W802_11Packet)root;
|
||||
srcMAC = DC.GetPhysicalAddress(wp.SA, 0).ToString();
|
||||
dstMAC = DC.GetPhysicalAddress(wp.DA, 0).ToString();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
PosixTime Timeval;
|
||||
public byte[] Header;
|
||||
public byte[] Preamble;
|
||||
//public byte[] Payload;
|
||||
public byte[] Data;
|
||||
|
||||
public Packet SubPacket;
|
||||
public Packet ParentPacket;
|
||||
public virtual long Parse(byte[] data, uint offset, uint ends) { return 0; }
|
||||
public virtual bool Compose() { return false; }
|
||||
|
||||
public Packet RootPacket
|
||||
{
|
||||
get
|
||||
{
|
||||
Packet root = this;
|
||||
while (root.ParentPacket != null)
|
||||
root = root.ParentPacket;
|
||||
return root;
|
||||
}
|
||||
}
|
||||
|
||||
public Packet LeafPacket
|
||||
{
|
||||
get
|
||||
{
|
||||
Packet leaf = this;
|
||||
while (leaf.SubPacket != null)
|
||||
leaf = leaf.SubPacket;
|
||||
return leaf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/************************************ EOF *************************************/
|
||||
|
||||
|
217
Esiur/Net/Packets/WebsocketPacket.cs
Normal file
217
Esiur/Net/Packets/WebsocketPacket.cs
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2017 Ahmed Kh. Zamil
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Esiur.Misc;
|
||||
using Esiur.Data;
|
||||
|
||||
namespace Esiur.Net.Packets
|
||||
{
|
||||
public class WebsocketPacket : Packet
|
||||
{
|
||||
public enum WSOpcode : byte
|
||||
{
|
||||
ContinuationFrame = 0x0, // %x0 denotes a continuation frame
|
||||
|
||||
TextFrame = 0x1, // %x1 denotes a text frame
|
||||
|
||||
BinaryFrame = 0x2, // %x2 denotes a binary frame
|
||||
|
||||
// %x3-7 are reserved for further non-control frames
|
||||
|
||||
ConnectionClose = 0x8, // %x8 denotes a connection close
|
||||
|
||||
Ping = 0x9, // %x9 denotes a ping
|
||||
|
||||
Pong = 0xA, // %xA denotes a pong
|
||||
|
||||
//* %xB-F are reserved for further control frames
|
||||
}
|
||||
|
||||
|
||||
public bool FIN;
|
||||
public bool RSV1;
|
||||
public bool RSV2;
|
||||
public bool RSV3;
|
||||
public WSOpcode Opcode;
|
||||
public bool Mask;
|
||||
public long PayloadLength;
|
||||
// public UInt32 MaskKey;
|
||||
public byte[] MaskKey;
|
||||
|
||||
public byte[] Message;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "WebsocketPacket"
|
||||
+ "\n\tFIN: " + FIN
|
||||
+ "\n\tOpcode: " + Opcode
|
||||
+ "\n\tPayload: " + PayloadLength
|
||||
+ "\n\tMaskKey: " + MaskKey
|
||||
+ "\n\tMessage: " + (Message != null ? Message.Length.ToString() : "NULL");
|
||||
}
|
||||
|
||||
public override bool Compose()
|
||||
{
|
||||
var pkt = new List<byte>();
|
||||
pkt.Add((byte)((FIN ? 0x80 : 0x0) |
|
||||
(RSV1 ? 0x40 : 0x0) |
|
||||
(RSV2 ? 0x20 : 0x0) |
|
||||
(RSV3 ? 0x10 : 0x0) |
|
||||
(byte)Opcode));
|
||||
|
||||
// calculate length
|
||||
if (Message.Length > UInt16.MaxValue)
|
||||
// 4 bytes
|
||||
{
|
||||
pkt.Add((byte)((Mask ? 0x80 : 0x0) | 127));
|
||||
pkt.AddRange(DC.ToBytes((UInt64)Message.LongCount()));
|
||||
}
|
||||
else if (Message.Length > 125)
|
||||
// 2 bytes
|
||||
{
|
||||
pkt.Add((byte)((Mask ? 0x80 : 0x0) | 126));
|
||||
pkt.AddRange(DC.ToBytes((UInt16)Message.Length));
|
||||
}
|
||||
else
|
||||
{
|
||||
pkt.Add((byte)((Mask ? 0x80 : 0x0) | Message.Length));
|
||||
}
|
||||
|
||||
if (Mask)
|
||||
{
|
||||
pkt.AddRange(MaskKey);
|
||||
}
|
||||
|
||||
pkt.AddRange(Message);
|
||||
|
||||
Data = pkt.ToArray();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override long Parse(byte[] data, uint offset, uint ends)
|
||||
{
|
||||
try
|
||||
{
|
||||
long needed = 2;
|
||||
var length = (ends - offset);
|
||||
if (length < needed)
|
||||
{
|
||||
//Console.WriteLine("stage 1 " + needed);
|
||||
return length - needed;
|
||||
}
|
||||
|
||||
uint oOffset = offset;
|
||||
FIN = ((data[offset] & 0x80) == 0x80);
|
||||
RSV1 = ((data[offset] & 0x40) == 0x40);
|
||||
RSV2 = ((data[offset] & 0x20) == 0x20);
|
||||
RSV3 = ((data[offset] & 0x10) == 0x10);
|
||||
Opcode = (WSOpcode)(data[offset++] & 0xF);
|
||||
Mask = ((data[offset] & 0x80) == 0x80);
|
||||
PayloadLength = (long)(data[offset++] & 0x7F);
|
||||
|
||||
if (Mask)
|
||||
needed += 4;
|
||||
|
||||
if (PayloadLength == 126)
|
||||
{
|
||||
needed += 2;
|
||||
if (length < needed)
|
||||
{
|
||||
//Console.WriteLine("stage 2 " + needed);
|
||||
return length - needed;
|
||||
}
|
||||
PayloadLength = DC.GetUInt16(data, offset);
|
||||
offset += 2;
|
||||
}
|
||||
else if (PayloadLength == 127)
|
||||
{
|
||||
needed += 8;
|
||||
if (length < needed)
|
||||
{
|
||||
//Console.WriteLine("stage 3 " + needed);
|
||||
return length - needed;
|
||||
}
|
||||
|
||||
PayloadLength = DC.GetInt64(data, offset);
|
||||
offset += 8;
|
||||
}
|
||||
|
||||
/*
|
||||
if (Mask)
|
||||
{
|
||||
MaskKey = new byte[4];
|
||||
MaskKey[0] = data[offset++];
|
||||
MaskKey[1] = data[offset++];
|
||||
MaskKey[2] = data[offset++];
|
||||
MaskKey[3] = data[offset++];
|
||||
|
||||
//MaskKey = DC.GetUInt32(data, offset);
|
||||
//offset += 4;
|
||||
}
|
||||
*/
|
||||
|
||||
needed += PayloadLength;
|
||||
if (length < needed)
|
||||
{
|
||||
//Console.WriteLine("stage 4");
|
||||
return length - needed;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (Mask)
|
||||
{
|
||||
MaskKey = new byte[4];
|
||||
MaskKey[0] = data[offset++];
|
||||
MaskKey[1] = data[offset++];
|
||||
MaskKey[2] = data[offset++];
|
||||
MaskKey[3] = data[offset++];
|
||||
|
||||
Message = DC.Clip(data, offset, (uint)PayloadLength);
|
||||
|
||||
//var aMask = BitConverter.GetBytes(MaskKey);
|
||||
for (int i = 0; i < Message.Length; i++)
|
||||
Message[i] = (byte)(Message[i] ^ MaskKey[i % 4]);
|
||||
}
|
||||
else
|
||||
Message = DC.Clip(data, offset, (uint)PayloadLength);
|
||||
|
||||
|
||||
return (offset - oOffset) + (int)PayloadLength;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.ToString());
|
||||
Console.WriteLine(offset + "::" + DC.ToHex(data));
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user