From ad54c92028787c13d0930fa6124b9db7a37134c0 Mon Sep 17 00:00:00 2001 From: Henri Herscher Date: Mon, 31 Oct 2005 19:42:26 +0000 Subject: Groundwork for adding skinny support git-svn-id: https://oreka.svn.sourceforge.net/svnroot/oreka/trunk@24 09dcff7a-b715-0410-9601-b79a96267cd0 --- .../audiocaptureplugins/voip/PacketHeaderDefs.cpp | 39 ++++++++++ .../audiocaptureplugins/voip/PacketHeaderDefs.h | 82 +++++++++++++++++++++- orkaudio/audiocaptureplugins/voip/RtpSession.cpp | 20 +++--- orkaudio/audiocaptureplugins/voip/RtpSession.h | 26 +++++++ orkaudio/audiocaptureplugins/voip/VoIp.cpp | 79 +++++++++++++++++++++ 5 files changed, 236 insertions(+), 10 deletions(-) create mode 100644 orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.cpp diff --git a/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.cpp b/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.cpp new file mode 100644 index 0000000..ecf4d8e --- /dev/null +++ b/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.cpp @@ -0,0 +1,39 @@ +#include "PacketHeaderDefs.h" + +int SkinnyMessageToEnum(CStdString& msg) +{ + int msgEnum = SkUnkn; + if(msg.CompareNoCase(SKINNY_MSG_START_MEDIA_TRANSMISSION) == 0) + { + msgEnum = SkStartMediaTransmission; + } + else if (msg.CompareNoCase(SKINNY_MSG_STOP_MEDIA_TRANSMISSION) == 0) + { + msgEnum = SkStopMediaTransmission; + } + else if (msg.CompareNoCase(SKINNY_MSG_CALL_INFO_MESSAGE) == 0) + { + msgEnum = SkCallInfoMessage; + } + return msgEnum; +} + +CStdString SkinnyMessageToString(int msgEnum) +{ + CStdString msgString; + switch (msgEnum) + { + case SkStartMediaTransmission: + msgString = SKINNY_MSG_START_MEDIA_TRANSMISSION; + break; + case SkStopMediaTransmission: + msgString = SKINNY_MSG_STOP_MEDIA_TRANSMISSION; + break; + case SkCallInfoMessage: + msgString = SKINNY_MSG_CALL_INFO_MESSAGE; + break; + default: + msgString = SKINNY_MSG_UNKN; + } + return msgString; +} diff --git a/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h b/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h index 1293c5c..ae488bb 100644 --- a/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h +++ b/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h @@ -15,6 +15,9 @@ #ifndef __PACKETHEADERDEFS_H__ #define __PACKETHEADERDEFS_H__ +#include "ace/OS_NS_arpa_inet.h" +#include "StdString.h" + // Structure of Ethernet header typedef struct @@ -25,7 +28,7 @@ typedef struct } EthernetHeaderStruct; -// Structure of an internet header, naked of options, only valid for little endian +// Structure of an internet header, naked of options, only valid for LITTLE ENDIAN typedef struct { unsigned char ip_hl:4; // Header length @@ -41,6 +44,25 @@ typedef struct struct in_addr ip_dest; // Destination address } IpHeaderStruct; + +// Strucutre of a TCP header, only valid for LITTLE ENDIAN +typedef struct +{ + unsigned short source; // source port + unsigned short dest; // destination port + unsigned long seq; // sequence number + unsigned long ack; // acknowledgement id + unsigned int x2:4; // unused + unsigned int off:4; // data offset + unsigned char flags; // flags field + unsigned short win; // window size + unsigned short sum; // tcp checksum + unsigned short urp; // urgent pointer + +} TcpHeaderStruct; +#define TCP_HEADER_LENGTH 20 + + // Structure of UDP header typedef struct { @@ -54,7 +76,8 @@ typedef struct #define RTP_PT_PCMA 8 // Structure of RTP header, only valid for little endian -typedef struct { +typedef struct +{ unsigned short cc:4; // CSRC count unsigned short x:1; // header extension flag unsigned short p:1; // padding flag @@ -67,5 +90,60 @@ typedef struct { //unsigned int csrc[1]; // optional CSRC list } RtpHeaderStruct; +typedef struct +{ + unsigned long len; + unsigned long reserved; + unsigned long messageType; +} SkinnyHeaderStruct; + +typedef struct +{ + SkinnyHeaderStruct header; + unsigned long conferenceId; + unsigned long passThruParty; + struct in_addr remoteIpAddr; + unsigned long remoteTcpPort; + // and some more fields +} SkStartMediaTransmissionStruct; + +typedef struct +{ + SkinnyHeaderStruct header; + unsigned long conferenceId; + unsigned long passThruParty; +} SkStopMediaTransmissionStruct; + +typedef struct +{ + SkinnyHeaderStruct header; + char callingPartyName[40]; + char callingParty[24]; + char calledPartyName[40]; + char calledParty[24]; + unsigned long lineInstance; + unsigned long callId; + unsigned long callType; +} SkCallInfoStruct; + +#define SKINNY_CTRL_PORT 2000 +#define SKINNY_MIN_MESSAGE_SIZE 12 +#define SKINNY_HEADER_LENGTH 8 + +#define SKINNY_MSG_UNKN "Unkn" +#define SKINNY_MSG_START_MEDIA_TRANSMISSION "StartMediaTransmission" +#define SKINNY_MSG_STOP_MEDIA_TRANSMISSION "StopMediaTransmission" +#define SKINNY_MSG_CALL_INFO_MESSAGE "CallInfoMessage" + +typedef enum +{ + SkStartMediaTransmission = 0x008A, + SkStopMediaTransmission = 0x008B, + SkCallInfoMessage = 0x008F, + SkUnkn = 0x0 +} SkinnyMessageEnum; +int SkinnyMessageToEnum(CStdString& msg); +CStdString SkinnyMessageToString(int msgEnum); + #endif diff --git a/orkaudio/audiocaptureplugins/voip/RtpSession.cpp b/orkaudio/audiocaptureplugins/voip/RtpSession.cpp index 1239055..c8b49dd 100644 --- a/orkaudio/audiocaptureplugins/voip/RtpSession.cpp +++ b/orkaudio/audiocaptureplugins/voip/RtpSession.cpp @@ -289,10 +289,10 @@ RtpSessions::RtpSessions() void RtpSessions::ReportSipInvite(SipInviteInfoRef& invite) { - CStdString key = CStdString(ACE_OS::inet_ntoa(invite->m_fromIp)) + "," + invite->m_fromRtpPort; + CStdString ipAndPort = CStdString(ACE_OS::inet_ntoa(invite->m_fromIp)) + "," + invite->m_fromRtpPort; std::map::iterator pair; - pair = m_byIpAndPort.find(key); + pair = m_byIpAndPort.find(ipAndPort); if (pair != m_byIpAndPort.end()) { @@ -302,11 +302,12 @@ void RtpSessions::ReportSipInvite(SipInviteInfoRef& invite) } // create new session and insert into both maps RtpSessionRef session(new RtpSession()); - session->m_ipAndPort = key; + session->m_ipAndPort = ipAndPort; + session->m_callId = invite->m_callId; session->m_protocol = RtpSession::ProtSip; session->ReportSipInvite(invite); - m_byCallId.insert(std::make_pair(invite->m_callId, session)); - m_byIpAndPort.insert(std::make_pair(key, session)); + m_byIpAndPort.insert(std::make_pair(session->m_ipAndPort, session)); + m_byCallId.insert(std::make_pair(session->m_callId, session)); } void RtpSessions::ReportSipBye(SipByeInfo bye) @@ -325,10 +326,13 @@ void RtpSessions::ReportSipBye(SipByeInfo bye) void RtpSessions::Stop(RtpSessionRef& session) { session->Stop(); - m_byIpAndPort.erase(session->m_ipAndPort); - if(session->m_invite.get() != NULL) + if(session->m_ipAndPort.size() > 0) + { + m_byIpAndPort.erase(session->m_ipAndPort); + } + if(session->m_callId.size() > 0) { - m_byCallId.erase(session->m_invite->m_callId); + m_byCallId.erase(session->m_callId); } } diff --git a/orkaudio/audiocaptureplugins/voip/RtpSession.h b/orkaudio/audiocaptureplugins/voip/RtpSession.h index f804721..3fd07c1 100644 --- a/orkaudio/audiocaptureplugins/voip/RtpSession.h +++ b/orkaudio/audiocaptureplugins/voip/RtpSession.h @@ -37,6 +37,31 @@ public: }; +class SccpCallInfoMessageInfo +{ + CStdString m_callingParty; + CStdString m_calledParty; + CStdString m_callId; +}; +typedef boost::shared_ptr SccpCallInfoMessageInfoRef; + + +class SccpStartMediaTransmissionInfo +{ + struct in_addr m_remoteIp; + int m_remoteTcpPort; + CStdString m_callId; +}; +typedef boost::shared_ptr SccpStartMediaTransmissionInfoRef; + + +class SccpStopMediaTransmissionInfo +{ + CStdString m_callId; +}; +typedef boost::shared_ptr SccpStopMediaTransmissionInfoRef; + + class RtpSession { public: @@ -54,6 +79,7 @@ public: void ReportSipInvite(SipInviteInfoRef& invite); CStdString m_ipAndPort; + CStdString m_callId; SipInviteInfoRef m_invite; time_t m_lastUpdated; ProtocolEnum m_protocol; diff --git a/orkaudio/audiocaptureplugins/voip/VoIp.cpp b/orkaudio/audiocaptureplugins/voip/VoIp.cpp index 8a860df..b2f83bf 100644 --- a/orkaudio/audiocaptureplugins/voip/VoIp.cpp +++ b/orkaudio/audiocaptureplugins/voip/VoIp.cpp @@ -36,11 +36,23 @@ extern LogManager* g_logManager; static LoggerPtr s_log; static LoggerPtr s_sipExtractionLog; +static LoggerPtr s_skinnyLog; time_t lastHooveringTime; VoIpConfigTopObjectRef g_VoIpConfigTopObjectRef; #define DLLCONFIG g_VoIpConfigTopObjectRef.get()->m_config +// Convert a piece of memnory to hex string +void memToHex(unsigned char* input, size_t len, CStdString&output) +{ + char byteAsHex[10]; + for(int i=0; imessageType) + { + case SkStartMediaTransmission: + start = (SkStartMediaTransmissionStruct*)skinnyHeader; + if(s_skinnyLog->isDebugEnabled()) + { + debug.Format(" CallId:%u %s,%u", start->conferenceId, ACE_OS::inet_ntoa(start->remoteIpAddr), start->remoteTcpPort); + } + break; + case SkStopMediaTransmission: + stop = (SkStopMediaTransmissionStruct*)skinnyHeader; + if(s_skinnyLog->isDebugEnabled()) + { + debug.Format(" CallId:%u", stop->conferenceId); + } + break; + case SkCallInfoMessage: + callInfo = (SkCallInfoStruct*)skinnyHeader; + if(s_skinnyLog->isDebugEnabled()) + { + debug.Format(" CallId:%u calling:%s called:%s", callInfo->callId, callInfo->callingParty, callInfo->calledParty); + } + break; + default: + useful = false; + } + if(useful && s_skinnyLog->isDebugEnabled()) + { + CStdString msg = SkinnyMessageToString(skinnyHeader->messageType); + debug = msg + debug; + LOG4CXX_DEBUG(s_skinnyLog, debug); + } +} + void HandlePacket(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) { EthernetHeaderStruct* ethernetHeader = (EthernetHeaderStruct *)pkt_data; IpHeaderStruct* ipHeader = (IpHeaderStruct*)((char*)ethernetHeader + sizeof(EthernetHeaderStruct)); int ipHeaderLength = ipHeader->ip_hl*4; + u_char* ipPacketEnd = (u_char*)ipHeader + ipHeader->ip_len; //CStdString source = ACE_OS::inet_ntoa(ipHeader->ip_src); //CStdString dest = ACE_OS::inet_ntoa(ipHeader->ip_dest); @@ -287,6 +342,29 @@ void HandlePacket(u_char *param, const struct pcap_pkthdr *header, const u_char } } } + else if(ipHeader->ip_p == IPPROTO_TCP) + { + TcpHeaderStruct* tcpHeader = (TcpHeaderStruct*)((char *)ipHeader + ipHeaderLength); + + if(ntohs(tcpHeader->source) == SKINNY_CTRL_PORT || ntohs(tcpHeader->dest) == SKINNY_CTRL_PORT) + { + SkinnyHeaderStruct* skinnyHeader = (SkinnyHeaderStruct*)((u_char*)tcpHeader + TCP_HEADER_LENGTH); + + // Scan all skinny message in this TCP packet + while( ipPacketEnd > (u_char*)skinnyHeader && + (u_char*)skinnyHeader>=((u_char*)tcpHeader + TCP_HEADER_LENGTH) && + (ipPacketEnd - (u_char*)skinnyHeader) > SKINNY_MIN_MESSAGE_SIZE ) + { + //CStdString dbg; + //dbg.Format("Len:%u, Type:%x, %s", skinnyHeader->len, skinnyHeader->messageType, SkinnyMessageToString(skinnyHeader->messageType)); + //LOG4CXX_INFO(s_log, dbg); + HandleSkinnyMessage(skinnyHeader); + + // Point to next skinny message within this TCP packet + skinnyHeader = (SkinnyHeaderStruct*)((u_char*)skinnyHeader + SKINNY_HEADER_LENGTH + skinnyHeader->len); + } + } + } time_t now = time(NULL); if((now - lastHooveringTime) > 5) @@ -342,6 +420,7 @@ void VoIp::Initialize() { s_log = Logger::getLogger("voip"); s_sipExtractionLog = Logger::getLogger("sipextraction"); + s_skinnyLog = Logger::getLogger("skinny"); LOG4CXX_INFO(s_log, "Initializing VoIP plugin"); // create a default config object in case it was not properly initialized by Configure -- cgit v1.2.3