mirror of
https://github.com/fairwaves/openbts-2.8.git
synced 2025-10-23 07:42:01 +00:00
r4232: Major change in hos entries are removed from a TransactionTable. >From now on, the only place were entries are actually removed is in TransactionTable::innerRemove. Anywhere else, the remove methods just set a flag to tag the entry for later removal be innerRemove. This allows us to survive situations where we try to touch transactions that have been removed already. We still log at the ERR level, but no more segfaults. Updated all of the TransactionTable "find" methods to not return pointers to dead or removed tranactions. Updated find-by-channel search to return the transaction entry with the highest transaction number, which fixes a bug that sometimes picked up the wrong transaction records during EA TCH assignment. r4253: New exception class for when someone tries to use a "removed" transaction. r4254: Updated copyright notice. r4265: Unlock TransactionEntry::mLock while blocked on SIP message FIFOs in SIPEngine. This does wonders to reduce lock contention and make everything more snappy. Use Mutex::tryLock in TransactionEntry::dead and if lock is held, assume that it is not dead. This also does a lot to reduce lock contention. r4294: Change Um congestion response back to SIP 503. r4295: When deleting an entry that has failed to respond to paging, send a SIP 480 response so the switch knows that transaction is dead. r4412: Fixed bug that was causing SIPInterface to crash when the IMSI cannot be extracted from the To: header. git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@4497 19bc5d8c-e614-43d4-8b26-e1612bc8e597
222 lines
5.0 KiB
C++
222 lines
5.0 KiB
C++
/*
|
|
* Copyright 2008 Free Software Foundation, Inc.
|
|
*
|
|
* This software is distributed under multiple licenses;
|
|
* see the COPYING file in the main directory for licensing
|
|
* information for this specific distribuion.
|
|
*
|
|
* This use of this software may be subject to additional restrictions.
|
|
* See the LEGAL file in the main directory for details.
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#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 timeout, Mutex *lock);
|
|
|
|
/** Read sip message out of map+fifo. used by sip engine. */
|
|
osip_message_t * read(const std::string& call_id, Mutex *lock);;
|
|
|
|
/** 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 *);
|
|
|
|
/**
|
|
Send an error response before a transaction is even created.
|
|
*/
|
|
void sendEarlyError(osip_message_t * cause,
|
|
const char *proxy,
|
|
int code, const char * reason);
|
|
|
|
|
|
/**
|
|
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, Mutex *lock=NULL)
|
|
{ return mSIPMap.read(call_id, readTimeout, lock); }
|
|
|
|
osip_message_t* read(const std::string& call_id, Mutex *lock=NULL)
|
|
{ return mSIPMap.read(call_id, lock); }
|
|
|
|
|
|
/** 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
|