// // // Copyright 2002 Rob Tougher // // This file is part of xmlrpc. // // xmlrpc is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // xmlrpc is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with xmlrpc; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // #include "server.hpp" #include "xmlrpc_exceptions.hpp" #include "server_socket.hpp" #include "socket_exceptions.hpp" #include "request.hpp" #include "thread_group.hpp" #include "thread_exceptions.hpp" namespace xmlrpc { class accept_thread { public: accept_thread ( sockets::server_socket& socket, server& s ) : m_socket ( socket ), m_server ( s ) {} ~accept_thread(){} void operator ()() { std::cout << "Thread created: " << (long*)this << "\n"; while ( true ) { try { // // Accept an incoming socket request // sockets::server_socket new_sock; m_socket.accept ( new_sock ); std::string data, tmp; std::cout << "Socket accepted: thread " << (long*)this << "\n"; new_sock >> tmp; data += tmp; // // Keep reading until we get to the terminator. // while ( data.find ( request().terminator(), 0 ) == data.npos ) { tmp = ""; new_sock >> tmp; data += tmp; } if ( data.find ( request().terminator(), 0 ) == data.npos ) { // problem! reply rp; rp.add_error ( "We did not receive a terminator." ); new_sock << rp.get_xml() << rp.terminator(); } else { // Cut the terminator out of the request string. data = data.substr ( 0, data.find ( request().terminator(), 0 ) ); try { request r; r.load_xml ( data ); // // Call the derived class // reply rp = m_server.handle_request ( r ); // // Send the reply back to the client // new_sock << rp.get_xml() << rp.terminator(); } catch ( request_exception& e ) { // problem! reply rp; rp.add_error ( "XML request was not properly formed." ); new_sock << rp.get_xml() << rp.terminator(); } } } catch ( sockets::socket_exception& ) {} } } private: sockets::server_socket& m_socket; server& m_server; }; server::server ( const int port ) : m_port ( port ), m_threads ( 5 ) {} server::~server (){} void server::run() { try { sockets::server_socket server ( m_port ); try { threads::thread_group accept_threads; // create threads for ( int i = 0; i < m_threads; i++ ) { accept_threads.add_thread ( accept_thread ( server, *this ) ); } // wait for the threads to finish accept_threads.join_all(); } catch ( threads::exception& e ) { throw xmlrpc::exception ( "Error while creating the threads." ); } } catch ( sockets::exception& e ) { std::string msg = "Error while running the server: "; msg += e.description(); throw run_exception ( msg ); } } };