diff options
-rw-r--r-- | orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h | 4 | ||||
-rw-r--r-- | orkaudio/audiocaptureplugins/voip/RtpSession.cpp | 104 | ||||
-rw-r--r-- | orkaudio/audiocaptureplugins/voip/RtpSession.h | 5 | ||||
-rw-r--r-- | orkaudio/audiocaptureplugins/voip/VoIp.cpp | 16 |
4 files changed, 108 insertions, 21 deletions
diff --git a/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h b/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h index 0b45e6d..fcc8621 100644 --- a/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h +++ b/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h @@ -101,7 +101,7 @@ typedef struct { SkinnyHeaderStruct header; unsigned long conferenceId; - unsigned long passThruParty; + unsigned long passThruPartyId; struct in_addr remoteIpAddr; unsigned long remoteTcpPort; // and some more fields @@ -111,7 +111,7 @@ typedef struct { SkinnyHeaderStruct header; unsigned long conferenceId; - unsigned long passThruParty; + unsigned long passThruPartyId; } SkStopMediaTransmissionStruct; typedef struct diff --git a/orkaudio/audiocaptureplugins/voip/RtpSession.cpp b/orkaudio/audiocaptureplugins/voip/RtpSession.cpp index 2f618d4..9f12fc1 100644 --- a/orkaudio/audiocaptureplugins/voip/RtpSession.cpp +++ b/orkaudio/audiocaptureplugins/voip/RtpSession.cpp @@ -465,7 +465,7 @@ void RtpSessions::ReportSipBye(SipByeInfo bye) } } -void RtpSessions::ReportSkinnyCallInfo(SkCallInfoStruct* callInfo) +void RtpSessions::ReportSkinnyCallInfo(SkCallInfoStruct* callInfo, IpHeaderStruct* ipHeader) { CStdString callId = IntToString(callInfo->callId); std::map<CStdString, RtpSessionRef>::iterator pair; @@ -480,6 +480,7 @@ void RtpSessions::ReportSkinnyCallInfo(SkCallInfoStruct* callInfo) CStdString trackingId = alphaCounter.GetNext(); RtpSessionRef session(new RtpSession(trackingId)); session->m_callId = callId; + session->m_endPointIp = ipHeader->ip_dest; // CallInfo message always goes from CM to endpoint session->m_protocol = RtpSession::ProtSkinny; switch(callInfo->callType) { @@ -494,21 +495,81 @@ void RtpSessions::ReportSkinnyCallInfo(SkCallInfoStruct* callInfo) session->m_direction = CaptureEvent::DirOut; break; } + + if(m_log->isInfoEnabled()) + { + CStdString logMsg; + CStdString dir = CaptureEvent::DirectionToString(session->m_direction); + char szEndPointIp[16]; + ACE_OS::inet_ntop(AF_INET, (void*)&session->m_endPointIp, szEndPointIp, sizeof(szEndPointIp)); + + logMsg.Format("%s: Skinny CallInfo callId %s local:%s remote:%s dir:%s endpoint:%s", session->m_trackingId, + session->m_callId, session->m_localParty, session->m_remoteParty, dir, szEndPointIp); + LOG4CXX_INFO(m_log, logMsg); + } + m_byCallId.insert(std::make_pair(session->m_callId, session)); } -void RtpSessions::ReportSkinnyStartMediaTransmission(SkStartMediaTransmissionStruct* startMedia) +void RtpSessions::ReportSkinnyStartMediaTransmission(SkStartMediaTransmissionStruct* startMedia, IpHeaderStruct* ipHeader) { // Lookup by callId + RtpSessionRef session; CStdString callId = IntToString(startMedia->conferenceId); std::map<CStdString, RtpSessionRef>::iterator pair; - pair = m_byCallId.find(callId); - if (pair != m_byCallId.end()) + if(callId.Equals("0")) { - // Session found - RtpSessionRef session = pair->second; + // Ok this seems to be CallManager 3.3 or older, Conference ID field is not populated + // We need to find the CallInfo with the same endpoint IP address + for(pair = m_byCallId.begin(); pair != m_byCallId.end(); pair++) + { + RtpSessionRef tmpSession = pair->second; + + if(tmpSession->m_endPointIp.s_addr == ipHeader->ip_dest.s_addr) + { + if(tmpSession->m_ipAndPort.size() == 0) + { + session = tmpSession; + // The "Call ID" between StartMediaTransmission and StopMediaTransmission + // is represented by the PassThruPartyId field. + // So let's move the session within the callId map. + // 1. remove it from the map + m_byCallId.erase(session->m_callId); + // 2. add it back with PassThruPartyId as CallId + CStdString passThruPartyId = IntToString(startMedia->passThruPartyId); + CStdString oldCallId = session->m_callId; + session->m_callId = passThruPartyId; + m_byCallId.insert(std::make_pair(passThruPartyId, session)); + + if(m_log->isInfoEnabled()) + { + CStdString logMsg; + logMsg.Format("%s: Skinny StartMedia: callId %s becomes %s", session->m_trackingId, oldCallId, session->m_callId); + LOG4CXX_INFO(m_log, logMsg); + } + break; + } + else + { + // The session has already had a StartMediaTransmission message. + } + } + } + } + else + { + // CallManager 4 or newer + pair = m_byCallId.find(callId); + if (pair != m_byCallId.end()) + { + session = pair->second; + } + } + if (session.get() != NULL) + { + // Session found if(session->m_ipAndPort.size() == 0) { CStdString ipAndPort; @@ -519,10 +580,18 @@ void RtpSessions::ReportSkinnyStartMediaTransmission(SkStartMediaTransmissionStr pair = m_byIpAndPort.find(ipAndPort); if (pair != m_byIpAndPort.end()) { - // A session exists ont the same IP+port, stop old session + // A session exists on the same IP+port, stop old session RtpSessionRef session = pair->second; Stop(session); } + + if(m_log->isInfoEnabled()) + { + CStdString logMsg; + logMsg.Format("%s: Skinny StartMedia: callId %s is on %s", session->m_trackingId, session->m_callId, ipAndPort); + LOG4CXX_INFO(m_log, logMsg); + } + session->m_ipAndPort = ipAndPort; m_byIpAndPort.insert(std::make_pair(session->m_ipAndPort, session)); } @@ -539,8 +608,17 @@ void RtpSessions::ReportSkinnyStartMediaTransmission(SkStartMediaTransmissionStr void RtpSessions::ReportSkinnyStopMediaTransmission(SkStopMediaTransmissionStruct* stopMedia) { - CStdString callId = IntToString(stopMedia->conferenceId); - + CStdString callId; + if(stopMedia->conferenceId == 0) + { + // CallManager 3.3 or older, see explanation in ReportSkinnyStartMediaTransmission + callId = IntToString(stopMedia->passThruPartyId); + } + else + { + // CallManager 4 or later + callId = IntToString(stopMedia->conferenceId); + } std::map<CStdString, RtpSessionRef>::iterator pair; pair = m_byCallId.find(callId); @@ -548,6 +626,14 @@ void RtpSessions::ReportSkinnyStopMediaTransmission(SkStopMediaTransmissionStruc { // Session found: stop it RtpSessionRef session = pair->second; + + if(m_log->isInfoEnabled()) + { + CStdString logMsg; + logMsg.Format("%s: Skinny StopMedia", session->m_trackingId); + LOG4CXX_INFO(m_log, logMsg); + } + Stop(session); } } diff --git a/orkaudio/audiocaptureplugins/voip/RtpSession.h b/orkaudio/audiocaptureplugins/voip/RtpSession.h index 85540a0..5618b53 100644 --- a/orkaudio/audiocaptureplugins/voip/RtpSession.h +++ b/orkaudio/audiocaptureplugins/voip/RtpSession.h @@ -92,6 +92,7 @@ public: CStdString m_remoteParty; CaptureEvent::DirectionEnum m_direction; int m_numRtpPackets; + struct in_addr m_endPointIp; // only used for Skinny private: void ProcessMetadataSip(RtpPacketInfoRef&); @@ -124,8 +125,8 @@ public: void StopAll(); void ReportSipInvite(SipInviteInfoRef& invite); void ReportSipBye(SipByeInfo bye); - void ReportSkinnyCallInfo(SkCallInfoStruct*); - void ReportSkinnyStartMediaTransmission(SkStartMediaTransmissionStruct*); + void ReportSkinnyCallInfo(SkCallInfoStruct*, IpHeaderStruct* ipHeader); + void ReportSkinnyStartMediaTransmission(SkStartMediaTransmissionStruct*, IpHeaderStruct* ipHeader); void ReportSkinnyStopMediaTransmission(SkStopMediaTransmissionStruct*); void ReportRtpPacket(RtpPacketInfoRef& rtpPacket); void Hoover(time_t now); diff --git a/orkaudio/audiocaptureplugins/voip/VoIp.cpp b/orkaudio/audiocaptureplugins/voip/VoIp.cpp index bf72b69..b49651b 100644 --- a/orkaudio/audiocaptureplugins/voip/VoIp.cpp +++ b/orkaudio/audiocaptureplugins/voip/VoIp.cpp @@ -201,7 +201,7 @@ bool TryRtp(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, UdpH bool TrySipBye(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, UdpHeaderStruct* udpHeader, u_char* udpPayload) { bool result = false; - if (memcmp("BYE", (void*)udpPayload, 1) == 0) + if (memcmp("BYE", (void*)udpPayload, 3) == 0) { result = true; int sipLength = ntohs(udpHeader->len); @@ -221,7 +221,7 @@ bool TrySipBye(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, U bool TrySipInvite(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, UdpHeaderStruct* udpHeader, u_char* udpPayload) { bool result = false; - if (memcmp("INVITE", (void*)udpPayload, 1) == 0) + if (memcmp("INVITE", (void*)udpPayload, 6) == 0) { result = true; @@ -295,7 +295,7 @@ bool TrySipInvite(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader return result; } -void HandleSkinnyMessage(SkinnyHeaderStruct* skinnyHeader) +void HandleSkinnyMessage(SkinnyHeaderStruct* skinnyHeader, IpHeaderStruct* ipHeader) { bool useful = true; CStdString debug; @@ -311,15 +311,15 @@ void HandleSkinnyMessage(SkinnyHeaderStruct* skinnyHeader) { char szRemoteIp[16]; ACE_OS::inet_ntop(AF_INET, (void*)&startMedia->remoteIpAddr, szRemoteIp, sizeof(szRemoteIp)); - debug.Format(" CallId:%u %s,%u", startMedia->conferenceId, szRemoteIp, startMedia->remoteTcpPort); + debug.Format(" CallId:%u PassThru:%u %s,%u", startMedia->conferenceId, startMedia->passThruPartyId, szRemoteIp, startMedia->remoteTcpPort); } - RtpSessionsSingleton::instance()->ReportSkinnyStartMediaTransmission(startMedia); + RtpSessionsSingleton::instance()->ReportSkinnyStartMediaTransmission(startMedia, ipHeader); break; case SkStopMediaTransmission: stopMedia = (SkStopMediaTransmissionStruct*)skinnyHeader; if(s_skinnyPacketLog->isDebugEnabled()) { - debug.Format(" CallId:%u", stopMedia->conferenceId); + debug.Format(" CallId:%u PassThru:%u", stopMedia->conferenceId, stopMedia->passThruPartyId); } RtpSessionsSingleton::instance()->ReportSkinnyStopMediaTransmission(stopMedia); break; @@ -329,7 +329,7 @@ void HandleSkinnyMessage(SkinnyHeaderStruct* skinnyHeader) { debug.Format(" CallId:%u calling:%s called:%s", callInfo->callId, callInfo->callingParty, callInfo->calledParty); } - RtpSessionsSingleton::instance()->ReportSkinnyCallInfo(callInfo); + RtpSessionsSingleton::instance()->ReportSkinnyCallInfo(callInfo, ipHeader); break; default: useful = false; @@ -405,7 +405,7 @@ void HandlePacket(u_char *param, const struct pcap_pkthdr *header, const u_char } MutexSentinel mutexSentinel(s_mutex); // serialize access for competing pcap threads - HandleSkinnyMessage(skinnyHeader); + HandleSkinnyMessage(skinnyHeader, ipHeader); // Point to next skinny message within this TCP packet skinnyHeader = (SkinnyHeaderStruct*)((u_char*)skinnyHeader + SKINNY_HEADER_LENGTH + skinnyHeader->len); |