Skip to content

Commit

Permalink
Merge branch 'pcap-image'
Browse files Browse the repository at this point in the history
Closes #42
Closes #129
  • Loading branch information
wdoekes committed May 8, 2015
2 parents 4609a0b + 0026639 commit 9f302f2
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 47 deletions.
1 change: 1 addition & 0 deletions include/actions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class CAction
E_AT_CLOSE_CON,
#ifdef PCAPPLAY
E_AT_PLAY_PCAP_AUDIO,
E_AT_PLAY_PCAP_IMAGE,
E_AT_PLAY_PCAP_VIDEO,
#endif
#ifdef RTP_STREAM
Expand Down
1 change: 1 addition & 0 deletions include/call.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ class call : virtual public task, virtual public listener, public virtual socket
int hasMediaInformation;
pthread_t media_thread;
play_args_t play_args_a;
play_args_t play_args_i;
play_args_t play_args_v;
#endif

Expand Down
3 changes: 2 additions & 1 deletion include/rtpstream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ void rtpstream_shutdown (void);

int rtpstream_get_audioport (rtpstream_callinfo_t *callinfo);
int rtpstream_get_videoport (rtpstream_callinfo_t *callinfo);
void rtpstream_set_remote (rtpstream_callinfo_t *callinfo, int ip_ver, char *ip_addr, int audio_port, int video_port);
void rtpstream_set_remote (rtpstream_callinfo_t *callinfo, int ip_ver, char *ip_addr,
int audio_port, int video_port);

int rtpstream_cache_file (char *filename);
void rtpstream_play (rtpstream_callinfo_t *callinfo, rtpstream_actinfo_t *actioninfo);
Expand Down
4 changes: 2 additions & 2 deletions src/actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ void CAction::afficheInfo()
} else if (M_action == E_AT_VAR_TO_DOUBLE) {
printf("Type[%d] - toDouble varId[%s]", M_action, display_scenario->allocVars->getName(M_varId));
#ifdef PCAPPLAY
} else if ((M_action == E_AT_PLAY_PCAP_AUDIO) || (M_action == E_AT_PLAY_PCAP_VIDEO)) {
} else if ((M_action == E_AT_PLAY_PCAP_AUDIO) || (M_action == E_AT_PLAY_PCAP_IMAGE) || (M_action == E_AT_PLAY_PCAP_VIDEO)) {
printf("Type[%d] - file[%s]", M_action, M_pcapArgs->file);
#endif

Expand Down Expand Up @@ -635,7 +635,7 @@ CAction::CAction(scenario *scenario)
#endif

#ifdef RTP_STREAM
memset (&M_rtpstream_actinfo,0,sizeof(M_rtpstream_actinfo));
memset(&M_rtpstream_actinfo, 0, sizeof(M_rtpstream_actinfo));
#endif

M_scenario = scenario;
Expand Down
104 changes: 71 additions & 33 deletions src/call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,19 +195,24 @@ uint8_t get_remote_ipv6_media(char *msg, struct in6_addr *addr)
}

/*
* Look for "m=audio " or "m=video " pattern in the message and extract the
* following value which should be port number
* Look for "m=audio ", "m=image " or "m=video " pattern in the message
* and extract the following value which should be port number.
*/
#define PAT_AUDIO 1
#define PAT_VIDEO 2
uint16_t get_remote_port_media(const char *msg, int pattype)
enum media_ptn {
PAT_AUDIO,
PAT_IMAGE,
PAT_VIDEO
};
uint16_t get_remote_port_media(const char *msg, enum media_ptn pattype)
{
const char *pattern;
char *begin, *end;
char number[6];

if (pattype == PAT_AUDIO) {
pattern = "m=audio ";
} else if (pattype == PAT_IMAGE) {
pattern = "m=image ";
} else if (pattype == PAT_VIDEO) {
pattern = "m=video ";
} else {
Expand Down Expand Up @@ -244,7 +249,7 @@ uint16_t get_remote_port_media(const char *msg, int pattype)
*/
void call::get_remote_media_addr(char *msg)
{
uint16_t video_port, audio_port;
uint16_t audio_port, image_port, video_port;
if (media_ip_is_ipv6) {
struct in6_addr ip_media;
if (get_remote_ipv6_media(msg, &ip_media)) {
Expand All @@ -254,16 +259,25 @@ void call::get_remote_media_addr(char *msg)
(_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_flowinfo = 0;
(_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_scope_id = 0;
(_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_family = AF_INET6;
(_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_port = audio_port;
(_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_port = htons(audio_port);
(_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_addr = ip_media;
}
image_port = get_remote_port_media(msg, PAT_IMAGE);
if (image_port) {
/* We have image in the SDP: set the to_image addr */
(_RCAST(struct sockaddr_in6 *, &(play_args_i.to)))->sin6_flowinfo = 0;
(_RCAST(struct sockaddr_in6 *, &(play_args_i.to)))->sin6_scope_id = 0;
(_RCAST(struct sockaddr_in6 *, &(play_args_i.to)))->sin6_family = AF_INET6;
(_RCAST(struct sockaddr_in6 *, &(play_args_i.to)))->sin6_port = htons(image_port);
(_RCAST(struct sockaddr_in6 *, &(play_args_i.to)))->sin6_addr = ip_media;
}
video_port = get_remote_port_media(msg, PAT_VIDEO);
if (video_port) {
/* We have video in the SDP: set the to_video addr */
(_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_flowinfo = 0;
(_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_scope_id = 0;
(_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_family = AF_INET6;
(_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_port = video_port;
(_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_port = htons(video_port);
(_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_addr = ip_media;
}
hasMediaInformation = 1;
Expand All @@ -276,14 +290,21 @@ void call::get_remote_media_addr(char *msg)
if (audio_port) {
/* We have audio in the SDP: set the to_audio addr */
(_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_family = AF_INET;
(_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_port = audio_port;
(_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_port = htons(audio_port);
(_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_addr.s_addr = ip_media;
}
image_port = get_remote_port_media(msg, PAT_IMAGE);
if (image_port) {
/* We have image in the SDP: set the to_image addr */
(_RCAST(struct sockaddr_in *, &(play_args_i.to)))->sin_family = AF_INET;
(_RCAST(struct sockaddr_in *, &(play_args_i.to)))->sin_port = htons(image_port);
(_RCAST(struct sockaddr_in *, &(play_args_i.to)))->sin_addr.s_addr = ip_media;
}
video_port = get_remote_port_media(msg, PAT_VIDEO);
if (video_port) {
/* We have video in the SDP: set the to_video addr */
(_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_family = AF_INET;
(_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_port = video_port;
(_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_port = htons(video_port);
(_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_addr.s_addr = ip_media;
}
hasMediaInformation = 1;
Expand All @@ -299,15 +320,17 @@ void call::get_remote_media_addr(char *msg)

#define SDP_IPADDR_PREFIX "\nc=IN IP"
#define SDP_AUDIOPORT_PREFIX "\nm=audio"
#define SDP_IMAGEPORT_PREFIX "\nm=image"
#define SDP_VIDEOPORT_PREFIX "\nm=video"
void call::extract_rtp_remote_addr (char * msg)
{
char *search;
char *copy;
char ip_addr[128];
int ip_ver;
int audio_port= 0;
int video_port= 0;
int audio_port = 0;
int image_port = 0;
int video_port = 0;

/* Look for start of message body */
search= strstr(msg,"\r\n\r\n");
Expand Down Expand Up @@ -349,6 +372,15 @@ void call::extract_rtp_remote_addr (char * msg)
}
sscanf (search,"%d",&audio_port);
}
/* And find the port number for the image stream */
search= strstr(msg,SDP_IMAGEPORT_PREFIX);
if (search) {
search+= strlen(SDP_IMAGEPORT_PREFIX);
while ( (*search==' ') || (*search=='\t') ) {
search++;
}
sscanf (search,"%d",&image_port);
}
/* And find the port number for the video stream */
search= strstr(msg,SDP_VIDEOPORT_PREFIX);
if (search) {
Expand All @@ -358,10 +390,13 @@ void call::extract_rtp_remote_addr (char * msg)
}
sscanf (search,"%d",&video_port);
}
if ((audio_port==0)&&(video_port==0)) {
ERROR("extract_rtp_remote_addr: no m=audio or m=video line found in SDP message body");
if (audio_port == 0 && image_port == 0 && video_port == 0) {
ERROR("extract_rtp_remote_addr: no m=audio, m=image or m=video line found in SDP message body");
}
rtpstream_set_remote (&rtpstream_callinfo,ip_ver,ip_addr,audio_port,video_port);
/* If we get an image_port only, we won't set anything useful.
* We cannot use rtpstream for udptl/t38 data because it has
* non-linear timing and data size. */
rtpstream_set_remote(&rtpstream_callinfo, ip_ver, ip_addr, audio_port, video_port);
}
#endif

Expand Down Expand Up @@ -612,8 +647,10 @@ void call::init(scenario * call_scenario, struct sipp_socket *socket, struct soc

#ifdef PCAPPLAY
memset(&(play_args_a.to), 0, sizeof(struct sockaddr_storage));
memset(&(play_args_i.to), 0, sizeof(struct sockaddr_storage));
memset(&(play_args_v.to), 0, sizeof(struct sockaddr_storage));
memset(&(play_args_a.from), 0, sizeof(struct sockaddr_storage));
memset(&(play_args_i.from), 0, sizeof(struct sockaddr_storage));
memset(&(play_args_v.from), 0, sizeof(struct sockaddr_storage));
hasMediaInformation = 0;
media_thread = 0;
Expand Down Expand Up @@ -2105,9 +2142,8 @@ char* call::createSendingMessage(SendingMessage *src, int P_index, char *msg_buf
(sockaddr *)(void *)&server_sockaddr, &len);

if (server_sockaddr.ss_family == AF_INET6) {
char * temp_dest;
temp_dest = (char *) malloc(INET6_ADDRSTRLEN);
memset(temp_dest,0,INET6_ADDRSTRLEN);
char temp_dest[INET6_ADDRSTRLEN]; /* fits both INET and INET6 */
temp_dest[0] = temp_dest[INET6_ADDRSTRLEN - 1] = '\0';
inet_ntop(AF_INET6,
&((_RCAST(struct sockaddr_in6 *,&server_sockaddr))->sin6_addr),
temp_dest,
Expand Down Expand Up @@ -2139,21 +2175,21 @@ char* call::createSendingMessage(SendingMessage *src, int P_index, char *msg_buf
if (begin == msg_buffer) {
ERROR("Can not find beginning of a line for the media port!\n");
}
play_args_t *play_args = NULL;
if (strstr(begin, "audio")) {
if (media_ip_is_ipv6) {
(_RCAST(struct sockaddr_in6 *, &(play_args_a.from)))->sin6_port = port;
} else {
(_RCAST(struct sockaddr_in *, &(play_args_a.from)))->sin_port = port;
}
play_args = &play_args_a;
} else if (strstr(begin, "image")) {
play_args = &play_args_i;
} else if (strstr(begin, "video")) {
if (media_ip_is_ipv6) {
(_RCAST(struct sockaddr_in6 *, &(play_args_v.from)))->sin6_port = port;
} else {
(_RCAST(struct sockaddr_in *, &(play_args_v.from)))->sin_port = port;
}
play_args = &play_args_v;
} else {
ERROR("media_port keyword with no audio or video on the current line (%s)", begin);
}
if (media_ip_is_ipv6) {
(_RCAST(struct sockaddr_in6 *, &(play_args->from)))->sin6_port = htons(port);
} else {
(_RCAST(struct sockaddr_in *, &(play_args->from)))->sin_port = htons(port);
}
#endif
dest += sprintf(dest, "%u", port);
break;
Expand Down Expand Up @@ -3835,16 +3871,18 @@ call::T_ActionResult call::executeAction(char * msg, message *curmsg)
}
#ifdef PCAPPLAY
} else if ((currentAction->getActionType() == CAction::E_AT_PLAY_PCAP_AUDIO) ||
(currentAction->getActionType() == CAction::E_AT_PLAY_PCAP_IMAGE) ||
(currentAction->getActionType() == CAction::E_AT_PLAY_PCAP_VIDEO)) {
play_args_t *play_args = NULL;
play_args_t *play_args;
if (currentAction->getActionType() == CAction::E_AT_PLAY_PCAP_AUDIO) {
play_args = &(this->play_args_a);
} else if (currentAction->getActionType() == CAction::E_AT_PLAY_PCAP_IMAGE) {
play_args = &(this->play_args_i);
} else if (currentAction->getActionType() == CAction::E_AT_PLAY_PCAP_VIDEO) {
play_args = &(this->play_args_v);
}

if (!play_args)
} else {
ERROR("Can't find pcap data to play");
}

play_args->pcap = currentAction->getPcapPkts();
/* port number is set in [auto_]media_port interpolation */
Expand All @@ -3857,7 +3895,7 @@ call::T_ActionResult call::executeAction(char * msg, message *curmsg)
from->sin_family = AF_INET;
from->sin_addr.s_addr = inet_addr(media_ip);
}
/* Create a thread to send RTP packets */
/* Create a thread to send RTP or UDPTL packets */
pthread_attr_t attr;
pthread_attr_init(&attr);
#ifndef PTHREAD_STACK_MIN
Expand Down
31 changes: 24 additions & 7 deletions src/prepare_pcap.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,9 @@
* made available by the platform, as we had no problems to get them on all supported platforms.
*/

typedef struct _ether_hdr {
char ether_dst[6];
char ether_src[6];
typedef struct _ether_type_hdr {
u_int16_t ether_type; /* we only need the type, so we can determine, if the next header is IPv4 or IPv6 */
} ether_hdr;
} ether_type_hdr;

typedef struct _ipv6_hdr {
char dontcare[6];
Expand Down Expand Up @@ -99,7 +97,9 @@ int prepare_pkts(char *file, pcap_pkts *pkts)
u_int16_t base = 0xffff;
u_long pktlen;
pcap_pkt *pkt_index;
ether_hdr *ethhdr;
size_t ether_type_offset;
ether_type_hdr *ethhdr;

struct iphdr *iphdr;
ipv6_hdr *ip6hdr;
struct udphdr *udphdr;
Expand All @@ -110,6 +110,19 @@ int prepare_pkts(char *file, pcap_pkts *pkts)
if (!pcap)
ERROR_NO("Can't open PCAP file '%s'", file);

switch (pcap_datalink(pcap)) {
case DLT_EN10MB:
/* srcmac[6], dstmac[6], ethertype[2] */
ether_type_offset = 12;
break;
case DLT_LINUX_SLL:
/* some_stuff[14], ethertype[2] */
ether_type_offset = 14;
break;
default:
ERROR("Unsupported link-type %d", pcap_datalink(pcap));
}

#if HAVE_PCAP_NEXT_EX
while (pcap_next_ex (pcap, &pkthdr, (const u_char **) &pktdata) == 1) {
#else
Expand All @@ -122,10 +135,14 @@ int prepare_pkts(char *file, pcap_pkts *pkts)
ERROR("Can't allocate memory for pcap pkthdr");
while ((pktdata = (u_char *) pcap_next (pcap, pkthdr)) != NULL) {
#endif
ethhdr = (ether_hdr *)pktdata;
if (pkthdr->len != pkthdr->caplen) {
ERROR("You got truncated packets. Please create a new dump with -s0");
}
ethhdr = (ether_type_hdr *)(pktdata + ether_type_offset);
if (ntohs(ethhdr->ether_type) != 0x0800 /* IPv4 */
&& ntohs(ethhdr->ether_type) != 0x86dd) { /* IPv6 */
fprintf(stderr, "Ignoring non IP{4,6} packet!\n");
fprintf(stderr, "Ignoring non IP{4,6} packet, got ether_type %hu!\n",
ntohs(ethhdr->ether_type));
continue;
}
iphdr = (struct iphdr *)((char *)ethhdr + sizeof(*ethhdr));
Expand Down
6 changes: 4 additions & 2 deletions src/rtpstream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -886,7 +886,8 @@ int rtpstream_get_videoport (rtpstream_callinfo_t *callinfo)
}

/* code checked */
void rtpstream_set_remote (rtpstream_callinfo_t *callinfo, int ip_ver, char *ip_addr, int audio_port, int video_port)
void rtpstream_set_remote (rtpstream_callinfo_t *callinfo, int ip_ver, char *ip_addr,
int audio_port, int video_port)
{
struct sockaddr_storage address;
struct in_addr *ip4_addr;
Expand All @@ -895,7 +896,8 @@ void rtpstream_set_remote (rtpstream_callinfo_t *callinfo, int ip_ver, char *ip_
unsigned count;
int nonzero_ip;

debugprint ("rtpstream_set_remote callinfo=%p, ip_ver %d ip_addr %s audio %d video %d\n",callinfo,ip_ver,ip_addr,audio_port,video_port);
debugprint("rtpstream_set_remote callinfo=%p, ip_ver %d ip_addr %s audio %d video %d\n",
callinfo, ip_ver, ip_addr, audio_port, video_port);

taskinfo= callinfo->taskinfo;
if (!taskinfo) {
Expand Down
5 changes: 5 additions & 0 deletions src/scenario.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1608,6 +1608,9 @@ void scenario::parseAction(CActions *actions)
} else if ((ptr = xp_get_value((char *) "play_pcap_audio"))) {
tmpAction->setPcapArgs(ptr);
tmpAction->setActionType(CAction::E_AT_PLAY_PCAP_AUDIO);
} else if ((ptr = xp_get_value((char *) "play_pcap_image"))) {
tmpAction->setPcapArgs(ptr);
tmpAction->setActionType(CAction::E_AT_PLAY_PCAP_IMAGE);
hasMedia = 1;
} else if ((ptr = xp_get_value((char *) "play_pcap_video"))) {
tmpAction->setPcapArgs(ptr);
Expand All @@ -1616,6 +1619,8 @@ void scenario::parseAction(CActions *actions)
#else
} else if ((ptr = xp_get_value((char *) "play_pcap_audio"))) {
ERROR("Scenario specifies a play_pcap_audio action, but this version of SIPp does not have PCAP support");
} else if ((ptr = xp_get_value((char *) "play_pcap_image"))) {
ERROR("Scenario specifies a play_pcap_image action, but this version of SIPp does not have PCAP support");
} else if ((ptr = xp_get_value((char *) "play_pcap_video"))) {
ERROR("Scenario specifies a play_pcap_video action, but this version of SIPp does not have PCAP support");
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/send_packets.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ int send_packets (play_args_t * play_args)
memcpy(udp, pkt_index->data, pkt_index->pktlen);
port_diff = ntohs (udp->uh_dport) - pkts->base;
// modify UDP ports
udp->uh_sport = htons(port_diff + *from_port);
udp->uh_dport = htons(port_diff + *to_port);
udp->uh_sport = htons(port_diff + ntohs(*from_port));
udp->uh_dport = htons(port_diff + ntohs(*to_port));

if (!media_ip_is_ipv6) {
temp_sum = checksum_carry(pkt_index->partial_check + check((u_int16_t *) &(((struct sockaddr_in *)(void *) from)->sin_addr.s_addr), 4) + check((u_int16_t *) &(((struct sockaddr_in *)(void *) to)->sin_addr.s_addr), 4) + check((u_int16_t *) &udp->uh_sport, 4));
Expand Down

0 comments on commit 9f302f2

Please sign in to comment.