
#ifndef _XMLRPCSERVER_H_
#define _XMLRPCSERVER_H_
//
// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley
//          Copyright (c) 2010 Petr Kubanek, Institute of Physics
//
#if defined(_MSC_VER)
# pragma warning(disable:4786)	 // identifier was truncated in debug info
#endif

#ifndef MAKEDEPEND
# include <map>
# include <string>
#endif

#include "rts2-config.h"

#include "XmlRpcDispatch.h"

#ifdef RTS2_SSL
# include "XmlRpcSocketSSL.h"
#else
# include "XmlRpcSocket.h"
#endif

#include "XmlRpcSource.h"


namespace XmlRpc
{

	// An abstract class supporting XML RPC methods
	class XmlRpcServerMethod;

	// An abstract class supporting HTTP GET requests
	class XmlRpcServerGetRequest;

	// Class representing connections to specific clients
	class XmlRpcServerConnection;

	// Class representing argument and result values
	class XmlRpcValue;

	// collection of get processors. String is prefix of the request
	typedef std::map< std::string, XmlRpcServerGetRequest* > RequestMap;

	//! A class to handle XML RPC requests
	class XmlRpcServer : public XmlRpcSource
	{
		public:
			//! Create a server object.
			XmlRpcServer();

			//! Destructor.
			virtual ~XmlRpcServer();

#ifdef RTS2_SSL
		    int initSSL(const char *certFile, const char *keyFile);
#endif

			//! Specify whether introspection is enabled or not. Default is not enabled.
			void enableIntrospection(bool enabled=true);

			//! Add a command to the RPC server
			void addMethod(XmlRpcServerMethod* method);

			//! Remove a command from the RPC server
			void removeMethod(XmlRpcServerMethod* method);

			//! Remove a command from the RPC server by name
			void removeMethod(const std::string& methodName);

			//! Look up a method by name
			XmlRpcServerMethod* findMethod(const std::string& name) const;

			//! Specify default GET request handler
			void setDefaultGetRequest(XmlRpcServerGetRequest *defaultGetRequest);

			//! Add a GET request to the HTTP server
			void addGetRequest(XmlRpcServerGetRequest* serverGetRequest);

			//! Remove a GET request from HTTP server
			void removeGetRequest(XmlRpcServerGetRequest* serverGetRequest);

			//! Lookup a get request by prefix
			XmlRpcServerGetRequest* findGetRequest(const std::string& prefix) const;

			//! Return begin iterator of request map.
			RequestMap::const_iterator requestsBegin () { return _requests.begin (); }

			//! Return end iterator of request map.
			RequestMap::const_iterator requestsEnd () { return _requests.end (); }

			//! Create a socket, bind to the specified port, and
			//! set it in listen mode to make it available for clients.
			bool bindAndListen(int port, int backlog = 5);

			//! Modify the types of events to watch for on this source
			void setSourceEvents(XmlRpcSource* source, unsigned eventMask);

			//! Process client requests for the specified time
			void work(double msTime);

			//! Add sockets to file descriptor set
			void addToFd (void (* addFD) (int, short));

			//! Check if it should server any of the modified sockets
			void checkFd (short (* getFDEvents) (int));

			//! Temporarily stop processing client requests and exit the work() method.
			void exitWork();

			//! Close all connections with clients and the socket file descriptor
			void shutdown();

			//! Introspection support
			void listMethods(XmlRpcValue& result);

			// XmlRpcSource interface implementation

			//! Handle client connection requests
			virtual unsigned handleEvent(unsigned eventType);

			virtual void goAsync () {}

			virtual void asyncFinished (XmlRpcServerConnection*) {};

			//! Remove a connection from the dispatcher
			virtual void removeConnection(XmlRpcServerConnection*);

		protected:

			//! Accept a client connection request
			virtual void acceptConnection();

			//! Create a new connection object for processing requests from a specific client.
#ifdef _WINDOWS
			virtual XmlRpcServerConnection* createConnection(int socket, struct sockaddr_in *saddr, int addrlen);
#else
			virtual XmlRpcServerConnection* createConnection(int socket, struct sockaddr_in *saddr, socklen_t addrlen);
#endif
			// Whether the introspection API is supported by this server
			bool _introspectionEnabled;

			// Event dispatcher
			XmlRpcDispatch _disp;

			// Collection of methods. This could be a set keyed on method name if we wanted...
			typedef std::map< std::string, XmlRpcServerMethod* > MethodMap;
			MethodMap _methods;

			RequestMap _requests;

			// system methods
			XmlRpcServerMethod* _listMethods;
			XmlRpcServerMethod* _methodHelp;
		private:
			XmlRpcServerGetRequest* _defaultGetRequest;
	};
}								 // namespace XmlRpc
#endif							 //_XMLRPCSERVER_H_
