using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace pyxis.gemini.Protocol { public class Request { // 1024 meta // 2 status code // 1 separator space // 2 \r\n private const int MAX_REQUEST_LENGTH = 1024 + 2 + 1 + 2; public string Url { private set; get; } // TODO: Provide properties for fetching specific parts of the URL public void setUrl(string url) { this.Url = url; } public static int Parse(byte[] data, int length, out Request request) { int i; bool found_cr = false, found_lf = false; request = null; // Minimum request length would be 3 -- one byte url and \r\n. If it's less than that, just // bail now. This guards against any potential bug later when we start trying to trim the // crlf, etc. if (length < 3) { return 0; } for (i = 0; i < length; i++) { if (i >= MAX_REQUEST_LENGTH) { throw new Exception.ProtocolViolationException(String.Format("Request length exceeded maximum: %d", MAX_REQUEST_LENGTH)); } if (data[i] == '\r') { found_cr = true; } else if (found_cr && data[i] == '\n') { found_lf = true; break; } else { found_cr = false; found_lf = false; } } if (!found_cr || !found_lf) { return 0; } request = new Request(); request.setUrl(Encoding.UTF8.GetString(data, 0, i - 2 /* trim \r\n */)); return i + 1; } public byte[] Serialize() { System.IO.MemoryStream ms = new System.IO.MemoryStream(); System.IO.StreamWriter sw = new System.IO.StreamWriter(ms); // TODO: Validate URL sw.Write(this.Url); sw.Write("\r\n"); sw.Close(); return ms.ToArray(); } } }