[tools] / trunk / publicdemo / sipp / send_packets.c Repository:
ViewVC logotype

View of /trunk/publicdemo/sipp/send_packets.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 70 - (download) (annotate)
Thu May 5 20:35:33 2011 UTC (2 years ago) by jhermanski
File size: 8493 byte(s)
Package all media, etc. needed for Public demo system into one tree
    1 /*
    2  * send_packets.c: from tcpreplay tools by Aaron Turner
    3  * http://tcpreplay.sourceforge.net/
    4  * send_packets.c is under BSD license (see below)
    5  * SIPp is under GPL license
    6  *
    7  *
    8  * Copyright (c) 2001-2004 Aaron Turner.
    9  * All rights reserved.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  *
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the names of the copyright owners nor the names of its
   21  *    contributors may be used to endorse or promote products derived from
   22  *    this software without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
   25  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   27  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
   28  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
   30  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
   32  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   33  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   34  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   35  */
   36 
   37 /*Map linux structure fields to BSD ones*/
   38 #ifdef __LINUX
   39 #define __BSD_SOURCE
   40 #define _BSD_SOURCE
   41 #define __FAVOR_BSD
   42 #endif /*__LINUX*/
   43 
   44 #include <pcap.h>
   45 #include <unistd.h>
   46 #include <stdlib.h>
   47 #include <netinet/udp.h>
   48 #if defined(__DARWIN) || defined(__CYGWIN) || defined(__FreeBSD__)
   49 #include <netinet/in.h>
   50 #endif
   51 #ifndef __CYGWIN
   52 #include <netinet/ip6.h>
   53 #endif
   54 #include <errno.h>
   55 #include <string.h>
   56 #include <fcntl.h>
   57 
   58 #include "send_packets.h"
   59 #include "prepare_pcap.h"
   60 #include "screen.hpp"
   61 
   62 extern volatile unsigned long rtp_pckts_pcap;
   63 extern volatile unsigned long rtp_bytes_pcap;
   64 extern int media_ip_is_ipv6;
   65 
   66 inline void
   67 timerdiv (struct timeval *tvp, float div)
   68 {
   69   double interval;
   70 
   71   if (div == 0 || div == 1)
   72     return;
   73 
   74   interval = ((double) tvp->tv_sec * 1000000 + tvp->tv_usec) / (double) div;
   75   tvp->tv_sec = interval / (int) 1000000;
   76   tvp->tv_usec = interval - (tvp->tv_sec * 1000000);
   77 }
   78 
   79 /*
   80  * converts a float to a timeval structure
   81  */
   82 inline void
   83 float2timer (float time, struct timeval *tvp)
   84 {
   85   float n;
   86 
   87   n = time;
   88 
   89   tvp->tv_sec = n;
   90 
   91   n -= tvp->tv_sec;
   92   tvp->tv_usec = n * 100000;
   93 }
   94 
   95 /* buffer should be "file_name" */
   96 int
   97 parse_play_args (char *buffer, pcap_pkts *pkts)
   98 {
   99   pkts->file = strdup (buffer);
  100   prepare_pkts(pkts->file, pkts);
  101   return 1;
  102 }
  103 
  104 void hexdump(char *p, int s) {
  105   int i;
  106   for (i = 0; i < s; i++) {
  107     fprintf(stderr, "%02x ", *(char *)(p+i));
  108   }
  109   fprintf(stderr, "\n");
  110 }
  111 
  112 /*Safe threaded version*/
  113 void do_sleep (struct timeval *, struct timeval *,
  114                struct timeval *, struct timeval *);
  115 
  116 int
  117 send_packets (play_args_t * play_args)
  118 {
  119   int ret, sock, port_diff;
  120   pcap_pkt *pkt_index, *pkt_max;
  121   uint16_t *from_port, *to_port;
  122   struct timeval didsleep = { 0, 0 };
  123   struct timeval start = { 0, 0 };
  124   struct timeval last = { 0, 0 };
  125   pcap_pkts *pkts = play_args->pcap;
  126   /* to and from are pointers in case play_args (call sticky) gets modified! */
  127   struct sockaddr_storage *to = &(play_args->to);
  128   struct sockaddr_storage *from = &(play_args->from);
  129   struct udphdr *udp;
  130   struct sockaddr_in6 to6, from6;
  131   char buffer[PCAP_MAXPACKET];
  132   int temp_sum;
  133 
  134 #ifndef MSG_DONTWAIT
  135   int fd_flags;
  136 #endif
  137 
  138   if (media_ip_is_ipv6) {
  139     sock = socket(PF_INET6, SOCK_RAW, IPPROTO_UDP);
  140     if (sock < 0) {
  141       ERROR("Can't create raw socket (need to run as root?)");
  142     }
  143     from_port = &(((struct sockaddr_in6 *)(void *) from )->sin6_port);
  144     to_port = &(((struct sockaddr_in6 *)(void *) to )->sin6_port);
  145   }
  146   else {
  147     sock = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
  148     if (sock < 0) {
  149       ERROR("Can't create raw socket (need to run as root?)");
  150     }
  151     from_port = &(((struct sockaddr_in *)(void *) from )->sin_port);
  152     to_port = &(((struct sockaddr_in *)(void *) to )->sin_port);
  153   }
  154 
  155 #ifndef MSG_DONTWAIT
  156   fd_flags = fcntl(sock, F_GETFL , NULL);
  157   fd_flags |= O_NONBLOCK;
  158   fcntl(sock, F_SETFL , fd_flags);
  159 #endif
  160   udp = (struct udphdr *)buffer;
  161 
  162   pkt_index = pkts->pkts;
  163   pkt_max = pkts->max;
  164 
  165   if (media_ip_is_ipv6) {
  166     memset(&to6, 0, sizeof(to6));
  167     memset(&from6, 0, sizeof(from6));
  168     to6.sin6_family = AF_INET6;
  169     from6.sin6_family = AF_INET6;
  170     memcpy(&(to6.sin6_addr.s6_addr), &(((struct sockaddr_in6 *)(void *) to)->sin6_addr.s6_addr), sizeof(to6.sin6_addr.s6_addr));
  171     memcpy(&(from6.sin6_addr.s6_addr), &(((struct sockaddr_in6 *)(void *) from)->sin6_addr.s6_addr), sizeof(from6.sin6_addr.s6_addr));
  172   }
  173 
  174   while (pkt_index < pkt_max) {
  175     memcpy(udp, pkt_index->data, pkt_index->pktlen);
  176     port_diff = ntohs (udp->uh_dport) - pkts->base;
  177     // modify UDP ports
  178     udp->uh_sport = htons(port_diff + *from_port);
  179     udp->uh_dport = htons(port_diff + *to_port);
  180 
  181     if (!media_ip_is_ipv6) {
  182       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));
  183     }
  184     else {
  185       temp_sum = checksum_carry(pkt_index->partial_check + check((u_int16_t *) &(from6.sin6_addr.s6_addr), 16) + check((u_int16_t *) &(to6.sin6_addr.s6_addr), 16) + check((u_int16_t *) &udp->uh_sport, 4));
  186     }
  187 
  188 #ifndef _HPUX_LI
  189 #ifdef __HPUX
  190     udp->uh_sum = (temp_sum>>16)+((temp_sum & 0xffff)<<16);
  191 #else
  192     udp->uh_sum = temp_sum;
  193 #endif
  194 #else
  195     udp->uh_sum = temp_sum;
  196 #endif
  197 
  198     do_sleep ((struct timeval *) &pkt_index->ts, &last, &didsleep,
  199     &start);
  200 #ifdef MSG_DONTWAIT
  201     if (!media_ip_is_ipv6) {
  202       ret = sendto(sock, buffer, pkt_index->pktlen, MSG_DONTWAIT,
  203                    (struct sockaddr *)(void *) to, sizeof(struct sockaddr_in));
  204     }
  205     else {
  206       ret = sendto(sock, buffer, pkt_index->pktlen, MSG_DONTWAIT,
  207                    (struct sockaddr *)(void *) &to6, sizeof(struct sockaddr_in6));
  208     }
  209 #else
  210     if (!media_ip_is_ipv6) {
  211       ret = sendto(sock, buffer, pkt_index->pktlen, 0,
  212                    (struct sockaddr *)(void *) to, sizeof(struct sockaddr_in));
  213     }
  214     else {
  215       ret = sendto(sock, buffer, pkt_index->pktlen, 0,
  216                    (struct sockaddr *)(void *) &to6, sizeof(struct sockaddr_in6));
  217     }
  218 #endif
  219     if (ret < 0) {
  220       close(sock);
  221       WARNING_P1("send_packets.c: sendto failed with error: %s", strerror(errno));
  222       return( -1);
  223     }
  224 
  225     rtp_pckts_pcap++;
  226     rtp_bytes_pcap += pkt_index->pktlen - sizeof(*udp);
  227     memcpy (&last, &(pkt_index->ts), sizeof (struct timeval));
  228     pkt_index++;
  229   }
  230 
  231   close(sock);
  232   return 0;
  233 }
  234 
  235 /*
  236  * Given the timestamp on the current packet and the last packet sent,
  237  * calculate the appropriate amount of time to sleep and do so.
  238  */
  239 void do_sleep (struct timeval *time, struct timeval *last,
  240     struct timeval *didsleep, struct timeval *start)
  241 {
  242   struct timeval nap, now, delta;
  243   struct timespec sleep;
  244 
  245   if (gettimeofday (&now, NULL) < 0)
  246     {
  247       fprintf (stderr, "Error gettimeofday: %s\n", strerror (errno));
  248     }
  249 
  250   /* First time through for this file */
  251   if (!timerisset (last))
  252     {
  253       *start = now;
  254       timerclear (&delta);
  255       timerclear (didsleep);
  256     }
  257   else
  258     {
  259       timersub (&now, start, &delta);
  260     }
  261 
  262   if (timerisset (last) && timercmp (time, last, >))
  263     {
  264       timersub (time, last, &nap);
  265     }
  266   else
  267     {
  268       /*
  269        * Don't sleep if this is our first packet, or if the
  270        * this packet appears to have been sent before the
  271        * last packet.
  272        */
  273       timerclear (&nap);
  274     }
  275 
  276   timeradd (didsleep, &nap, didsleep);
  277 
  278   if (timercmp (didsleep, &delta, >))
  279     {
  280       timersub (didsleep, &delta, &nap);
  281 
  282       sleep.tv_sec = nap.tv_sec;
  283       sleep.tv_nsec = nap.tv_usec * 1000; /* convert ms to ns */
  284 
  285       while ((nanosleep (&sleep, &sleep) == -1) && (errno == -EINTR));
  286     }
  287 }
  288 
  289 

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.8