New Architecture (see doc/sflphone-server2.xmi)

This commit is contained in:
yanmorin
2005-09-26 17:59:42 +00:00
parent bcc70ba8c7
commit 2befedfed9
13 changed files with 438 additions and 131 deletions

View File

@ -42,19 +42,6 @@ GUIServerImpl::exec() {
}
bool
GUIServerImpl::outgoingCall (const std::string& seq, const std::string& callid, const std::string& to)
{
short serverCallId = GuiFramework::outgoingCall(to);
if ( serverCallId ) {
SubCall subcall(seq, callid);
insertSubCall(serverCallId, subcall);
return true;
} else {
return false;
}
}
/**
* SubCall operations
* insert
@ -95,17 +82,100 @@ GUIServerImpl::getIdFromCallId(const std::string& callId)
throw std::runtime_error("No match for this CallId");
}
void
GUIServerImpl::hangup(const std::string& callId) {
bool
GUIServerImpl::outgoingCall (const std::string& seq, const std::string& callid, const std::string& to)
{
short serverCallId = GuiFramework::outgoingCall(to);
if ( serverCallId ) {
SubCall subcall(seq, callid);
insertSubCall(serverCallId, subcall);
return true;
} else {
return false;
}
}
bool
GUIServerImpl::answerCall(const std::string& callId)
{
try {
short id = getIdFromCallId(callId);
// There was a problem when hanging up...
if (!GuiFramework::hangupCall(id)) {
throw std::runtime_error("Error when hangup");
if (GuiFramework::answerCall(id)) {
return true;
}
} catch(...) {
throw;
return false;
}
return false;
}
bool
GUIServerImpl::refuseCall(const std::string& callId)
{
try {
short id = getIdFromCallId(callId);
if (GuiFramework::refuseCall(id)) {
return true;
}
} catch(...) {
return false;
}
return false;
}
bool
GUIServerImpl::holdCall(const std::string& callId)
{
try {
short id = getIdFromCallId(callId);
if (GuiFramework::onHoldCall(id)) {
return true;
}
} catch(...) {
return false;
}
return false;
}
bool
GUIServerImpl::unholdCall(const std::string& callId)
{
try {
short id = getIdFromCallId(callId);
if (GuiFramework::offHoldCall(id)) {
return true;
}
} catch(...) {
return false;
}
return false;
}
bool
GUIServerImpl::hangupCall(const std::string& callId)
{
try {
short id = getIdFromCallId(callId);
if (GuiFramework::hangupCall(id)) {
return true;
}
} catch(...) {
return false;
}
return false;
}
bool
GUIServerImpl::dtmfCall(const std::string& callId, const std::string& dtmfKey)
{
try {
short id = getIdFromCallId(callId);
char code = dtmfKey[0];
return GuiFramework::sendDtmf(id, code);
} catch(...) {
return false;
}
return false;
}
int
@ -140,6 +210,16 @@ GUIServerImpl::peerRingingCall (short id)
int
GUIServerImpl::peerHungupCall (short id)
{
CallMap::iterator iter = _callMap.find(id);
if ( iter != _callMap.end() ) {
std::ostringstream responseMessage;
responseMessage << iter->second.callId() << " hangup";
_requestManager.sendResponse(ResponseMessage("250", "seq0", responseMessage.str()));
// remove this call...
_callMap.erase(id);
}
return 0;
}

View File

@ -61,8 +61,13 @@ public:
bool outgoingCall (const std::string& seq,
const std::string& callid,
const std::string& to);
bool answerCall(const std::string& callId);
bool refuseCall(const std::string& callId);
bool holdCall(const std::string& callId);
bool unholdCall(const std::string& callId);
bool hangupCall(const std::string& callId);
bool dtmfCall(const std::string& callId, const std::string& dtmfKey);
void hangup(const std::string& callId);
void quit() {_shouldQuit=true;}
private:

View File

@ -26,33 +26,44 @@ RequestCall::execute()
{
if ( GUIServer::instance().outgoingCall(_sequenceId, _callId, _destination) ) {
return message("150", "Trying");
} else {
return message("500","Server Error");
}
return message("500","Server Error");
}
ResponseMessage
RequestAnswer::execute()
{
return message("200","TODO");
if ( GUIServer::instance().answerCall(_callId) ) {
return message("200", "OK");
}
return message("500","Server Error");
}
ResponseMessage
RequestRefuse::execute()
{
return message("200","TODO");
if ( GUIServer::instance().refuseCall(_callId) ) {
return message("200", "OK");
}
return message("500","Server Error");
}
ResponseMessage
RequestHold::execute()
{
return message("200","TODO");
if ( GUIServer::instance().holdCall(_callId) ) {
return message("200", "OK");
}
return message("500","Server Error");
}
ResponseMessage
RequestUnhold::execute()
{
return message("200","TODO");
if ( GUIServer::instance().unholdCall(_callId) ) {
return message("200", "OK");
}
return message("500","Server Error");
}
ResponseMessage
@ -64,12 +75,37 @@ RequestTransfer::execute()
ResponseMessage
RequestHangup::execute()
{
try {
GUIServer::instance().hangup(_callId);
if ( GUIServer::instance().hangupCall(_callId) ) {
return message("200", "OK");
} catch (...) {
return message("500", "Hangup Error");
}
return message("500", "Hangup Error");
}
RequestDTMF::RequestDTMF(const std::string &sequenceId,
const TokenList& argList) : RequestGlobalCall(sequenceId, argList)
{
TokenList::iterator iter = _argList.begin();
// check for the dtmf key
bool argsAreValid = false;
if (iter != _argList.end() && (*iter).length()==1) {
_dtmfKey = *iter;
_argList.pop_front();
argsAreValid = true;
}
if (!argsAreValid) {
throw RequestConstructorException();
}
}
ResponseMessage
RequestDTMF::execute()
{
if ( GUIServer::instance().dtmfCall(_callId, _dtmfKey) ) {
return message("200", "OK");
}
return message("500", "DTMF Error");
}

View File

@ -140,6 +140,17 @@ public:
ResponseMessage execute();
};
class RequestDTMF : public RequestGlobalCall {
public:
RequestDTMF(const std::string &sequenceId,
const TokenList& argList);
ResponseMessage execute();
private:
std::string _dtmfKey;
};
class RequestGlobal : public Request
{
public:

View File

@ -92,6 +92,7 @@ RequestFactory::registerAll() {
registerRequest<RequestHold> ("hold");
registerRequest<RequestUnhold> ("unhold");
registerRequest<RequestHangup> ("hangup");
registerRequest<RequestDTMF> ("dtmf");
registerRequest<RequestTransfer> ("transfer");
registerRequest<RequestMute> ("mute");
registerRequest<RequestUnmute> ("unmute");

View File

@ -30,6 +30,7 @@ RequestManager::RequestManager() : _sessionIO(0)
RequestManager::~RequestManager()
{
delete _sessionIO;
flushWaitingRequest();
}
@ -37,43 +38,39 @@ int
RequestManager::exec()
{
try {
ost::InetAddress addr("127.0.0.1");
// waiting for a new connection
std::cout << "waiting for a new connection..." << std::endl;
//Creating a listening socket
ost::TCPSocket aServer(addr, 3999);
// TCPSessionIO start a thread for the stream socket
_sessionIO = new TCPSessionIO();
// wait for the first message
std::cout << "accepting connection..." << std::endl;
ResponseMessage outputResponse; // TCPStream output line
std::string input;
std::string output;
Request *request;
while (std::cin.good()) {
_sessionIO->init();
// waiting for a new connection
std::cout << "waiting for a new connection..." << std::endl;
// std::cin.good() is only there to close the server when
// we do a CTRL+D
while(std::cin.good()) {
//I'm accepting an incomming connection
_sessionIO = new TCPSessionIO(aServer);
_sessionIO->start();
if (_sessionIO->receive(input)) {
// wait for the first message
std::cout << "accepting connection..." << std::endl;
request = _factory.create(input);
outputResponse = request->execute();
while(_sessionIO->good()) {
_sessionIO->send(outputResponse.toString());
if ( _sessionIO->receive(input)) {
handleExecutedRequest(request, outputResponse);
} // end pop
request = _factory.create(input);
outputResponse = request->execute();
_sessionIO->send(outputResponse.toString());
handleExecutedRequest(request, outputResponse);
} // end pop
} // end streaming
} // end server side : ctrl + d
} // end streaming
delete _sessionIO;
_sessionIO = 0;
} catch(ost::Socket *e) {
std::cerr << e->getErrorString() << std::endl;
@ -126,9 +123,7 @@ void
RequestManager::sendResponse(const ResponseMessage& response) {
if (_sessionIO) {
_sessionIO->send(response.toString());
} else {
std::cerr << "RequestManager::sendResponse: no initialize sessionIO" << response.toString() << std::endl;
}
}
// remove the request from the waiting requests list
if (response.isFinal()) {

View File

@ -21,7 +21,7 @@
#include <cc++/thread.h>
#include "tcpsessionio.h"
#include "sessionio.h"
#include "requestfactory.h"
#include "responsemessage.h"
@ -42,7 +42,7 @@ private:
void handleExecutedRequest(Request * const request, const ResponseMessage& response);
RequestFactory _factory;
TCPSessionIO* _sessionIO;
SessionIO* _sessionIO;
// waiting requests
ost::Mutex _waitingRequestsMutex;

View File

@ -0,0 +1,30 @@
/**
* Copyright (C) 2005 Savoir-Faire Linux inc.
* Author: Yan Morin <yan.morin@savoirfairelinux.com>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "sessionio.h"
SessionIO::SessionIO()
{
}
SessionIO::~SessionIO()
{
}

View File

@ -0,0 +1,40 @@
/**
* Copyright (C) 2005 Savoir-Faire Linux inc.
* Author: Yan Morin <yan.morin@savoirfairelinux.com>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef SESSIONIO_H
#define SESSIONIO_H
#include <string>
/**
Session IO Interface to send and receive requests
Could be over network or locally
@author Yan Morin
*/
class SessionIO {
public:
SessionIO();
virtual ~SessionIO();
virtual void send(const std::string& response) = 0;
virtual bool receive(std::string& request) = 0;
virtual bool good() = 0;
virtual void init() = 0;
};
#endif

View File

@ -1,52 +1,68 @@
/**
* Copyright (C) 2005 Savoir-Faire Linux inc.
* Author: Yan Morin <yan.morin@savoirfairelinux.com>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
//
// C++ Implementation: tcpsessionio
//
// Description:
//
//
// Author: Yan Morin <yan.morin@savoirfairelinux.com>, (C) 2005
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "tcpsessionio.h"
#include "../../global.h"
void
TCPSessionIO::run() {
std::string output;
std::string input;
while(!testCancel() && good()) {
if (isPending(ost::TCPSocket::pendingInput, 10)) {
std::getline(*this, input);
_inputPool.push(input);
}
if (_outputPool.pop(output, 10LU)) {
*this << output << std::endl;
}
const int TCPSessionIO::PORT = 3999;
const char * const TCPSessionIO::IP = "127.0.0.1";
TCPSessionIO::TCPSessionIO() : SessionIO()
{
_clientStream = 0;
ost::InetAddress addr(IP);
//Creating a listening socket
_serverSocket = new ost::TCPSocket(addr, PORT);
}
TCPSessionIO::~TCPSessionIO()
{
delete _clientStream;
delete _serverSocket;
}
bool
TCPSessionIO::good()
{
if (_clientStream) { // just in case
_debug("_clientStream->good() == %d\n", _clientStream->good());
return _clientStream->good();
}
_debug("_clientStream doesn't exists yet...");
return false;
}
void
TCPSessionIO::send(const std::string& response)
{
_outputPool.push(response);
if (_clientStream) { // just in case
_clientStream->send(response);
}
}
bool
TCPSessionIO::receive(std::string& request)
{
if ( _inputPool.pop(request, 10LU) ) {
return true;
if (_clientStream) { // just in case
return _clientStream->receive(request);
}
return false;
}
void
TCPSessionIO::init() {
// this is strange to create a waiting client here...
_clientStream = new TCPStreamPool(*_serverSocket);
_clientStream->start();
}

View File

@ -1,53 +1,41 @@
/**
* Copyright (C) 2005 Savoir-Faire Linux inc.
* Author: Yan Morin <yan.morin@savoirfairelinux.com>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
//
// C++ Interface: tcpsessionio
//
// Description:
//
//
// Author: Yan Morin <yan.morin@savoirfairelinux.com>, (C) 2005
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TCPSESSIONIO_H
#define TCPSESSIONIO_H
#include <string>
#include <cc++/socket.h>
#include "ObjectPool.hpp"
#include "sessionio.h"
#include "tcpstreampool.h"
/**
* Utilisation:
* TCPSessionIO session = TCPSessionIO(aServer);
* std::string response = "hello";
* std::string request;
* session.start();
* session.send(response);
* while(session.receive(request)) {
* std::cout << request << std::endl;
* }
* @author Yan Morin
@author Yan Morin
*/
class TCPSessionIO : public ost::TCPSession
class TCPSessionIO : public SessionIO
{
public:
TCPSessionIO(ost::TCPSocket& server) : ost::TCPSession(server) {}
TCPSessionIO();
~TCPSessionIO();
void run();
void send(const std::string& response);
bool receive(std::string& request);
void send(const std::string& response);
bool receive(std::string& request);
bool good();
void init();
private:
ObjectPool<std::string> _outputPool;
ObjectPool<std::string> _inputPool;
ost::TCPSocket* _serverSocket;
TCPStreamPool* _clientStream;
static const int PORT;
static const char * const IP;
};
#endif

View File

@ -0,0 +1,52 @@
/**
* Copyright (C) 2005 Savoir-Faire Linux inc.
* Author: Yan Morin <yan.morin@savoirfairelinux.com>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "tcpstreampool.h"
void
TCPStreamPool::run() {
std::string output;
std::string input;
while(!testCancel() && good()) {
if (isPending(ost::TCPSocket::pendingInput, 2)) {
std::getline(*this, input);
_inputPool.push(input);
}
if (_outputPool.pop(output, 2LU)) {
*this << output << std::endl;
}
}
}
void
TCPStreamPool::send(const std::string& response)
{
_outputPool.push(response);
}
bool
TCPStreamPool::receive(std::string& request)
{
if ( _inputPool.pop(request, 2LU) ) {
return true;
}
return false;
}

View File

@ -0,0 +1,53 @@
/**
* Copyright (C) 2005 Savoir-Faire Linux inc.
* Author: Yan Morin <yan.morin@savoirfairelinux.com>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef TCPSTREAMPOOL_H
#define TCPSTREAMPOOL_H
#include <string>
#include <cc++/socket.h>
#include "ObjectPool.hpp"
/**
* Utilisation:
* TCPSessionIO session = TCPStreamPool(aServer);
* std::string response = "hello";
* std::string request;
* session.start();
* session.send(response);
* while(session.receive(request)) {
* std::cout << request << std::endl;
* }
* @author Yan Morin
*/
class TCPStreamPool : public ost::TCPSession
{
public:
TCPStreamPool(ost::TCPSocket& server) : ost::TCPSession(server) {}
void run();
void send(const std::string& response);
bool receive(std::string& request);
private:
ObjectPool<std::string> _outputPool;
ObjectPool<std::string> _inputPool;
};
#endif