205 lines
4.6 KiB
C
205 lines
4.6 KiB
C
|
/*
|
||
|
* OpenBTS provides an open source alternative to legacy telco protocols and
|
||
|
* traditionally complex, proprietary hardware systems.
|
||
|
*
|
||
|
* Copyright 2008 Free Software Foundation, Inc.
|
||
|
* Copyright 2014 Range Networks, Inc.
|
||
|
*
|
||
|
* This software is distributed under the terms of the GNU Affero General
|
||
|
* Public License version 3. See the COPYING and NOTICE files in the main
|
||
|
* directory for licensing information.
|
||
|
*
|
||
|
* This use of this software may be subject to additional restrictions.
|
||
|
* See the LEGAL file in the main directory for details.
|
||
|
*/
|
||
|
|
||
|
#ifndef SIPINTERFACE_H
|
||
|
#define SIPINTERFACE_H
|
||
|
|
||
|
#include <Globals.h>
|
||
|
#include <Interthread.h>
|
||
|
#include <Sockets.h>
|
||
|
#include <osip2/osip.h>
|
||
|
|
||
|
#include <string>
|
||
|
|
||
|
|
||
|
namespace GSM {
|
||
|
|
||
|
class L3MobileIdentity;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
namespace SIP {
|
||
|
|
||
|
|
||
|
typedef InterthreadQueue<osip_message_t> _OSIPMessageFIFO;
|
||
|
|
||
|
class OSIPMessageFIFO : public _OSIPMessageFIFO {
|
||
|
|
||
|
private:
|
||
|
|
||
|
struct sockaddr_in mReturnAddress;
|
||
|
|
||
|
virtual void freeElement(osip_message_t* element) const { osip_message_free(element); };
|
||
|
|
||
|
public:
|
||
|
|
||
|
OSIPMessageFIFO(const struct sockaddr_in* wReturnAddress)
|
||
|
:_OSIPMessageFIFO()
|
||
|
{
|
||
|
memcpy(&mReturnAddress,wReturnAddress,sizeof(mReturnAddress));
|
||
|
}
|
||
|
|
||
|
virtual ~OSIPMessageFIFO()
|
||
|
{
|
||
|
// We must call clear() here, because if it is called from InterthreadQueue
|
||
|
// destructor, then clear() will call InterthreadQueue's freeElement() which
|
||
|
// is not what we want. This destructor behaviour is intntional, because
|
||
|
// inherited object's data is already destroyed at the time parent's destructor
|
||
|
// is called.
|
||
|
clear();
|
||
|
}
|
||
|
|
||
|
const struct sockaddr_in* returnAddress() const { return &mReturnAddress; }
|
||
|
|
||
|
size_t addressSize() const { return sizeof(mReturnAddress); }
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
class OSIPMessageFIFOMap : public InterthreadMap<std::string,OSIPMessageFIFO> {};
|
||
|
|
||
|
|
||
|
std::ostream& operator<<(std::ostream& os, const OSIPMessageFIFO& m);
|
||
|
|
||
|
|
||
|
/**
|
||
|
A Map the keeps a SIP message FIFO for each active SIP transaction.
|
||
|
Keyed by SIP call ID string.
|
||
|
Overall map is thread-safe. Each FIFO is also thread-safe.
|
||
|
*/
|
||
|
class SIPMessageMap
|
||
|
{
|
||
|
|
||
|
private:
|
||
|
|
||
|
OSIPMessageFIFOMap mMap;
|
||
|
|
||
|
public:
|
||
|
|
||
|
/** Write sip message to the map+fifo. used by sip interface. */
|
||
|
void write(const std::string& call_id, osip_message_t * sip_msg );
|
||
|
|
||
|
/** Read sip message out of map+fifo. used by sip engine. */
|
||
|
osip_message_t * read(const std::string& call_id, unsigned readTimeout=3600000);
|
||
|
|
||
|
/** Create a new entry in the map. */
|
||
|
bool add(const std::string& call_id, const struct sockaddr_in* returnAddress);
|
||
|
|
||
|
/**
|
||
|
Remove a fifo from map (called at the end of a sip interaction).
|
||
|
@param call_id The call_id key string.
|
||
|
@return True if the call_id was there in the first place.
|
||
|
*/
|
||
|
bool remove(const std::string& call_id);
|
||
|
|
||
|
/** Direct access to the map. */
|
||
|
// FIXME -- This should probably be replaced with more specific methods.
|
||
|
OSIPMessageFIFOMap& map() {return mMap;}
|
||
|
|
||
|
};
|
||
|
|
||
|
std::ostream& operator<<(std::ostream& os, const SIPMessageMap& m);
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
class SIPInterface
|
||
|
{
|
||
|
|
||
|
private:
|
||
|
|
||
|
char mReadBuffer[2048]; ///< buffer for UDP reads
|
||
|
|
||
|
UDPSocket mSIPSocket;
|
||
|
|
||
|
Mutex mSocketLock;
|
||
|
Thread mDriveThread;
|
||
|
SIPMessageMap mSIPMap;
|
||
|
|
||
|
public:
|
||
|
// 2 ways to starte sip interface.
|
||
|
// Ex 1.
|
||
|
// SIPInterface si;
|
||
|
// si.localAdder(port0, ip_str, port1);
|
||
|
// si.open();
|
||
|
// or Ex 2.
|
||
|
// SIPInterface si(port0, ip_str, port1);
|
||
|
// Then after all that. si.start();
|
||
|
|
||
|
|
||
|
/**
|
||
|
Create the SIP interface to watch for incoming SIP messages.
|
||
|
*/
|
||
|
SIPInterface()
|
||
|
:mSIPSocket(gConfig.getNum("SIP.Local.Port"))
|
||
|
{ }
|
||
|
|
||
|
|
||
|
/** Start the SIP drive loop. */
|
||
|
void start();
|
||
|
|
||
|
/** Receive, parse and dispatch a single SIP message. */
|
||
|
void drive();
|
||
|
|
||
|
/**
|
||
|
Look for incoming INVITE messages to start MTC.
|
||
|
@param msg The SIP message to check.
|
||
|
@return true if the message is a new INVITE
|
||
|
*/
|
||
|
bool checkInvite( osip_message_t *);
|
||
|
|
||
|
|
||
|
/**
|
||
|
Schedule SMS for delivery.
|
||
|
*/
|
||
|
//void deliverSMS(const GSM::L3MobileIdentity& mobile_id, const char* returnAddress, const char* text);
|
||
|
|
||
|
// To write a msg to outside, make the osip_message_t
|
||
|
// then call si.write(msg);
|
||
|
// to read, you need to have the call_id
|
||
|
// then call si.read(call_id)
|
||
|
|
||
|
void write(const struct sockaddr_in*, osip_message_t*);
|
||
|
|
||
|
osip_message_t* read(const std::string& call_id , unsigned readTimeout=3600000)
|
||
|
{ return mSIPMap.read(call_id, readTimeout); }
|
||
|
|
||
|
/** Create a new message FIFO in the SIP interface. */
|
||
|
bool addCall(const std::string& call_id);
|
||
|
|
||
|
bool removeCall(const std::string& call_id);
|
||
|
|
||
|
int fifoSize(const std::string& call_id );
|
||
|
|
||
|
};
|
||
|
|
||
|
void driveLoop(SIPInterface*);
|
||
|
|
||
|
|
||
|
}; // namespace SIP.
|
||
|
|
||
|
|
||
|
/*@addtogroup Globals */
|
||
|
//@{
|
||
|
/** A single global SIPInterface in the global namespace. */
|
||
|
extern SIP::SIPInterface gSIPInterface;
|
||
|
//@}
|
||
|
|
||
|
|
||
|
#endif // SIPINTERFACE_H
|
||
|
// vim: ts=4 sw=4
|