mirror of
				https://github.com/esiur/esiur-dotnet.git
				synced 2025-10-29 23:21:36 +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