2004-12-24 18:15:34 +00:00
|
|
|
/**
|
|
|
|
* ysipchan.cpp
|
|
|
|
* This file is part of the YATE Project http://YATE.null.ro
|
|
|
|
*
|
|
|
|
* Yet Another Sip Channel
|
|
|
|
*
|
|
|
|
* Yet Another Telephony Engine - a fully featured software PBX and IVR
|
|
|
|
* Copyright (C) 2004 Null Team
|
|
|
|
*
|
|
|
|
* 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 <telengine.h>
|
|
|
|
#include <telephony.h>
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
2004-12-29 04:02:55 +00:00
|
|
|
#include <netdb.h>
|
2004-12-24 18:15:34 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
/**
|
|
|
|
* we include also the sip stack headers
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <ysip.h>
|
|
|
|
|
|
|
|
using namespace TelEngine;
|
|
|
|
|
|
|
|
static Configuration s_cfg;
|
|
|
|
|
|
|
|
|
|
|
|
class SIPHandler : public MessageHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SIPHandler(const char *name) : MessageHandler(name) { }
|
|
|
|
virtual bool received(Message &msg);
|
|
|
|
};
|
|
|
|
|
|
|
|
class YateUDPParty : public SIPParty
|
|
|
|
{
|
|
|
|
public:
|
2004-12-29 04:02:55 +00:00
|
|
|
YateUDPParty(int fd,struct sockaddr_in sin,int local);
|
2004-12-24 18:15:34 +00:00
|
|
|
~YateUDPParty();
|
|
|
|
virtual void transmit(SIPEvent* event);
|
2004-12-29 04:02:55 +00:00
|
|
|
virtual const char* getProtoName() const;
|
2004-12-24 18:15:34 +00:00
|
|
|
protected:
|
|
|
|
int m_netfd;
|
|
|
|
struct sockaddr_in m_sin;
|
|
|
|
};
|
|
|
|
|
2004-12-29 04:02:55 +00:00
|
|
|
class YateSIPEndPoint;
|
|
|
|
|
2004-12-24 18:15:34 +00:00
|
|
|
class YateSIPEngine : public SIPEngine
|
|
|
|
{
|
2004-12-29 04:02:55 +00:00
|
|
|
public:
|
|
|
|
inline YateSIPEngine(YateSIPEndPoint* ep)
|
|
|
|
: m_ep(ep)
|
|
|
|
{ }
|
|
|
|
virtual bool buildParty(SIPMessage* message);
|
|
|
|
private:
|
|
|
|
YateSIPEndPoint* m_ep;
|
2004-12-24 18:15:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class YateSIPEndPoint : public Thread
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
YateSIPEndPoint();
|
|
|
|
~YateSIPEndPoint();
|
|
|
|
bool Init(void);
|
|
|
|
// YateSIPConnection *findconn(int did);
|
|
|
|
// void terminateall(void);
|
|
|
|
void run(void);
|
2004-12-28 05:15:11 +00:00
|
|
|
void incoming(SIPEvent* e);
|
2004-12-29 04:02:55 +00:00
|
|
|
bool buildParty(SIPMessage* message);
|
2004-12-24 18:15:34 +00:00
|
|
|
inline ObjList &calls()
|
|
|
|
{ return m_calls; }
|
2004-12-29 04:02:55 +00:00
|
|
|
inline YateSIPEngine* engine() const
|
|
|
|
{ return m_engine; }
|
2004-12-24 18:15:34 +00:00
|
|
|
private:
|
|
|
|
ObjList m_calls;
|
|
|
|
int m_localport;
|
|
|
|
int m_port;
|
|
|
|
int m_netfd;
|
|
|
|
YateSIPEngine *m_engine;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
class SIPPlugin : public Plugin
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SIPPlugin();
|
|
|
|
~SIPPlugin();
|
|
|
|
virtual void initialize();
|
2004-12-29 04:02:55 +00:00
|
|
|
inline YateSIPEndPoint* ep() const
|
|
|
|
{ return m_endpoint; }
|
2004-12-24 18:15:34 +00:00
|
|
|
private:
|
|
|
|
SIPHandler *m_handler;
|
|
|
|
YateSIPEndPoint *m_endpoint;
|
|
|
|
};
|
|
|
|
|
2004-12-29 04:02:55 +00:00
|
|
|
static SIPPlugin plugin;
|
2004-12-24 18:15:34 +00:00
|
|
|
|
2004-12-29 04:02:55 +00:00
|
|
|
YateUDPParty::YateUDPParty(int fd,struct sockaddr_in sin, int local)
|
2004-12-24 18:15:34 +00:00
|
|
|
: m_netfd(fd), m_sin(sin)
|
|
|
|
{
|
2004-12-29 04:02:55 +00:00
|
|
|
m_local = "localhost";
|
|
|
|
m_localPort = local;
|
|
|
|
m_party = inet_ntoa(m_sin.sin_addr);
|
|
|
|
m_partyPort = ntohs(m_sin.sin_port);
|
|
|
|
int s = ::socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
|
|
|
|
if (s != -1) {
|
|
|
|
if (!::connect(s, (const sockaddr *)&m_sin, sizeof(m_sin))) {
|
|
|
|
struct sockaddr_in raddr;
|
|
|
|
socklen_t len = sizeof(raddr);
|
|
|
|
if (!::getsockname(s, (sockaddr *)&raddr, &len))
|
|
|
|
m_local = ::inet_ntoa(raddr.sin_addr);
|
|
|
|
}
|
|
|
|
::close(s);
|
|
|
|
}
|
2004-12-24 18:15:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
YateUDPParty::~YateUDPParty()
|
|
|
|
{
|
|
|
|
m_netfd = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void YateUDPParty::transmit(SIPEvent* event)
|
|
|
|
{
|
|
|
|
Debug(DebugAll,"Sending to %s:%d",inet_ntoa(m_sin.sin_addr),ntohs(m_sin.sin_port));
|
|
|
|
::sendto(m_netfd,
|
|
|
|
event->getMessage()->getBuffer().data(),
|
|
|
|
event->getMessage()->getBuffer().length(),
|
|
|
|
0,
|
|
|
|
(struct sockaddr *) &m_sin,
|
|
|
|
sizeof(m_sin)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2004-12-29 04:02:55 +00:00
|
|
|
const char* YateUDPParty::getProtoName() const
|
|
|
|
{
|
|
|
|
return "UDP";
|
|
|
|
}
|
|
|
|
|
|
|
|
bool YateSIPEngine::buildParty(SIPMessage* message)
|
|
|
|
{
|
|
|
|
return m_ep->buildParty(message);
|
|
|
|
}
|
|
|
|
|
2004-12-24 18:15:34 +00:00
|
|
|
YateSIPEndPoint::YateSIPEndPoint()
|
2004-12-29 04:02:55 +00:00
|
|
|
: Thread("YSIP EndPoint"), m_netfd(-1), m_engine(0)
|
2004-12-24 18:15:34 +00:00
|
|
|
{
|
|
|
|
m_netfd = -1;
|
|
|
|
Debug(DebugAll,"YateSIPEndPoint::YateSIPEndPoint() [%p]",this);
|
|
|
|
}
|
|
|
|
|
|
|
|
YateSIPEndPoint::~YateSIPEndPoint()
|
|
|
|
{
|
|
|
|
Debug(DebugAll,"YateSIPEndPoint::~YateSIPEndPoint() [%p]",this);
|
2004-12-29 04:02:55 +00:00
|
|
|
delete m_engine;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool YateSIPEndPoint::buildParty(SIPMessage* message)
|
|
|
|
{
|
|
|
|
if (message->isAnswer())
|
|
|
|
return false;
|
|
|
|
URI uri(message->uri);
|
|
|
|
int port = uri.getPort();
|
|
|
|
if (port <= 0)
|
|
|
|
port = 5060;
|
|
|
|
struct hostent he, *res = 0;
|
|
|
|
int err = 0;
|
|
|
|
char buf[1024];
|
|
|
|
if (::gethostbyname_r(uri.getHost().safe(),&he,buf,sizeof(buf),&res,&err)) {
|
|
|
|
Debug(DebugWarn,"Error %d resolving name '%s'",err,uri.getHost().safe());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
struct sockaddr_in sin;
|
|
|
|
sin.sin_family = he.h_addrtype;
|
|
|
|
sin.sin_addr.s_addr = *((u_int32_t*)he.h_addr_list[0]);
|
|
|
|
sin.sin_port = htons((short)port);
|
|
|
|
Debug(DebugAll,"got addr: %d %08X %04X",sin.sin_family,sin.sin_addr.s_addr,sin.sin_port);
|
|
|
|
message->setParty(new YateUDPParty(m_netfd,sin,m_port));
|
|
|
|
return true;
|
2004-12-24 18:15:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool YateSIPEndPoint::Init ()
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* This part have been taking from libiax after i have lost my sip driver for bayonne
|
|
|
|
*/
|
|
|
|
struct sockaddr_in sin;
|
|
|
|
int port = s_cfg.getIntValue("general","port",5060);
|
|
|
|
m_localport = port;
|
|
|
|
int flags;
|
|
|
|
if (m_netfd > -1) {
|
|
|
|
Debug(DebugInfo,"Already initialized.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
m_netfd = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
|
|
|
if (m_netfd < 0) {
|
|
|
|
Debug(DebugFail,"Unable to allocate UDP socket\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sinlen = sizeof(sin);
|
|
|
|
|
|
|
|
sin.sin_family = AF_INET;
|
|
|
|
sin.sin_addr.s_addr = 0;
|
|
|
|
sin.sin_port = htons((short)port);
|
|
|
|
if (::bind(m_netfd, (struct sockaddr *) &sin, sinlen) < 0) {
|
|
|
|
Debug(DebugFail,"Unable to bind to preferred port. Using random one instead.");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (::getsockname(m_netfd, (struct sockaddr *) &sin, (socklen_t *)&sinlen) < 0) {
|
|
|
|
::close(m_netfd);
|
|
|
|
m_netfd = -1;
|
|
|
|
Debug(DebugFail,"Unable to figure out what I'm bound to.");
|
|
|
|
}
|
|
|
|
if ((flags = ::fcntl(m_netfd, F_GETFL)) < 0) {
|
|
|
|
::close(m_netfd);
|
|
|
|
m_netfd = -1;
|
|
|
|
Debug(DebugFail,"Unable to retrieve socket flags.");
|
|
|
|
}
|
|
|
|
if (::fcntl(m_netfd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
|
|
|
::close(m_netfd);
|
|
|
|
m_netfd = -1;
|
|
|
|
Debug(DebugFail,"Unable to set non-blocking mode.");
|
|
|
|
}
|
|
|
|
port = ntohs(sin.sin_port);
|
|
|
|
Debug(DebugInfo,"Started on port %d\n", port);
|
|
|
|
m_port = port;
|
2004-12-29 04:02:55 +00:00
|
|
|
m_engine = new YateSIPEngine(this);
|
2004-12-24 18:15:34 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void YateSIPEndPoint::run ()
|
|
|
|
{
|
|
|
|
fd_set fds;
|
|
|
|
struct timeval tv;
|
|
|
|
int retval;
|
|
|
|
char buf[1500];
|
|
|
|
struct sockaddr_in sin;
|
|
|
|
/* Watch stdin (fd 0) to see when it has input. */
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
FD_ZERO(&fds);
|
|
|
|
FD_SET(m_netfd, &fds);
|
|
|
|
/* Wait up to 20000 microseconds. */
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 20000;
|
|
|
|
|
|
|
|
retval = select(m_netfd+1, &fds, NULL, NULL, &tv);
|
|
|
|
if (retval)
|
|
|
|
{
|
|
|
|
// we got the dates
|
|
|
|
int sinlen = sizeof(sin);
|
|
|
|
|
|
|
|
int res = ::recvfrom(m_netfd, buf, sizeof(buf)-1, 0, (struct sockaddr *) &sin,(socklen_t *) &sinlen);
|
|
|
|
if (res < 0) {
|
|
|
|
if (errno != EAGAIN) {
|
|
|
|
Debug(DebugFail,"Error on read: %s\n", strerror(errno));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// we got already the buffer and here we start to do "good" stuff
|
|
|
|
buf[res]=0;
|
2004-12-29 04:02:55 +00:00
|
|
|
m_engine->addMessage(new YateUDPParty(m_netfd,sin,m_port),buf,res);
|
2004-12-24 18:15:34 +00:00
|
|
|
// Output("res %d buf %s",res,buf);
|
|
|
|
}
|
|
|
|
}
|
2004-12-28 05:15:11 +00:00
|
|
|
// m_engine->process();
|
|
|
|
SIPEvent* e = m_engine->getEvent();
|
|
|
|
if (e) {
|
|
|
|
if ((e->getState() == SIPTransaction::Trying) && !e->isOutgoing()) {
|
|
|
|
incoming(e);
|
|
|
|
delete e;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m_engine->processEvent(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void YateSIPEndPoint::incoming(SIPEvent* e)
|
|
|
|
{
|
|
|
|
Message *m = new Message("call.preroute");
|
|
|
|
m->addParam("driver","sip");
|
|
|
|
Engine::dispatch(m);
|
|
|
|
*m = "call.route";
|
|
|
|
m->retValue().clear();
|
|
|
|
if (Engine::dispatch(m) && m->retValue()) {
|
|
|
|
e->getTransaction()->setResponse(500, "Server Internal Error");
|
2004-12-24 18:15:34 +00:00
|
|
|
}
|
2004-12-28 05:15:11 +00:00
|
|
|
else
|
|
|
|
e->getTransaction()->setResponse(404, "Not Found");
|
|
|
|
delete m;
|
2004-12-24 18:15:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool SIPHandler::received(Message &msg)
|
|
|
|
{
|
2004-12-29 04:02:55 +00:00
|
|
|
String dest(msg.getValue("callto"));
|
|
|
|
if (!dest.startSkip("sip2/",false))
|
|
|
|
return false;
|
|
|
|
SIPMessage* m = new SIPMessage("INVITE",dest);
|
|
|
|
// m->complete(plugin.ep()->engine());
|
|
|
|
SDPBody* sdp = new SDPBody;
|
|
|
|
sdp->addLine("v","0");
|
|
|
|
sdp->addLine("s","Call");
|
|
|
|
sdp->addLine("t","0 0");
|
|
|
|
m->setBody(sdp);
|
|
|
|
plugin.ep()->engine()->addMessage(m);
|
|
|
|
m->deref();
|
2004-12-28 05:15:11 +00:00
|
|
|
return false;
|
2004-12-24 18:15:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SIPPlugin::SIPPlugin()
|
|
|
|
: m_handler(0), m_endpoint(0)
|
|
|
|
{
|
|
|
|
Output("Loaded module SIP Channel");
|
|
|
|
}
|
|
|
|
|
|
|
|
SIPPlugin::~SIPPlugin()
|
|
|
|
{
|
|
|
|
Output("Unloading module SIP Channel");
|
|
|
|
}
|
|
|
|
|
|
|
|
void SIPPlugin::initialize()
|
|
|
|
{
|
|
|
|
Output("Initializing module SIP Channel");
|
|
|
|
s_cfg = Engine::configFile("sipchan");
|
|
|
|
s_cfg.load();
|
|
|
|
if (!m_endpoint) {
|
|
|
|
m_endpoint = new YateSIPEndPoint();
|
|
|
|
if(!(m_endpoint->Init()))
|
|
|
|
{
|
|
|
|
delete m_endpoint;
|
|
|
|
m_endpoint = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m_endpoint->startup();
|
|
|
|
}
|
|
|
|
if (!m_handler) {
|
2004-12-28 05:15:11 +00:00
|
|
|
m_handler = new SIPHandler("call.execute");
|
2004-12-24 18:15:34 +00:00
|
|
|
Engine::install(m_handler);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* vi: set ts=8 sw=4 sts=4 noet: */
|