// This file is part of mongoose web server project, // https://github.com/cesanta/mongoose using System; using System.Runtime.InteropServices; [StructLayout(LayoutKind.Sequential)] public struct MongooseHeader { public IntPtr name; // Using IntPtr here because if we use strings here, public IntPtr value; // it won't be properly marshalled. }; // mongoose.h :: struct mg_request_info [StructLayout(LayoutKind.Sequential)] public struct MongooseRequestInfo { public string request_method; public string uri; public string http_version; public string query_string; public string remote_user; public int remote_ip; public int remote_port; public int is_ssl; public IntPtr user_data; public IntPtr conn_data; [MarshalAs(UnmanagedType.ByValArray,SizeConst=64)] public MongooseHeader[] http_headers; }; [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate int MongooseBeginRequest_native(IntPtr conn); public delegate int MongooseBeginRequest(MongooseConnection conn); // mongoose.h :: struct mg_callbacks [StructLayout(LayoutKind.Sequential)] public struct MongooseCallbacks { public MongooseBeginRequest_native begin_request; [MarshalAs(UnmanagedType.ByValArray,SizeConst=20)] public IntPtr[] other_callbacks; }; public class Mongoose { public const string dll_name_ = "mongoose"; public string version_ = "??"; // These are here to store a ref to the callbacks // while they are over in unmanaged code, to prevent garbage collection. private event MongooseBeginRequest_native delegates; private IntPtr ctx_; [DllImport(dll_name_)] private static extern IntPtr mg_start([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPTStr)] string[] options, ref MongooseCallbacks callbacks, IntPtr user_data); [DllImport(dll_name_)] public static extern IntPtr mg_get_request_info(IntPtr conn); [DllImport(dll_name_)] private static extern void mg_stop(IntPtr ctx); [DllImport(dll_name_)] private static extern string mg_version(); public Mongoose(string document_root, string listening_ports, MongooseBeginRequest request_handler) { version_ = mg_version(); string[] options = { "document_root", document_root, "listening_ports", listening_ports, null }; MongooseBeginRequest_native begin_request_cb = delegate(IntPtr conn) { return request_handler(new MongooseConnection(conn, this)); }; MongooseCallbacks callbacks = new MongooseCallbacks(); callbacks.begin_request = begin_request_cb; // Prevent garbage collection delegates += begin_request_cb; ctx_ = mg_start(options, ref callbacks, IntPtr.Zero); } ~Mongoose() { if (this.ctx_ != IntPtr.Zero) { mg_stop(this.ctx_); } this.ctx_ = IntPtr.Zero; } } public class MongooseConnection { public Mongoose mongoose; private IntPtr conn; [DllImport(Mongoose.dll_name_)] private static extern string mg_get_header(IntPtr conn, string name); [DllImport(Mongoose.dll_name_)] private static extern string mg_get_var(IntPtr conn, string name); [DllImport(Mongoose.dll_name_)] public static extern int mg_write(IntPtr conn, string data, int length); public MongooseConnection(IntPtr conn_, Mongoose mongoose_) { mongoose = mongoose_; conn = conn_; } public string get_header(string header_name) { return mg_get_header(this.conn, header_name); } public string get_var(string header_name) { string s = mg_get_var(this.conn, header_name); string copy = "" + s; return copy; } public int write(string data) { return mg_write(this.conn, data, data.Length); } }