From 9ed0a8dbad121b64ca8baca78f28ca58602c47ca Mon Sep 17 00:00:00 2001 From: MW Date: Wed, 25 Apr 2007 18:12:06 +0000 Subject: updated to use lastest version of libsl but is currently broke when using SL viewer 1.15.02, due to big changes in the message templates. --- XmlRpcCS/XmlRpcServer.cs | 239 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 XmlRpcCS/XmlRpcServer.cs (limited to 'XmlRpcCS/XmlRpcServer.cs') diff --git a/XmlRpcCS/XmlRpcServer.cs b/XmlRpcCS/XmlRpcServer.cs new file mode 100644 index 0000000..1c226c1 --- /dev/null +++ b/XmlRpcCS/XmlRpcServer.cs @@ -0,0 +1,239 @@ +namespace Nwc.XmlRpc +{ + using System; + using System.Collections; + using System.IO; + using System.Net; + using System.Net.Sockets; + using System.Text; + using System.Threading; + using System.Xml; + + /// A restricted HTTP server for use with XML-RPC. + /// It only handles POST requests, and only POSTs representing XML-RPC calls. + /// In addition to dispatching requests it also provides a registry for request handlers. + /// + public class XmlRpcServer : IEnumerable + { +#pragma warning disable 0414 // disable "private field assigned but not used" + const int RESPONDER_COUNT = 10; + private TcpListener _myListener; + private int _port; + private IPAddress _address; + private IDictionary _handlers; + private XmlRpcSystemObject _system; + private WaitCallback _wc; +#pragma warning restore 0414 + + ///Constructor with port and address. + ///This constructor sets up a TcpListener listening on the + ///given port and address. It also calls a Thread on the method StartListen(). + ///IPAddress value of the address to listen on. + ///Int value of the port to listen on. + public XmlRpcServer(IPAddress address, int port) + { + _port = port; + _address = address; + _handlers = new Hashtable(); + _system = new XmlRpcSystemObject(this); + _wc = new WaitCallback(WaitCallback); + } + + ///Basic constructor. + ///This constructor sets up a TcpListener listening on the + ///given port. It also calls a Thread on the method StartListen(). IPAddress.Any + ///is assumed as the address here. + ///Int value of the port to listen on. + public XmlRpcServer(int port) : this(IPAddress.Any, port) { } + + /// Start the server. + public void Start() + { + try + { + Stop(); + //start listing on the given port + // IPAddress addr = IPAddress.Parse("127.0.0.1"); + lock (this) + { + _myListener = new TcpListener(IPAddress.Any, _port); + _myListener.Start(); + //start the thread which calls the method 'StartListen' + Thread th = new Thread(new ThreadStart(StartListen)); + th.Start(); + } + } + catch (Exception e) + { + Logger.WriteEntry("An Exception Occurred while Listening :" + e.ToString(), LogLevel.Error); + } + } + + /// Stop the server. + public void Stop() + { + try + { + if (_myListener != null) + { + lock (this) + { + _myListener.Stop(); + _myListener = null; + } + } + } + catch (Exception e) + { + Logger.WriteEntry("An Exception Occurred while stopping :" + + e.ToString(), LogLevel.Error); + } + } + + /// Get an enumeration of my XML-RPC handlers. + /// IEnumerable the handler enumeration. + public IEnumerator GetEnumerator() + { + return _handlers.GetEnumerator(); + } + + /// Retrieve a handler by name. + /// String naming a handler + /// Object that is the handler. + public Object this[String name] + { + get { return _handlers[name]; } + } + + /// + ///This method Accepts new connections and dispatches them when appropriate. + /// + public void StartListen() + { + while (true && _myListener != null) + { + //Accept a new connection + XmlRpcResponder responder = new XmlRpcResponder(this, _myListener.AcceptTcpClient()); + ThreadPool.QueueUserWorkItem(_wc, responder); + } + } + + + /// + ///Add an XML-RPC handler object by name. + /// + ///String XML-RPC dispatch name of this object. + ///Object The object that is the XML-RPC handler. + public void Add(String name, Object obj) + { + _handlers.Add(name, obj); + } + + ///Return a C# object.method name for and XML-RPC object.method name pair. + ///The XML-RPC object.method. + ///String of form object.method for the underlying C# method. + public String MethodName(String methodName) + { + int dotAt = methodName.LastIndexOf('.'); + + if (dotAt == -1) + { + throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD, + XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Bad method name " + methodName); + } + + String objectName = methodName.Substring(0, dotAt); + Object target = _handlers[objectName]; + + if (target == null) + { + throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD, + XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Object " + objectName + " not found"); + } + + return target.GetType().FullName + "." + methodName.Substring(dotAt + 1); + } + + ///Invoke a method described in a request. + ///XmlRpcRequest containing a method descriptions. + /// + /// + public Object Invoke(XmlRpcRequest req) + { + return Invoke(req.MethodNameObject, req.MethodNameMethod, req.Params); + } + + ///Invoke a method on a named handler. + ///String The name of the handler. + ///String The name of the method to invoke on the handler. + ///IList The parameters to invoke the method with. + /// + public Object Invoke(String objectName, String methodName, IList parameters) + { + Object target = _handlers[objectName]; + + if (target == null) + { + throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD, + XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Object " + objectName + " not found"); + } + + return XmlRpcSystemObject.Invoke(target, methodName, parameters); + } + + /// The method the thread pool invokes when a thread is available to handle an HTTP request. + /// TcpClient from the socket accept. + public void WaitCallback(object responder) + { + XmlRpcResponder resp = (XmlRpcResponder)responder; + + if (resp.HttpReq.HttpMethod == "POST") + { + try + { + resp.Respond(); + } + catch (Exception e) + { + Logger.WriteEntry("Failed on post: " + e, LogLevel.Error); + } + } + else + { + Logger.WriteEntry("Only POST methods are supported: " + resp.HttpReq.HttpMethod + + " ignored", LogLevel.Error); + } + + resp.Close(); + } + + /// + /// This function send the Header Information to the client (Browser) + /// + /// HTTP Version + /// Mime Type + /// Total Bytes to be sent in the body + /// + /// Socket reference + static public void HttpHeader(string sHttpVersion, string sMIMEHeader, long iTotBytes, string sStatusCode, TextWriter output) + { + String sBuffer = ""; + + // if Mime type is not provided set default to text/html + if (sMIMEHeader.Length == 0) + { + sMIMEHeader = "text/html"; // Default Mime Type is text/html + } + + sBuffer += sHttpVersion + sStatusCode + "\r\n"; + sBuffer += "Connection: close\r\n"; + if (iTotBytes > 0) + sBuffer += "Content-Length: " + iTotBytes + "\r\n"; + sBuffer += "Server: XmlRpcServer \r\n"; + sBuffer += "Content-Type: " + sMIMEHeader + "\r\n"; + sBuffer += "\r\n"; + + output.Write(sBuffer); + } + } +} -- cgit v1.1