Commit 3a3b996c authored by yanmorin's avatar yanmorin
Browse files

Implementing registration and outgoing call

parent 9f7579f1
......@@ -26,11 +26,42 @@
#define IAX_SUCCESS 0
#define IAX_FAILURE -1
#define RANDOM_IAX_PORT rand() % 64000 + 1024
// from IAXC : iaxclient.h
/* payload formats : WARNING: must match libiax values!!! */
/* Data formats for capabilities and frames alike */
#define IAX__FORMAT_G723_1 (1 << 0) /* G.723.1 compression */
#define IAX__FORMAT_GSM (1 << 1) /* GSM compression */
#define IAX__FORMAT_ULAW (1 << 2) /* Raw mu-law data (G.711) */
#define IAX__FORMAT_ALAW (1 << 3) /* Raw A-law data (G.711) */
#define IAX__FORMAT_G726 (1 << 4) /* ADPCM, 32kbps */
#define IAX__FORMAT_ADPCM (1 << 5) /* ADPCM IMA */
#define IAX__FORMAT_SLINEAR (1 << 6) /* Raw 16-bit Signed Linear (8000 Hz) PCM */
#define IAX__FORMAT_LPC10 (1 << 7) /* LPC10, 180 samples/frame */
#define IAX__FORMAT_G729A (1 << 8) /* G.729a Audio */
#define IAX__FORMAT_SPEEX (1 << 9) /* Speex Audio */
#define IAX__FORMAT_ILBC (1 << 10) /* iLBC Audio */
#define IAX__FORMAT_MAX_AUDIO (1 << 15) /* Maximum audio format */
#define IAX__FORMAT_JPEG (1 << 16) /* JPEG Images */
#define IAX__FORMAT_PNG (1 << 17) /* PNG Images */
#define IAX__FORMAT_H261 (1 << 18) /* H.261 Video */
#define IAX__FORMAT_H263 (1 << 19) /* H.263 Video */
#define IAX__FORMAT_H263_PLUS (1 << 20) /* H.263+ Video */
#define IAX__FORMAT_MPEG4 (1 << 21) /* MPEG4 Video */
#define IAX__FORMAT_H264 (1 << 23) /* H264 Video */
#define IAX__FORMAT_THEORA (1 << 24) /* Theora Video */
IAXVoIPLink::IAXVoIPLink(const AccountID& accountID)
: VoIPLink(accountID)
{
_evThread = new EventThread(this);
_regSession = 0;
// to get random number for RANDOM_PORT
srand (time(NULL));
}
......@@ -48,17 +79,31 @@ IAXVoIPLink::init()
//_localAddress = "127.0.0.1";
// port 0 is default
// iax_enable_debug(); have to enable debug when compiling iax...
int port = iax_init(IAX_DEFAULT_PORTNO);
if (port == IAX_FAILURE) {
_debug("IAX Failure: Error when initializing\n");
} else if ( port == 0 ) {
_debug("IAX Warning: already initialize\n");
} else {
_debug("IAX Info: listening on port %d\n", port);
_localPort = port;
returnValue = true;
_evThread->start();
int port = IAX_DEFAULT_PORTNO;
int last_port = 0;
int nbTry = 3;
while (port != IAX_FAILURE && nbTry) {
last_port = port;
port = iax_init(port);
if ( port < 0 ) {
_debug("IAX Warning: already initialize on port %d\n", last_port);
port = RANDOM_IAX_PORT;
} else if (port == IAX_FAILURE) {
_debug("IAX Fail to start on port %d", last_port);
port = RANDOM_IAX_PORT;
} else {
_debug("IAX Info: listening on port %d\n", last_port);
_localPort = last_port;
returnValue = true;
_evThread->start();
break;
}
nbTry--;
}
if (port == IAX_FAILURE || nbTry==0) {
_debug("Fail to initialize iax\n");
}
return returnValue;
}
......@@ -75,42 +120,44 @@ void
IAXVoIPLink::getEvent()
{
// mutex here
_mutexIAX.enterMutex();
iax_event* event = 0;
IAXCall* call = 0;
while ( (event = iax_get_event(0)) != 0 ) {
_debug ("Receive IAX Event: %d\n", event->etype);
call = iaxFindCallBySession(event->session);
if (call!=0) {
iaxHandleCallEvent(event, call);
iaxHandleCallEvent(event, call);
} else if (event->session != 0 && event->session == _regSession) {
// in iaxclient, there is many session handling, here, only one
iaxHandleRegReply(event);
// in iaxclient, there is many session handling, here, only one
iaxHandleRegReply(event);
} else {
switch(event->etype) {
case IAX_EVENT_REGACK:
case IAX_EVENT_REGREJ:
_debug("Unknown IAX Registration Event\n");
break;
case IAX_EVENT_REGREQ:
_debug("Registration by a peer, don't allow it\n");
break;
case IAX_EVENT_CONNECT: // new call
// New incoming call!
break;
case IAX_EVENT_TIMEOUT: // timeout for an unknown session
break;
default:
_debug("Unknown event type: %d\n", event->etype);
}
switch(event->etype) {
case IAX_EVENT_REGACK:
case IAX_EVENT_REGREJ:
_debug("Unknown IAX Registration Event\n");
break;
case IAX_EVENT_REGREQ:
_debug("Registration by a peer, don't allow it\n");
break;
case IAX_EVENT_CONNECT: // new call
// New incoming call!
break;
case IAX_EVENT_TIMEOUT: // timeout for an unknown session
break;
default:
_debug("Unknown event type: %d\n", event->etype);
}
}
iax_event_free(event);
}
// unlock mutex here
_mutexIAX.leaveMutex();
//iaxRefreshRegistrations();
// thread wait 5 millisecond
......@@ -130,8 +177,9 @@ IAXVoIPLink::setRegister()
Manager::instance().displayConfigError("Fill user field for IAX Account");
return false;
}
// lock
// lock
_mutexIAX.enterMutex();
_regSession = iax_session_new();
if (!_regSession) {
......@@ -147,12 +195,13 @@ IAXVoIPLink::setRegister()
strcpy(pass, _pass.c_str());
//iax_register don't use const char*
_debug("Sending registration to %s with user %s\n", host, user);
iax_register(_regSession, host, user, pass, 300);
_debug("IAX Sending registration to %s with user %s\n", host, user);
int val = iax_register(_regSession, host, user, pass, 300);
_debug ("Return value: %d\n", val);
result = true;
}
// unlock
_mutexIAX.leaveMutex();
}
return result;
}
......@@ -160,9 +209,69 @@ IAXVoIPLink::setRegister()
bool
IAXVoIPLink::setUnregister()
{
if (_regSession==0) {
// lock here
_mutexIAX.enterMutex();
iax_destroy(_regSession);
_regSession = 0;
// unlock here
_mutexIAX.leaveMutex();
return false;
}
return false;
}
Call*
IAXVoIPLink::newOutgoingCall(const CallID& id, const std::string& toUrl)
{
IAXCall* call = new IAXCall(id, Call::Outgoing);
if (call) {
call->setPeerNumber(toUrl);
// we have to add the codec before using it in SIPOutgoingInvite...
//call->setCodecMap(Manager::instance().getCodecDescriptorMap());
if ( iaxOutgoingInvite(call) ) {
call->setConnectionState(Call::Progressing);
call->setState(Call::Active);
addCall(call);
} else {
delete call; call = 0;
}
}
return call;
}
bool
IAXVoIPLink::iaxOutgoingInvite(IAXCall* call)
{
struct iax_session *newsession;
// lock here
_mutexIAX.enterMutex();
newsession = iax_session_new();
if (!newsession) {
_debug("IAX Error: Can't make new session for a new call\n");
// unlock here
_mutexIAX.leaveMutex();
return false;
}
call->setSession(newsession);
/* reset activity and ping "timers" */
// iaxc_note_activity(callNo);
char num[call->getPeerNumber().length()+1];
strcpy(num, call->getPeerNumber().c_str());
char* lang = NULL;
int wait = 0;
int audio_format_preferred = IAX__FORMAT_SPEEX;
int audio_format_capability = IAX__FORMAT_ULAW | IAX__FORMAT_ALAW | IAX__FORMAT_GSM | IAX__FORMAT_SPEEX;
iax_call(newsession, num, num, num, lang, wait, audio_format_preferred, audio_format_capability);
// unlock here
_mutexIAX.leaveMutex();
return true;
}
IAXCall*
IAXVoIPLink::iaxFindCallBySession(struct iax_session* session)
{
......@@ -196,7 +305,7 @@ IAXVoIPLink::iaxHandleCallEvent(iax_event* event, IAXCall* call)
case IAX_EVENT_ACCEPT:
break;
case IAX_EVENT_ANSWER:
break;
......@@ -233,8 +342,17 @@ IAXVoIPLink::iaxHandleCallEvent(iax_event* event, IAXCall* call)
}
}
void
IAXVoIPLink::iaxHandleRegReply(iax_event* event)
{
// use _regSession here, should be equal to event->session;
//unregister
if (event->etype == IAX_EVENT_REGREJ) {
iax_destroy(_regSession);
_regSession = 0;
Manager::instance().registrationFailed(getAccountID());
} else if (event->etype == IAX_EVENT_REGACK) {
Manager::instance().registrationSucceed(getAccountID());
}
}
......@@ -45,7 +45,7 @@ public:
bool setRegister (void);
bool setUnregister (void);
Call* newOutgoingCall(const CallID& id, const std::string& toUrl) {return 0; }
Call* newOutgoingCall(const CallID& id, const std::string& toUrl);
bool answer(const CallID& id) {return false;}
bool hangup(const CallID& id) { return false; }
......@@ -83,6 +83,11 @@ private:
*/
void iaxHandleRegReply(iax_event* event);
/**
* Send an outgoing call invite to iax
*/
bool iaxOutgoingInvite(IAXCall* Call);
EventThread* _evThread;
/** registration session : 0 if not register */
struct iax_session* _regSession;
......@@ -93,7 +98,8 @@ private:
std::string _user;
/** IAX Password */
std::string _pass;
ost::Mutex _mutexIAX;
};
#endif
......@@ -421,12 +421,11 @@ ManagerImpl::initRegisterVoIPLink()
if ( iter->second) {
iter->second->loadConfig();
if ( iter->second->shouldInitOnStart() ) {
iter->second->init();
if (iter->second->shouldRegisterOnStart()) {
iter->second->registerAccount();
if ( iter->second->init() && iter->second->shouldRegisterOnStart()) {
iter->second->registerAccount();
}
// init only the first account
break;
// init only the first account
break;
}
}
iter++;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment