diff --git a/src/gui/server/factory.cpp b/src/gui/server/factory.cpp index 0edd6db31485997e6464a0e29260336a5325a81d..fef3d6c6a9a5deb6762baa00cf1352f46735701d 100644 --- a/src/gui/server/factory.cpp +++ b/src/gui/server/factory.cpp @@ -1,8 +1,7 @@ - -#include <iostream> -#include <map> #include <stdexcept> #include <string> +#include <iostream> +#include <map> class Request diff --git a/src/gui/server/guiserver.cpp b/src/gui/server/guiserver.cpp index a2d67b711569556119008d669743b7eb3e0f4519..f48ed8a6d79d41b72d9cc096697e9bfe1ecf8256 100644 --- a/src/gui/server/guiserver.cpp +++ b/src/gui/server/guiserver.cpp @@ -21,24 +21,55 @@ #include <string> #include <iostream> -const std::string RequestFactory::CMD_CALL = "call"; -const std::string RequestFactory::CMD_QUIT = "quit"; -const std::string RequestFactory::CMD_ANWSER = "anwser"; -const std::string RequestFactory::CMD_REFUSE = "refuse"; -const std::string RequestFactory::CMD_HOLD = "hold"; -const std::string RequestFactory::CMD_UNHOLD = "unhold"; -const std::string RequestFactory::CMD_TRANSFER= "transfer"; -const std::string RequestFactory::CMD_MUTE = "mute"; -const std::string RequestFactory::CMD_UNMUTE = "unmute"; + +void +TCPSessionReader::run() +{ + while(!testCancel() && good()) { + std::string output; + std::getline(*this, output); + _gui->pushRequestMessage(output); + } +} + +void +TCPSessionWriter::run() +{ + while (!testCancel() && good()) { + *this << _gui->popResponseMessage() << std::endl; + } +} +std::string +RequestCall::execute(GUIServer *gui) +{ + int serverCallId = gui->outgoingCall(_destination); + if (serverCallId) { + return message("150", "Trying..."); + } else { + return message("500","Server Error"); + } +} // default constructor GUIServer::GUIServer() { + _factory = new RequestFactory(); + _factory->registerRequest< RequestSyntaxError > ("syntaxerror"); + _factory->registerRequest< RequestCall > ("call"); + _factory->registerRequest< RequestQuit > ("quit"); + _factory->registerRequest< RequestAnswer > ("anwser"); + _factory->registerRequest< RequestRefuse > ("refuse"); + _factory->registerRequest< RequestHold > ("hold"); + _factory->registerRequest< RequestUnhold > ("unhold"); + _factory->registerRequest< RequestTransfer > ("transfer"); + _factory->registerRequest< RequestMute > ("mute"); + _factory->registerRequest< RequestUnmute > ("unmute"); } // destructor GUIServer::~GUIServer() { + delete _factory; } int @@ -48,69 +79,35 @@ GUIServer::exec() { //Creating a listening socket. ost::TCPSocket aServer(addr, 3999); - RequestFactory factory; - Request *request; std::cout << "listening on " << aServer.getLocal() << ":" << 3999 << std::endl; - std::string input; // TCPStream input line std::string output; // TCPStream output line + Request *request; + while (std::cin.good()) { // waiting for a new connection std::cout << "waiting for a new connection..." << std::endl; //I'm accepting an incomming connection + sessionIn = new TCPSessionReader(aServer, this); + sessionOut = new TCPSessionWriter(aServer, this); - aServerStream = new ost::TCPStream(aServer); + sessionIn->start(); + sessionOut->start(); // wait for the first message std::cout << "accepting connection..." << std::endl; - *aServerStream << "Welcome to this serveur2" << std::endl; - input = ""; output = ""; - while(aServerStream->good() && input!="quit") { - // lire - std::getline(*aServerStream, input); - - //_eventList.push_back(Event(output)); - - // analyser - std::cout << input << ":" << input.length() << std::endl; - request = factory.createNewRequest(input); - output = request->execute(); + while(sessionIn->good() && sessionOut->good()) { + request = popRequest(); + output = request->execute(this); + pushResponseMessage(output); delete request; - - //aServerStream->parse(); - - /* - if ( output.find("call ") == 0 ) { - callid = outgoingCall(output.substr(5,output.size()-5)); - if ( callid ) { - status = "200 OK "; - status += callid; - status += " Trying status..."; - displayStatus(status); - } - - } else if ( output.find("hangup ") == 0 ) { - //hangup <CSeq/Client> <Call-Id> - int i = hangupCall(callid); - status = "200 OK "; - status += callid; - status += " Hangup."; - displayStatus(status); - } - */ - // repondre - *aServerStream << output << std::endl; } - - delete aServerStream; - std::cout << "end of connection\n"; } - std::cout << "end of listening" << std::endl; } catch(ost::Socket *e) { std::cerr << e->getErrorString() << std::endl; @@ -119,6 +116,57 @@ GUIServer::exec() { return 0; } +void +GUIServer::pushRequestMessage(const std::string &request) +{ + std::cout << "pushRequestMessage" << std::endl; + _mutex.enterMutex(); + _requests.push_back(_factory->create(request)); + _mutex.leaveMutex(); +} + +Request * +GUIServer::popRequest() +{ + Request *request = 0; + while(!request) { + _mutex.enterMutex(); + if ( _requests.size() ) { + request = _requests.front(); + _requests.pop_front(); + } + _mutex.leaveMutex(); + } + return request; +} + +void +GUIServer::pushResponseMessage(const std::string &response) +{ + std::cout << "pushResponseMessage" << std::endl; + _mutex.enterMutex(); + _responses.push_back(response); + _mutex.leaveMutex(); +} + +std::string +GUIServer::popResponseMessage() +{ + bool canPop = false; + std::string message; + while(!canPop) { + _mutex.enterMutex(); + if ( _responses.size() ) { + message = _responses.front(); + _responses.pop_front(); + canPop = true; + } + _mutex.leaveMutex(); + } + return message; +} + + int GUIServer::incomingCall (short id) { @@ -146,74 +194,70 @@ GUIServer::peerHungupCall (short id) void GUIServer::displayTextMessage (short id, const std::string& message) { - if ( aServerStream ) { - *aServerStream << "TEXTMESSAGE " << id << " " << message << std::endl; - } + std::string requestMessage = "500 seq0 s"; + requestMessage += id + " text message: " + message; + pushRequestMessage(requestMessage); } void GUIServer::displayErrorText (short id, const std::string& message) { - if ( aServerStream ) { - *aServerStream << "ERRORTEXT " << id << " " << message << std::endl; - } + std::string requestMessage = "500 seq0 s"; + requestMessage += id + " error text: " + message; + pushRequestMessage(requestMessage); } void GUIServer::displayError (const std::string& error) { - if ( aServerStream ) { - *aServerStream << "ERROR " << error << std::endl; - } + std::string requestMessage = "500 seq0 "; + requestMessage += error; + pushRequestMessage(requestMessage); } void GUIServer::displayStatus (const std::string& status) { - if ( aServerStream ) { - *aServerStream << status << std::endl; - } + std::string requestMessage = "500 seq0 "; + requestMessage += status; + pushRequestMessage(requestMessage); } void GUIServer::displayContext (short id) { - if ( aServerStream ) { - *aServerStream << "CONTEXT " << id << std::endl; - } + std::string requestMessage = "500 seq0 s"; + requestMessage += id + " context"; + pushRequestMessage(requestMessage); } std::string GUIServer::getRingtoneFile (void) { - } void GUIServer::setup (void) { - } int GUIServer::selectedCall (void) { - + } bool GUIServer::isCurrentId (short) { - } void -GUIServer::startVoiceMessageNotification (void) { - +GUIServer::startVoiceMessageNotification (void) +{ } void GUIServer::stopVoiceMessageNotification (void) { - } diff --git a/src/gui/server/guiserver.h b/src/gui/server/guiserver.h index eab61fbded43fdbdce7fa7d41e60563ed5524f1d..be2f36e77b71d06ed37448c0190b0612b8ac37ed 100644 --- a/src/gui/server/guiserver.h +++ b/src/gui/server/guiserver.h @@ -21,67 +21,103 @@ #include "../guiframework.h" #include <string> +#include <iostream> +#include <stdexcept> #include <list> #include <cc++/socket.h> +#include <cc++/thread.h> #include <map> +class GUIServer; class Request { public: - Request(const std::string &sequenceId) : _sequenceId(sequenceId) {} + Request(const std::string &sequenceId, const std::string &arg) : _sequenceId(sequenceId), _arg(arg) {} virtual ~Request() {} - virtual std::string execute() { return ""; } - virtual std::string error(const std::string &code, const std::string &error) + virtual std::string execute(GUIServer *gui) { return ""; } + virtual std::string message(const std::string &code, const std::string &message) { - std::string returnError = code + " " + _sequenceId + " " + error; - return returnError; + std::string returnMessage = code + " " + _sequenceId + " " + message; + return returnMessage; } protected: std::string _sequenceId; + std::string _arg; }; -class RequestCall : public Request +class RequestGlobalCall : public Request { public: - RequestCall(const std::string &sequenceId, const std::string &arg) : Request(sequenceId), _arg(arg) {} - virtual ~RequestCall() {} - virtual std::string execute() + RequestGlobalCall(const std::string &sequenceId, const std::string &arg) : Request(sequenceId,arg) { + unsigned int spacePos = _arg.find(' '); + if (spacePos == std::string::npos) { + // only one argument, so it's must be the callid + _callid = _arg; + } else { + _callid = _arg.substr(0, spacePos); + _arg = _arg.substr(spacePos+1, _arg.size()-spacePos+1); + } + } + virtual ~RequestGlobalCall() {} + virtual std::string execute(GUIServer *gui) { std::string returnOK = std::string("200 ") + _sequenceId + " OK"; return returnOK; } - std::string _arg; +protected: + std::string _callid; }; -class RequestAnswer : public RequestCall { +class RequestCall : public RequestGlobalCall { public: - RequestAnswer(const std::string &sequenceId, const std::string &arg) : RequestCall(sequenceId,arg) {} + RequestCall(const std::string &sequenceId, const std::string &arg) : RequestGlobalCall(sequenceId,arg) { + // only one argument, so it's must be the account (that switch is JP fault) + _account = _callid; + _callid = ""; + unsigned int spacePos = _arg.find(' '); + if (spacePos == std::string::npos) { + _callid = _arg; + } else { + _callid = _arg.substr(0, spacePos); + _destination = _arg.substr(spacePos+1, _arg.size()-spacePos+1); + } + } + std::string execute(GUIServer *gui); + +private: + std::string _destination; + std::string _account; +}; + +class RequestAnswer : public RequestGlobalCall { +public: + RequestAnswer(const std::string &sequenceId, const std::string &arg) : RequestGlobalCall(sequenceId,arg) {} }; -class RequestRefuse : public RequestCall { +class RequestRefuse : public RequestGlobalCall { public: - RequestRefuse(const std::string &sequenceId, const std::string &arg) : RequestCall(sequenceId,arg) {} + RequestRefuse(const std::string &sequenceId, const std::string &arg) : RequestGlobalCall(sequenceId,arg) {} }; -class RequestHold : public RequestCall { +class RequestHold : public RequestGlobalCall { public: - RequestHold(const std::string &sequenceId, const std::string &arg) : RequestCall(sequenceId,arg) {} + RequestHold(const std::string &sequenceId, const std::string &arg) : RequestGlobalCall(sequenceId,arg) {} }; -class RequestUnhold : public RequestCall { +class RequestUnhold : public RequestGlobalCall { public: - RequestUnhold(const std::string &sequenceId, const std::string &arg) : RequestCall(sequenceId,arg) {} + RequestUnhold(const std::string &sequenceId, const std::string &arg) : RequestGlobalCall(sequenceId,arg) {} }; -class RequestTransfer : public RequestCall { +class RequestTransfer : public RequestGlobalCall { public: - RequestTransfer(const std::string &sequenceId, const std::string &arg) : RequestCall(sequenceId,arg) {} + RequestTransfer(const std::string &sequenceId, const std::string &arg) : RequestGlobalCall(sequenceId,arg) {} }; class RequestGlobal : public Request { public: - RequestGlobal(const std::string &sequenceId) : Request(sequenceId) {} + RequestGlobal(const std::string &sequenceId, const std::string &arg) : Request(sequenceId,arg) {} virtual ~RequestGlobal() {} - virtual std::string execute() + virtual std::string execute(const GUIServer *gui) { std::string returnOK = std::string("200 ") + _sequenceId + " OK"; return returnOK; @@ -90,15 +126,15 @@ public: class RequestMute : public RequestGlobal { public: - RequestMute(const std::string &sequenceId) : RequestGlobal(sequenceId) {} + RequestMute(const std::string &sequenceId, const std::string &arg) : RequestGlobal(sequenceId,arg) {} }; class RequestUnmute : public RequestGlobal { public: - RequestUnmute(const std::string &sequenceId) : RequestGlobal(sequenceId) {} + RequestUnmute(const std::string &sequenceId, const std::string &arg) : RequestGlobal(sequenceId,arg) {} }; class RequestQuit : public RequestGlobal { public: - RequestQuit(const std::string &sequenceId) : RequestGlobal(sequenceId) {} + RequestQuit(const std::string &sequenceId, const std::string &arg) : RequestGlobal(sequenceId,arg) {} }; @@ -106,23 +142,45 @@ public: class RequestSyntaxError : public Request { public: - RequestSyntaxError(const std::string &sequenceId = "seq0") : Request(sequenceId) {} + RequestSyntaxError(const std::string &sequenceId, const std::string &arg) : Request(sequenceId, arg) {} ~RequestSyntaxError() {} std::string execute() { - return error("501", "Syntax Error"); + return message("501", "Syntax Error"); } }; -class RequestFactory +class RequestCreatorBase +{ +public: + virtual Request *create(const std::string &sequenceId, const std::string &arg) = 0; + virtual RequestCreatorBase *clone() = 0; +}; + +template< typename T > +class RequestCreator : public RequestCreatorBase { public: - RequestFactory(){ + virtual Request *create(const std::string &sequenceId, const std::string &arg) + { + return new T(sequenceId, arg); } - ~RequestFactory(){ + + virtual RequestCreatorBase *clone() + { + return new RequestCreator< T >(); } - - Request* createNewRequest(const std::string &requestLine) +}; + + +class RequestFactory +{ +public: + Request *create(const std::string &requestLine) { + std::string requestName; + std::string sequenceId="seq0"; + std::string arguments; + unsigned int spacePos = requestLine.find(' '); // we find a spacePos if (spacePos != std::string::npos) { @@ -135,58 +193,84 @@ public: 5 for 4 = (spacePos+1 for spacePos2-spacePos-1) 10 for 5 = (spacePos2+1 for size - spacePos2+1) */ - std::string cmd = requestLine.substr(0, spacePos); + requestName = requestLine.substr(0, spacePos); unsigned int spacePos2 = requestLine.find(' ', spacePos+1); if (spacePos2 == std::string::npos) { // command that end with a sequence number - std::string seq = requestLine.substr(spacePos+1, requestLine.size()-spacePos+1); - - if (cmd == CMD_MUTE) { - return new RequestMute(seq); - } else if (cmd == CMD_UNMUTE) { - return new RequestUnmute(seq); - } else if (cmd == CMD_QUIT) { - return new RequestQuit(seq); - } else { - return new RequestSyntaxError(seq); - } + sequenceId = requestLine.substr(spacePos+1, requestLine.size()-spacePos+1); } else { - std::string seq = requestLine.substr(spacePos+1, spacePos2-spacePos-1); - std::string arg = requestLine.substr(spacePos2+1, requestLine.size()-spacePos2+1); - - // command with args - if (cmd == CMD_CALL) { - return new RequestCall(seq, arg); - } else if (cmd == CMD_ANWSER) { - return new RequestAnswer(seq, arg); - } else if (cmd == CMD_REFUSE) { - return new RequestRefuse(seq, arg); - } else if (cmd == CMD_HOLD) { - return new RequestHold(seq, arg); - } else if (cmd == CMD_UNHOLD) { - return new RequestUnhold(seq, arg); - } else if (cmd == CMD_TRANSFER) { - return new RequestTransfer(seq, arg); - } else { - return new RequestSyntaxError(seq); - } + sequenceId = requestLine.substr(spacePos+1, spacePos2-spacePos-1); + arguments = requestLine.substr(spacePos2+1, requestLine.size()-spacePos2+1); } + } else { + requestName = "syntaxerror"; } - std::cout << "RequestLine: " << requestLine << std::endl; - return new RequestSyntaxError(); + + return create(requestName, sequenceId, arguments); } - static const std::string CMD_CALL; - static const std::string CMD_ANWSER; - static const std::string CMD_REFUSE; - static const std::string CMD_HOLD; - static const std::string CMD_UNHOLD; - static const std::string CMD_TRANSFER; - static const std::string CMD_MUTE; - static const std::string CMD_UNMUTE; - static const std::string CMD_QUIT; + + Request *create( + const std::string &requestname, + const std::string &sequenceId, + const std::string &arg) + { + std::map< std::string, RequestCreatorBase * >::iterator pos = mRequests.find(requestname); + if(pos == mRequests.end()) { + pos = mRequests.find("syntaxerror"); + if(pos == mRequests.end()) { + throw std::runtime_error("there's no request of that name"); + } + } + + return pos->second->create(sequenceId, arg); + } + + template< typename T > + void registerRequest(const std::string &requestname) + { + std::map< std::string, RequestCreatorBase * >::iterator pos = + mRequests.find(requestname); + if(pos != mRequests.end()) { + delete pos->second; + mRequests.erase(pos); + } + + mRequests.insert(std::make_pair(requestname, new RequestCreator< T >())); + } + + private: + std::map< std::string, RequestCreatorBase * > mRequests; }; + +class TCPSessionReader : public ost::TCPSession +{ +public: + TCPSessionReader(ost::TCPSocket &server, GUIServer *gui) : + ost::TCPSession(server), + _gui(gui) {} + + void run(); + +private: + GUIServer *_gui; +}; + +class TCPSessionWriter : public ost::TCPSession +{ +public: + TCPSessionWriter(ost::TCPSocket &server, GUIServer *gui) : + ost::TCPSession(server), + _gui(gui) {} + + void run(); + +private: + GUIServer *_gui; +}; + + class GUIServer : public GuiFramework { public: // GUIServer constructor @@ -196,6 +280,10 @@ public: // exec loop int exec(void); + void pushRequestMessage(const std::string& request); + Request *popRequest(void); + void pushResponseMessage(const std::string& response); + std::string popResponseMessage(void); // Reimplementation of virtual functions virtual int incomingCall (short id); @@ -213,10 +301,16 @@ public: virtual bool isCurrentId (short); virtual void startVoiceMessageNotification (void); virtual void stopVoiceMessageNotification (void); - + + int outgoingCall (const std::string& to) {return GuiFramework::outgoingCall(to);} + private: - ost::TCPStream* aServerStream; - std::map<std::string, Request*> _requestMap; + ost::TCPSession* sessionIn; + ost::TCPSession* sessionOut; + std::list<Request*> _requests; + std::list<std::string> _responses; + RequestFactory *_factory; + ost::Mutex _mutex; }; #endif // __GUI_SERVER_H__