summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenri Herscher <henri@oreka.org>2005-10-31 19:42:26 +0000
committerHenri Herscher <henri@oreka.org>2005-10-31 19:42:26 +0000
commitad54c92028787c13d0930fa6124b9db7a37134c0 (patch)
treef050b2a7cc217dcd0a2e24b9d7362736293fba1b
parentf0b8dfe5fe22576adc48c5ec414bb40cf38d0cb5 (diff)
Groundwork for adding skinny support
git-svn-id: https://oreka.svn.sourceforge.net/svnroot/oreka/trunk@24 09dcff7a-b715-0410-9601-b79a96267cd0
-rw-r--r--orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.cpp39
-rw-r--r--orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h82
-rw-r--r--orkaudio/audiocaptureplugins/voip/RtpSession.cpp20
-rw-r--r--orkaudio/audiocaptureplugins/voip/RtpSession.h26
-rw-r--r--orkaudio/audiocaptureplugins/voip/VoIp.cpp79
5 files changed, 236 insertions, 10 deletions
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<CStdString, RtpSessionRef>::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<SccpCallInfoMessageInfo> SccpCallInfoMessageInfoRef;
+
+
+class SccpStartMediaTransmissionInfo
+{
+ struct in_addr m_remoteIp;
+ int m_remoteTcpPort;
+ CStdString m_callId;
+};
+typedef boost::shared_ptr<SccpStartMediaTransmissionInfo> SccpStartMediaTransmissionInfoRef;
+
+
+class SccpStopMediaTransmissionInfo
+{
+ CStdString m_callId;
+};
+typedef boost::shared_ptr<SccpStopMediaTransmissionInfo> 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; i<len; i++)
+ {
+ sprintf(byteAsHex, "%.2x", input[i]);
+ output += byteAsHex;
+ }
+}
+
// find the address that follows the given search string between start and stop pointers
char* memFindAfter(char* toFind, char* start, char* stop)
{
@@ -252,11 +264,54 @@ bool TrySipInvite(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader
return result;
}
+void HandleSkinnyMessage(SkinnyHeaderStruct* skinnyHeader)
+{
+ bool useful = true;
+ CStdString debug;
+ SkStartMediaTransmissionStruct* start;
+ SkStopMediaTransmissionStruct* stop;
+ SkCallInfoStruct* callInfo;
+
+ switch(skinnyHeader->messageType)
+ {
+ 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