summaryrefslogtreecommitdiff
path: root/orkaudio/audiocaptureplugins/voip/SipSession.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'orkaudio/audiocaptureplugins/voip/SipSession.cpp')
-rw-r--r--orkaudio/audiocaptureplugins/voip/SipSession.cpp282
1 files changed, 282 insertions, 0 deletions
diff --git a/orkaudio/audiocaptureplugins/voip/SipSession.cpp b/orkaudio/audiocaptureplugins/voip/SipSession.cpp
new file mode 100644
index 0000000..e62a612
--- /dev/null
+++ b/orkaudio/audiocaptureplugins/voip/SipSession.cpp
@@ -0,0 +1,282 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#define _WINSOCKAPI_ // prevents the inclusion of winsock.h
+
+#include "Utils.h"
+#include "SipSession.h"
+#include "AudioCapturePlugin.h"
+#include "AudioCapturePluginCommon.h"
+#include <list>
+#include "VoIpConfig.h"
+#include "ace/OS_NS_arpa_inet.h"
+
+extern AudioChunkCallBackFunction g_audioChunkCallBack;
+extern CaptureEventCallBackFunction g_captureEventCallBack;
+
+extern VoIpConfigTopObjectRef g_VoIpConfigTopObjectRef;
+#define DLLCONFIG g_VoIpConfigTopObjectRef.get()->m_config
+
+
+SipSession::SipSession()
+{
+ m_lastUpdated = time(NULL);
+ m_log = Logger::getLogger("sipsession");
+ m_invitorIp.s_addr = 0;
+ m_inviteeIp.s_addr = 0;
+ m_direction = CaptureEvent::DirUnkn;
+}
+
+void SipSession::Stop()
+{
+ LOG4CXX_DEBUG(m_log, m_ipAndPort + " SIP Session stop");
+ CaptureEventRef stopEvent(new CaptureEvent);
+ stopEvent->m_type = CaptureEvent::EtStop;
+ stopEvent->m_timestamp = time(NULL);
+ g_captureEventCallBack(stopEvent, m_ipAndPort);
+}
+
+void SipSession::Start()
+{
+ LOG4CXX_DEBUG(m_log, m_ipAndPort + " SIP Session start");
+ m_rtpRingBuffer.SetCapturePort(m_ipAndPort);
+ CaptureEventRef startEvent(new CaptureEvent);
+ startEvent->m_type = CaptureEvent::EtStart;
+ startEvent->m_timestamp = time(NULL);
+ g_captureEventCallBack(startEvent, m_ipAndPort);
+}
+
+void SipSession::ProcessMetadataIncoming()
+{
+ m_remoteParty = m_invite->m_from;
+ m_localParty = m_invite->m_to;
+ m_direction = CaptureEvent::DirIn;
+}
+
+void SipSession::ProcessMetadataOutgoing()
+{
+ m_remoteParty = m_invite->m_to;
+ m_localParty = m_invite->m_from;
+ m_direction = CaptureEvent::DirOut;
+}
+
+void SipSession::ProcessMetadata(RtpPacketInfoRef& rtpPacket)
+{
+ bool done = false;
+
+ // work out invitee IP address
+ if(rtpPacket->m_sourceIp.s_addr == m_invitorIp.s_addr)
+ {
+ m_inviteeIp = rtpPacket->m_destIp;
+ }
+ else if(rtpPacket->m_destIp.s_addr == m_invitorIp.s_addr)
+ {
+ m_inviteeIp = rtpPacket->m_sourceIp;
+ }
+ else
+ {
+ LOG4CXX_DEBUG(m_log, m_ipAndPort + " alien RTP packet");
+ }
+
+ // work out capture port and direction
+ if(DLLCONFIG.IsMediaGateway(m_invitorIp))
+ {
+ if(DLLCONFIG.IsMediaGateway(m_inviteeIp))
+ {
+ // dismiss
+ }
+ if(DLLCONFIG.IsPartOfLan(m_inviteeIp))
+ {
+ ProcessMetadataIncoming();
+ }
+ }
+ else if (DLLCONFIG.IsPartOfLan(m_invitorIp))
+ {
+ ProcessMetadataOutgoing();
+ }
+ else
+ {
+ // SIP invitor IP address is an outside IP address
+ if(DLLCONFIG.IsMediaGateway(m_inviteeIp))
+ {
+ // dismiss
+ }
+ else if(DLLCONFIG.IsPartOfLan(m_inviteeIp))
+ {
+ ProcessMetadataIncoming();
+ }
+ else
+ {
+ // SIP invitee IP address is an outside IP address
+ ProcessMetadataOutgoing();
+ }
+ }
+ ReportMetadata();
+}
+
+void SipSession::ReportMetadata()
+{
+ // report Local party
+ CaptureEventRef event(new CaptureEvent());
+ event->m_type = CaptureEvent::EtLocalParty;
+ event->m_value = m_localParty;
+ g_captureEventCallBack(event, m_ipAndPort);
+
+ // Report remote party
+ event.reset(new CaptureEvent());
+ event->m_type = CaptureEvent::EtRemoteParty;
+ event->m_value = m_remoteParty;
+ g_captureEventCallBack(event, m_ipAndPort);
+
+ // report direction
+ event.reset(new CaptureEvent());
+ event->m_type = CaptureEvent::EtDirection;
+ event->m_value = CaptureEvent::DirectionToString(m_direction);
+ g_captureEventCallBack(event, m_ipAndPort);
+}
+
+
+void SipSession::AddRtpPacket(RtpPacketInfoRef& rtpPacket)
+{
+ // if first RTP packet, start session
+ if(m_lastRtpPacket.get() == NULL)
+ {
+ Start();
+ ProcessMetadata(rtpPacket);
+ }
+ m_lastRtpPacket = rtpPacket;
+
+ // send audio buffer
+ //AudioChunkRef chunkRef(new AudioChunk);
+ //chunkRef->SetBuffer(rtpPacket->m_payload, rtpPacket->m_payloadSize, AudioChunk::AlawAudio);
+ //g_audioChunkCallBack(chunkRef, m_ipAndPort);
+
+ m_rtpRingBuffer.AddRtpPacket(rtpPacket);
+
+ m_lastUpdated = time(NULL);
+}
+
+
+void SipSession::ReportSipInvite(SipInviteInfoRef& invite)
+{
+ m_invite = invite;
+ m_invitorIp = invite->m_fromIp;
+}
+
+//=====================================================================
+SipSessions::SipSessions()
+{
+ m_log = Logger::getLogger("sipsessions");
+}
+
+
+void SipSessions::ReportSipInvite(SipInviteInfoRef& invite)
+{
+ CStdString key = CStdString(ACE_OS::inet_ntoa(invite->m_fromIp)) + "," + invite->m_fromRtpPort;
+ std::map<CStdString, SipSessionRef>::iterator pair;
+
+ pair = m_byIpAndPort.find(key);
+
+ if (pair != m_byIpAndPort.end())
+ {
+ // A session exists ont the same IP+port, stop old session
+ SipSessionRef session = pair->second;
+ Stop(session);
+ }
+ // create new session and insert into both maps
+ SipSessionRef session(new SipSession());
+ session->m_ipAndPort = key;
+ session->ReportSipInvite(invite);
+ m_byCallId.insert(std::make_pair(invite->m_callId, session));
+ m_byIpAndPort.insert(std::make_pair(key, session));
+}
+
+void SipSessions::ReportSipBye(SipByeInfo bye)
+{
+ std::map<CStdString, SipSessionRef>::iterator pair;
+ pair = m_byCallId.find(bye.m_callId);
+
+ if (pair != m_byCallId.end())
+ {
+ // Session found: stop it
+ SipSessionRef session = pair->second;
+ Stop(session);
+ }
+}
+
+void SipSessions::Stop(SipSessionRef& session)
+{
+ session->Stop();
+ m_byIpAndPort.erase(session->m_ipAndPort);
+ m_byCallId.erase(session->m_invite->m_callId);
+}
+
+
+void SipSessions::ReportRtpPacket(RtpPacketInfoRef& rtpPacket)
+{
+ // Does a session exist with this source Ip+Port
+ SipSessionRef session;
+ CStdString port = IntToString(rtpPacket->m_sourcePort);
+ CStdString ipAndPort = CStdString(ACE_OS::inet_ntoa(rtpPacket->m_sourceIp)) + "," + port;
+ std::map<CStdString, SipSessionRef>::iterator pair;
+
+ pair = m_byIpAndPort.find(ipAndPort);
+ if (pair != m_byIpAndPort.end())
+ {
+ session = pair->second;
+ }
+ else
+ {
+ // Does a session exist with this destination Ip+Port
+ port = IntToString(rtpPacket->m_destPort);
+ ipAndPort = CStdString(ACE_OS::inet_ntoa(rtpPacket->m_destIp)) + "," + port;
+ pair = m_byIpAndPort.find(ipAndPort);
+ if (pair != m_byIpAndPort.end())
+ {
+ session = pair->second;
+ }
+ }
+ if (!session.get() == NULL)
+ {
+ // Found a session give it the RTP packet info
+ session->AddRtpPacket(rtpPacket);
+ }
+}
+
+void SipSessions::Hoover(time_t now)
+{
+ CStdString numSessions = IntToString(m_byIpAndPort.size());
+ LOG4CXX_DEBUG(m_log, "Hoover - check " + numSessions + " sessions time:" + IntToString(now));
+
+ // Go round the sessions and find inactive ones
+ std::map<CStdString, SipSessionRef>::iterator pair;
+ std::list<SipSessionRef> toDismiss;
+
+ for(pair = m_byIpAndPort.begin(); pair != m_byIpAndPort.end(); pair++)
+ {
+ SipSessionRef session = pair->second;
+ if((now - session->m_lastUpdated) > 10)
+ {
+ toDismiss.push_back(session);
+ }
+ }
+
+ // discard inactive sessions
+ for (std::list<SipSessionRef>::iterator it = toDismiss.begin(); it != toDismiss.end() ; it++)
+ {
+ SipSessionRef session = *it;
+ LOG4CXX_DEBUG(m_log, session->m_ipAndPort + " Expired");
+ Stop(session);
+ }
+}
+