summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Begumisa <ben_g@users.sourceforge.net>2007-08-24 21:37:49 +0000
committerGerald Begumisa <ben_g@users.sourceforge.net>2007-08-24 21:37:49 +0000
commit576816f821b60bc8580b310248bac409ed30915e (patch)
tree7fa422abd5e89d26fd8c0488d53a436ce4a09b75
parent9d30c0398e4447bf0b8b539caf738498fa45fb9f (diff)
Added support for SIP 200 OK message with ability to adjust the session RTP IP address and port if NAT is detected
git-svn-id: https://oreka.svn.sourceforge.net/svnroot/oreka/trunk@474 09dcff7a-b715-0410-9601-b79a96267cd0
-rw-r--r--orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h2
-rw-r--r--orkaudio/audiocaptureplugins/voip/RtpSession.cpp42
-rw-r--r--orkaudio/audiocaptureplugins/voip/RtpSession.h16
-rw-r--r--orkaudio/audiocaptureplugins/voip/VoIp.cpp60
4 files changed, 116 insertions, 4 deletions
diff --git a/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h b/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h
index f054c43..ad6906d 100644
--- a/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h
+++ b/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h
@@ -337,8 +337,10 @@ struct Iax2MetaTrunkEntryTs {
#define SIP_METHOD_INVITE_SIZE 6
#define SIP_METHOD_BYE_SIZE 3
+#define SIP_RESPONSE_200_OK_SIZE 11
#define SIP_METHOD_INVITE "INVITE"
#define SIP_METHOD_BYE "BYE"
+#define SIP_RESPONSE_200_OK "SIP/2.0 200"
#endif
diff --git a/orkaudio/audiocaptureplugins/voip/RtpSession.cpp b/orkaudio/audiocaptureplugins/voip/RtpSession.cpp
index 91a483e..e29ad76 100644
--- a/orkaudio/audiocaptureplugins/voip/RtpSession.cpp
+++ b/orkaudio/audiocaptureplugins/voip/RtpSession.cpp
@@ -697,6 +697,7 @@ void RtpSession::ReportSipInvite(SipInviteInfoRef& invite)
invite->ToString(inviteString);
CStdString logMsg;
logMsg.Format("[%s] associating INVITE:%s", m_trackingId, inviteString);
+ m_fromRtpIp = invite->m_fromRtpIp;
LOG4CXX_INFO(m_log, logMsg);
}
m_invites.push_front(invite);
@@ -916,6 +917,41 @@ void RtpSessions::ReportSipErrorPacket(SipFailureMessageInfoRef& info)
return;
}
+void RtpSessions::ReportSip200Ok(Sip200OkInfoRef info)
+{
+ std::map<CStdString, RtpSessionRef>::iterator pair;
+
+ pair = m_byCallId.find(info->m_callId);
+ if (pair != m_byCallId.end())
+ {
+ RtpSessionRef session = pair->second;
+
+ if(info->m_hasSdp && DLLCONFIG.IsPartOfLan(session->m_fromRtpIp) && !DLLCONFIG.IsPartOfLan(info->m_fromRtpIp) && !session->m_numRtpPackets)
+ {
+ char szFromRtpIp[16];
+
+ ACE_OS::inet_ntop(AF_INET, (void*)&info->m_fromRtpIp, szFromRtpIp, sizeof(szFromRtpIp));
+ m_byIpAndPort.erase(session->m_ipAndPort);
+ session->m_ipAndPort = CStdString(szFromRtpIp) + "," + info->m_fromRtpPort;
+
+ pair = m_byIpAndPort.find(session->m_ipAndPort);
+ if (pair != m_byIpAndPort.end())
+ {
+ RtpSessionRef session2 = pair->second;
+
+ if(session2->m_protocol == RtpSession::ProtRawRtp)
+ {
+ Stop(session2);
+ }
+ }
+
+ m_byIpAndPort.insert(std::make_pair(session->m_ipAndPort, session));
+
+ LOG4CXX_INFO(m_log, "[" + session->m_trackingId + "] updated RTP address: " + session->m_ipAndPort);
+ }
+ }
+}
+
void RtpSessions::ReportSipBye(SipByeInfo bye)
{
std::map<CStdString, RtpSessionRef>::iterator pair;
@@ -1751,3 +1787,9 @@ void SipFailureMessageInfo::ToString(CStdString& string)
string.Format("sender:%s rcvr:%s smac:%s rmac:%s callid:%s errorcode:%s errorstr:\"%s\"", senderIp, receiverIp, senderMac, receiverMac, m_callId, m_errorCode, m_errorString);
}
+Sip200OkInfo::Sip200OkInfo()
+{
+ m_fromRtpIp.s_addr = 0;
+ m_hasSdp = false;
+}
+
diff --git a/orkaudio/audiocaptureplugins/voip/RtpSession.h b/orkaudio/audiocaptureplugins/voip/RtpSession.h
index 5475cb9..ec9d262 100644
--- a/orkaudio/audiocaptureplugins/voip/RtpSession.h
+++ b/orkaudio/audiocaptureplugins/voip/RtpSession.h
@@ -70,6 +70,20 @@ public:
CStdString m_callId;
};
+
+class Sip200OkInfo
+{
+public:
+ Sip200OkInfo();
+ CStdString m_callId;
+ bool m_hasSdp;
+ struct in_addr m_fromRtpIp;
+ CStdString m_fromRtpPort;
+};
+
+typedef boost::shared_ptr<Sip200OkInfo> Sip200OkInfoRef;
+
+
//=============================================================
class EndpointInfo
@@ -104,6 +118,7 @@ public:
CStdString m_trackingId;
CStdString m_ipAndPort; // IP address and TCP port of one side of the session, serves as a key for session storage and retrieval. Not necessarily the same as the capturePort (capturePort is usually the client (phone) IP+port)
+ struct in_addr m_fromRtpIp;
CStdString m_callId;
SipInviteInfoRef m_invite;
ACE_Time_Value m_creationDate; // When the session is first created
@@ -180,6 +195,7 @@ public:
void ReportSkinnySoftKeyResume(SkSoftKeyEventMessageStruct* skEvent, IpHeaderStruct* ipHeader);
void ReportRtpPacket(RtpPacketInfoRef& rtpPacket);
void ReportSipErrorPacket(SipFailureMessageInfoRef& sipError);
+ void ReportSip200Ok(Sip200OkInfoRef info);
void Hoover(time_t now);
EndpointInfoRef GetEndpointInfo(struct in_addr endpointIp);
void StartCapture(CStdString& party);
diff --git a/orkaudio/audiocaptureplugins/voip/VoIp.cpp b/orkaudio/audiocaptureplugins/voip/VoIp.cpp
index 2db26d7..60bcf0d 100644
--- a/orkaudio/audiocaptureplugins/voip/VoIp.cpp
+++ b/orkaudio/audiocaptureplugins/voip/VoIp.cpp
@@ -1360,6 +1360,55 @@ bool TrySipTcp(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, T
return result;
}
+bool TrySip200Ok(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, UdpHeaderStruct* udpHeader, u_char* udpPayload, u_char* packetEnd)
+{
+ bool result = false;
+
+ int sipLength = ntohs(udpHeader->len) - sizeof(UdpHeaderStruct);
+ char* sipEnd = (char*)udpPayload + sipLength;
+ if(sipLength < SIP_RESPONSE_200_OK_SIZE || sipEnd > (char*)packetEnd)
+ {
+ ; // packet too short
+ }
+ else if (memcmp(SIP_RESPONSE_200_OK, (void*)udpPayload, SIP_RESPONSE_200_OK_SIZE) == 0)
+ {
+ result = true;
+
+ Sip200OkInfoRef info(new Sip200OkInfo());
+
+ char* callIdField = memFindAfter("\r\ni:", (char*)udpPayload, sipEnd);
+ char* audioField = NULL;
+ char* connectionAddressField = NULL;
+
+ if(callIdField)
+ {
+ GrabTokenSkipLeadingWhitespaces(callIdField, sipEnd, info->m_callId);
+ audioField = memFindAfter("m=audio ", callIdField, sipEnd);
+ connectionAddressField = memFindAfter("c=IN IP4 ", callIdField, sipEnd);
+ }
+ if(audioField && connectionAddressField)
+ {
+ info->m_hasSdp = true;
+
+ GrabToken(audioField, sipEnd, info->m_fromRtpPort);
+
+ CStdString connectionAddress;
+ GrabToken(connectionAddressField, sipEnd, connectionAddress);
+ struct in_addr fromIp;
+ if(connectionAddress.size())
+ {
+ if(ACE_OS::inet_aton((PCSTR)connectionAddress, &fromIp))
+ {
+ info->m_fromRtpIp = fromIp;
+ }
+ }
+ }
+
+ RtpSessionsSingleton::instance()->ReportSip200Ok(info);
+ }
+ return result;
+}
+
bool TrySipInvite(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, UdpHeaderStruct* udpHeader, u_char* udpPayload, u_char* packetEnd)
{
bool result = false;
@@ -1367,12 +1416,11 @@ bool TrySipInvite(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader
int sipLength = ntohs(udpHeader->len) - sizeof(UdpHeaderStruct);
char* sipEnd = (char*)udpPayload + sipLength;
- if(sipLength < sizeof(SIP_METHOD_INVITE) || sipEnd > (char*)packetEnd)
+ if(sipLength < SIP_METHOD_INVITE_SIZE || sipEnd > (char*)packetEnd)
{
- return false;
+ ; // packet too short
}
-
- if (memcmp(SIP_METHOD_INVITE, (void*)udpPayload, SIP_METHOD_INVITE_SIZE) == 0)
+ else if (memcmp(SIP_METHOD_INVITE, (void*)udpPayload, SIP_METHOD_INVITE_SIZE) == 0)
{
result = true;
@@ -1828,6 +1876,10 @@ void HandlePacket(u_char *param, const struct pcap_pkthdr *header, const u_char
}
if(!detectedUsefulPacket) {
+ detectedUsefulPacket= TrySip200Ok(ethernetHeader, ipHeader, udpHeader, udpPayload, ipPacketEnd);
+ }
+
+ if(!detectedUsefulPacket) {
detectedUsefulPacket = TrySipBye(ethernetHeader, ipHeader, udpHeader, udpPayload, ipPacketEnd);
}