Commit 98d0f226 authored by Emmanuel Milou's avatar Emmanuel Milou
parents fe52ad39 e9ab5571
......@@ -38,6 +38,7 @@ AC_CONFIG_FILES([src/Makefile \
src/audio/codecs/Makefile
src/audio/codecs/ilbc/Makefile \
src/config/Makefile \
src/contact/Makefile \
src/dbus/Makefile \
src/zeroconf/Makefile \
src/video/Makefile \
......
......@@ -30,7 +30,7 @@ endif
ALSAFLAG= -lasound
SUBDIRS = audio config dbus memmanager video mixer $(ZEROCONFDIR)
SUBDIRS = audio config contact dbus memmanager video mixer $(ZEROCONFDIR)
sflphoned_SOURCES = eventthread.cpp main.cpp voiplink.cpp \
managerimpl.cpp observer.cpp \
......@@ -53,6 +53,7 @@ libsflphone_la_LIBADD = \
./audio/libaudio.la \
./dbus/libdbus.la \
./config/libconfig.la \
./contact/libcontact.la \
./memmanager/libmemmanager.la \
./mixer/libmixer.la \
./video/libvideo.la \
......
......@@ -21,25 +21,60 @@
#include "voiplink.h"
#include "manager.h"
#include <string>
Account::Account(const AccountID& accountID) : _accountID(accountID)
{
_link = NULL;
_enabled = false;
_link = NULL;
_enabled = false;
}
Account::~Account()
{
// _link should be destroyed WHERE IT'S CREATED
//delete _link;
//_link = NULL;
}
void
Account::loadConfig()
{
_enabled = Manager::instance().getConfigInt(_accountID, CONFIG_ACCOUNT_ENABLE) ? true : false;
}
// NOW
void
Account::loadConfig()
Account::loadContacts()
{
_enabled = Manager::instance().getConfigInt(_accountID, CONFIG_ACCOUNT_ENABLE) ? true : false;
// TMP
Contact* contact1 = new Contact("1223345", "Guillaume140", "<sip:140@asterix.inside.savoirfairelinux.net>");
_contacts.push_back(contact1);
Contact* contact2 = new Contact("9876543", "SFLphone131", "<sip:131@asterix.inside.savoirfairelinux.net>");
_contacts.push_back(contact2);
Contact* contact3 = new Contact("6867823", "Guillaume201", "<sip:201@192.168.1.202:5066>");
_contacts.push_back(contact3);
Contact* contact4 = new Contact("3417928", "SFLphone203", "<sip:203@192.168.1.202:5066>");
_contacts.push_back(contact4);
// TODO Load contact file containing list of contacts
// or a configuration for LDAP contacts
}
void
Account::subscribeContactsPresence()
{
if(_link->isContactPresenceSupported())
{
// Subscribe to presence for each contact that presence is enabled
std::vector<Contact*>::iterator iter;
for(iter = _contacts.begin(); iter != _contacts.end(); iter++)
{
_link->subscribePresenceForContact(*iter);
}
}
}
void
Account::publishPresence(std::string presenceStatus)
{
if(_link->isContactPresenceSupported())
_link->publishPresenceStatus(presenceStatus);
}
......@@ -20,7 +20,9 @@
#define ACCOUNT_H
#include <string>
#include <vector>
#include "config/config.h"
#include "contact/contact.h"
#include "voiplink.h"
class VoIPLink;
......@@ -46,9 +48,6 @@ typedef std::string AccountID;
#define SIP_STUN_SERVER "STUN.STUNserver"
#define SIP_USE_STUN "STUN.useStun"
/**
* Class account is an interface to protocol account (SIPAccount, IAXAccount)
* It can be enable on loading or activate after.
......@@ -65,7 +64,7 @@ class Account{
* Load the settings for this account.
*/
virtual void loadConfig();
/**
* Get the account ID
* @return constant account id
......@@ -106,6 +105,21 @@ class Account{
*/
VoIPLink::RegistrationState getRegistrationState() { return _link->getRegistrationState(); }
/**
* Load all contacts
*/
void loadContacts();
/**
* Suscribe presence information for selected contacts if supported
*/
void subscribeContactsPresence();
/**
* Publish our presence information to the server
*/
void publishPresence(std::string presenceStatus);
private:
protected:
......@@ -127,7 +141,11 @@ protected:
* Modified by the configuration (key: ENABLED)
*/
bool _enabled;
/**
* Contacts related to account that can have presence information
*/
std::vector<Contact*> _contacts;
};
#endif
SUBDIRS =
noinst_LTLIBRARIES = \
libcontact.la
libcontact_la_SOURCES = \
contact.h \
presence.h \
contact.cpp \
presence.cpp
/*
* Copyright (C) 2008 Savoir-Faire Linux inc.
* Author: Guillaume Carmel-Archambault <guillaume.carmel-archambault@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 3 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 "contact.h"
#include <string>
Contact::Contact()
{
}
Contact::Contact(const std::string contactID, const std::string name, const std::string url)
{
_contactID = contactID;
_name = name;
_url = url;
_suscribeToPresence = true;
_presence = NULL;
}
Contact::~Contact()
{
}
/*
* Copyright (C) 2008 Savoir-Faire Linux inc.
* Author: Guillaume Carmel-Archambault <guillaume.carmel-archambault@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 3 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 CONTACT_H
#define CONTACT_H
#include "presence.h"
#include <string>
typedef std::string ContactID;
/**
* TOCOMMENT
* @author Guillaume Carmel-Archambault
*/
class Contact {
public:
Contact();
Contact(const std::string contactID, const std::string name, const std::string url);
virtual ~Contact();
std::string getUrl() { return _url; }
protected:
private:
ContactID _contactID;
std::string _name;
std::string _url;
bool _suscribeToPresence;
// Presence information, can be null
Presence* _presence;
};
#endif
/*
* Copyright (C) 2008 Savoir-Faire Linux inc.
* Author: Guillaume Carmel-Archambault <guillaume.carmel-archambault@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 3 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 "presence.h"
Presence::Presence()
{
}
Presence::~Presence()
{
}
/*
* Copyright (C) 2008 Savoir-Faire Linux inc.
* Author: Guillaume Carmel-Archambault <guillaume.carmel-archambault@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 3 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 PRESENCE_H
#define PRESENCE_H
#include <string>
/**
* TOCOMMENT
* @author Guillaume Carmel-Archambault
*/
class Presence {
public:
Presence();
virtual ~Presence();
protected:
private:
std::string _state;
std::string _capabalities;
};
#endif
/*
* Copyright (C) 2008 Savoir-Faire Linux inc.
* Author: Guillaume Carmel-Archambault <guillaume.carmel-archambault@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 3 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 PRESENCE_STATUS_H
#define PRESENCE_STATUS_H
/* Definition of all presence status used by the deamon and the GUI
* The deamon knows how to identify tags coming from presence servers
* and cast them in a defined presence status presented here.
* The presence information is transmitted along DBus by those strings.
* The GUI can format and translate these strings for presentation.
*
* If a presence status identified by a string cannot be identified
* when sent from a presence server, we directly use the raw string
* without any formating or translation process possible
*/
// Same presence status as defined in Asterisk
#define PRESENCE_UNKNOWN "UNKNOWN"
#define PRESENCE_NOT_IN_USE "NOT_IN_USE"
#define PRESENCE_INUSE "INUSE"
#define PRESENCE_BUSY "BUSY"
#define PRESENCE_INVALID "INVALID"
#define PRESENCE_UNAVAILABLE "UNAVAILABLE"
#define PRESENCE_RINGING "RINGING"
#define PRESENCE_RING_IN_USE "RING_IN_USE"
#define PRESENCE_HOLD_IN_USE "HOLD_IN_USE"
#define PRESENCE_ON_HOLD "ON_HOLD"
// Presence status defined on some hardware phones
#define PRESENCE_ONLINE "ONLINE"
#define PRESENCE_BUSY "BUSY"
#define PRESENCE_BE_RIGHT_BACK "BE_RIGHT_BACK"
#define PRESENCE_AWAY "AWAY"
#define PRESENCE_OUT_TO_LUNCH "OUT_TO_LUNCH"
#define PRESENCE_OFFLINE "OFFLINE"
#define PRESENCE_DO_NOT_DISTURB "DO_NOT_DISTURB"
// Other presence status defined supported
#define PRESENCE_IN_REUNION "IN_REUNION"
#define PRESENCE_IN_CONFERENCE_CALL "IN_CONFERENCE_CALL"
#endif
......@@ -84,6 +84,7 @@ public:
bool refuse (const CallID& id);
bool carryingDTMFdigits(const CallID& id, char code);
bool sendMessage(const std::string& to, const std::string& body) { return false; }
bool isContactPresenceSupported() { return false; }
public: // iaxvoiplink only
void setHost(const std::string& host) { _host = host; }
......
......@@ -47,6 +47,8 @@
#include "user_cfg.h"
#include "contact/presencestatus.h"
#ifdef USE_ZEROCONF
#include "zeroconf/DNSService.h"
#include "zeroconf/DNSServiceTXTRecord.h"
......@@ -433,18 +435,22 @@ ManagerImpl::saveConfig (void)
bool
ManagerImpl::initRegisterAccounts()
{
_debugInit("Initiate VoIP Links Registration");
AccountMap::iterator iter = _accountMap.begin();
while( iter != _accountMap.end() ) {
if ( iter->second) {
iter->second->loadConfig();
if ( iter->second->isEnabled() ) {
iter->second->registerVoIPLink();
}
}
iter++;
}
return true;
_debugInit("Initiate VoIP Links Registration");
AccountMap::iterator iter = _accountMap.begin();
while( iter != _accountMap.end() ) {
if ( iter->second) {
iter->second->loadConfig();
if ( iter->second->isEnabled() ) {
// NOW
iter->second->registerVoIPLink();
iter->second->loadContacts();
iter->second->publishPresence(PRESENCE_ONLINE);
iter->second->subscribeContactsPresence();
}
}
iter++;
}
return true;
}
//THREAD=Main
......@@ -465,7 +471,11 @@ ManagerImpl::registerAccount(const AccountID& accountId)
}
iter++;
}
// NOW
account->registerVoIPLink();
account->loadContacts();
account->publishPresence(PRESENCE_ONLINE);
account->subscribeContactsPresence();
}
return true;
}
......
......@@ -212,158 +212,229 @@ SIPVoIPLink::loadSIPLocalIP()
void
SIPVoIPLink::getEvent()
{
eXosip_event_t* event = eXosip_event_wait(0, 50);
eXosip_lock();
eXosip_automatic_action();
eXosip_unlock();
if (event == NULL) {
return;
}
_debug("> SIP Event: [cdt=%4d:%4d:%4d] type=#%03d %s \n", event->cid, event->did, event->tid, event->type, event->textinfo);
switch (event->type) {
/* REGISTER related events */
case EXOSIP_REGISTRATION_NEW: /** 00 < announce new registration. */
_debug(" !EXOSIP_REGISTRATION_NEW event is not implemented\n");
break;
case EXOSIP_REGISTRATION_SUCCESS: /** 01 < user is successfully registred. */
setRegistrationState(Registered);
//Manager::instance().registrationSucceed(getAccountID());
break;
case EXOSIP_REGISTRATION_FAILURE: /** 02 < user is not registred. */
setRegistrationState(Error, "SIP registration failure.");
//Manager::instance().registrationFailed(getAccountID());
break;
case EXOSIP_REGISTRATION_REFRESHED: /** 03 < registration has been refreshed. */
_debug(" !EXOSIP_REGISTRATION_REFRESHED event is not implemented\n");
break;
case EXOSIP_REGISTRATION_TERMINATED: /** 04 < UA is not registred any more. */
setRegistrationState(Unregistered, "Registration terminated by remote host");
_debug(" !EXOSIP_REGISTRATION_TERMINATED event is not implemented\n");
break;
/* INVITE related events within calls */
case EXOSIP_CALL_INVITE: /** 05 < announce a new call */
SIPCallInvite(event);
break;
case EXOSIP_CALL_REINVITE: /** 06 < announce a new INVITE within call */
SIPCallReinvite(event);
break;
case EXOSIP_CALL_NOANSWER: /** 07 < announce no answer within the timeout */
_debug(" !EXOSIP_CALL_NOANSWER event is not implemented\n");
break;
case EXOSIP_CALL_PROCEEDING: /** 08 < announce processing by a remote app */
_debug(" !EXOSIP_CALL_PROCEEDING event is not implemented\n");
break;
case EXOSIP_CALL_RINGING: /** 09 < announce ringback */
SIPCallRinging(event);
break;
case EXOSIP_CALL_ANSWERED: /** 10 < announce start of call */
SIPCallAnswered(event);
break;
case EXOSIP_CALL_REDIRECTED: /** 11 < announce a redirection */
_debug(" !EXOSIP_CALL_REDIRECTED event is not implemented\n");
break;
case EXOSIP_CALL_REQUESTFAILURE: /** 12 < announce a request failure */
SIPCallRequestFailure(event);
break;
case EXOSIP_CALL_SERVERFAILURE: /** 13 < announce a server failure */
SIPCallServerFailure(event);
break;
case EXOSIP_CALL_GLOBALFAILURE: /** 14 < announce a global failure */
SIPCallServerFailure(event);
break;
case EXOSIP_CALL_ACK: /** 15 < ACK received for 200ok to INVITE */
SIPCallAck(event);
break;
case EXOSIP_CALL_CANCELLED: /** 16 < announce that call has been cancelled */
case EXOSIP_CALL_TIMEOUT: /** 17 < announce that call has failed */
Manager::instance().displayError(" !EXOSIP Call Error not implemented yet");
break;
/* request related events within calls (except INVITE) */
case EXOSIP_CALL_MESSAGE_NEW: /** 18 < announce new incoming MESSAGE. */
SIPCallMessageNew(event);
break;
case EXOSIP_CALL_MESSAGE_PROCEEDING: /** 19 < announce a 1xx for MESSAGE. */
case EXOSIP_CALL_MESSAGE_ANSWERED: /** 20 < announce a 200ok */
// 200 OK
case EXOSIP_CALL_MESSAGE_REDIRECTED: /** 21 < announce a failure. */
case EXOSIP_CALL_MESSAGE_REQUESTFAILURE: /** 22 < announce a failure. */
case EXOSIP_CALL_MESSAGE_SERVERFAILURE: /** 23 < announce a failure. */
case EXOSIP_CALL_MESSAGE_GLOBALFAILURE: /** 24 < announce a failure. */
Manager::instance().displayError(" !EXOSIP Call Message not implemented yet");
break;
case EXOSIP_CALL_CLOSED: /** 25 < a BYE was received for this call */
SIPCallClosed(event);
break;
/* for both UAS & UAC events */
case EXOSIP_CALL_RELEASED: /** 26 < call context is cleared. */
SIPCallReleased(event);
break;
/* response received for request outside calls */
case EXOSIP_MESSAGE_NEW: /** 27 < announce new incoming MESSAGE. */
if (event->request == NULL) { break; }
SIPMessageNew(event);
break;
case EXOSIP_MESSAGE_PROCEEDING: /** 28 < announce a 1xx for MESSAGE. */
case EXOSIP_MESSAGE_ANSWERED: /** 29 < announce a 200ok */
case EXOSIP_MESSAGE_REDIRECTED: /** 30 < announce a failure. */
Manager::instance().displayError(" !EXOSIP Message not implemented yet");
break;
case EXOSIP_MESSAGE_REQUESTFAILURE: /** 31 < announce a failure. */
if (event->response !=0 && event->response->status_code == SIP_METHOD_NOT_ALLOWED) {
Manager::instance().incomingMessage(getAccountID(), "Message are not allowed");
} else {
Manager::instance().displayError(" !EXOSIP_MESSAGE_REQUESTFAILURE not implemented yet");
}
break;
case EXOSIP_MESSAGE_SERVERFAILURE: /** 32 < announce a failure. */
case EXOSIP_MESSAGE_GLOBALFAILURE: /** 33 < announce a failure. */
Manager::instance().displayError(" !EXOSIP Message not implemented yet");
break;
/* Presence and Instant Messaging */
case EXOSIP_SUBSCRIPTION_UPDATE: /** 34 < announce incoming SUBSCRIBE. */
case EXOSIP_SUBSCRIPTION_CLOSED: /** 35 < announce end of subscription. */
Manager::instance().displayError(" !EXOSIP Subscription not implemented yet");
break;
case EXOSIP_SUBSCRIPTION_NOANSWER: /** 37 < announce no answer */
case EXOSIP_SUBSCRIPTION_PROCEEDING: /** 38 < announce a 1xx */
Manager::instance().displayError(" !EXOSIP Subscription resposne not implemented yet");
break;
case EXOSIP_SUBSCRIPTION_ANSWERED: /** 39 < announce a 200ok */
eXosip_lock();
eXosip_automatic_action();
eXosip_unlock();
break;
case EXOSIP_SUBSCRIPTION_REDIRECTED: /** 40 < announce a redirection */
case EXOSIP_SUBSCRIPTION_REQUESTFAILURE: /** 41 < announce a request failure */
case EXOSIP_SUBSCRIPTION_SERVERFAILURE: /** 42 < announce a server failure */
case EXOSIP_SUBSCRIPTION_GLOBALFAILURE: /** 43 < announce a global failure */
case EXOSIP_SUBSCRIPTION_NOTIFY: /** 44 < announce new NOTIFY request */
case EXOSIP_SUBSCRIPTION_RELEASED: /** 45 < call context is cleared. */
Manager::instance().displayError(" !EXOSIP Subscription response not implemented yet.");
break;
case EXOSIP_IN_SUBSCRIPTION_NEW: /** 46 < announce new incoming SUBSCRIBE.*/
case EXOSIP_IN_SUBSCRIPTION_RELEASED: /** 47 < announce end of subscription. */
Manager::instance().displayError(" !EXOSIP Subscription not implemented yet");
break;
case EXOSIP_EVENT_COUNT: /** 48 < MAX number of events */
break;
}
eXosip_event_free(event);
char* tmp2;
eXosip_event_t* event = eXosip_event_wait(0, 50);
eXosip_lock();
eXosip_automatic_action();
eXosip_unlock();
if (event == NULL) {
return;
}
_debug("> SIP Event: [cdt=%4d:%4d:%4d] type=#%03d %s \n", event->cid, event->did, event->tid, event->type, event->textinfo);
switch (event->type) {
/* REGISTER related events */
case EXOSIP_REGISTRATION_NEW: /** 00 < announce new registration. */
_debug(" !EXOSIP_REGISTRATION_NEW event is not implemented\n");
break;
case EXOSIP_REGISTRATION_SUCCESS: /** 01 < user is successfully registred. */