⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtpdump.c

📁 RTP 实现的工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/** RTP/RTCP packet dumper (RFC 1889)* Usage:*   rtpdump [address/port] > dump file** Listens on port pair specified by argument for RTP and RTCP* packets, or reads from dump file.**  -F format (names can be abbreviated):*     dump     dump in binary format (suitable for rtpplay)*     header   like 'dump', but don't save audio/video payload*     ascii    parsed packets (default)*     hex      like 'ascii', but with hex dump*     rtcp     like 'ascii', RTCP packets only*     short    RTP or vat data: [-]time ts [seq]*     payload  only audio/video payload*     *  -t d:    recording duration in minutes*  -x n:    number of payload bytes to dump per packet (hex, dump)*  -f name: name of input file, using "dump" format** To record in chunks, simply build a shell script that loops,*  with suitably chosen file names. Each such file will be*  individually playable. (Gaps?)** Copyright (c) 1995-1997 by H. Schulzrinne (GMD Fokus, Columbia U.)* $Id$*/#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>  /* struct sockaddr_in */#include <arpa/inet.h>   /* inet_ntoa() */#include <sys/time.h>    /* gettimeofday() */#include <string.h>#include <stdio.h>#include <signal.h>#include <errno.h>#if !defined(nextstep)#include <values.h>#endif#include <unistd.h>      /* select(), perror() */#include <stdlib.h>      /* getopt(), atoi() */#include <math.h>        /* fmod() */#include "rtp.h"#include "vat.h"#include "rtpdump.h"#include "ansi.h"#define VERSION "1.0"typedef u_int32 member_t;static int verbose = 0; /* decode */static char rcsid[] = "$Id: rtpdump.c,v 1.6 1995/08/30 11:19:01 hgs Exp $";typedef enum {F_invalid, F_dump, F_header, F_hex, F_rtcp, F_short,   F_payload, F_ascii} t_format;/** Payload type map.*/static struct {  char *enc;      /* encoding name */  int  rate;      /* sampling rate for audio; clock rate for video */  int  ch;        /* audio channels; 0 for video */} pt_map[256];static void usage(char *argv0){  fprintf(stderr, "Usage: %s [-F [hex|ascii|rtcp|short|payload|dump|header] [-t minutes] [-b bytes] [multicast]/port > file\n",   argv0);}static void done(int sig){  exit(0);}static double tdbl(struct timeval *a){  return a->tv_sec + a->tv_usec/1e6;}static void hex(char *buf, int len){  int i;  for (i = 0; i < len; i++) {    printf("%02x ", (unsigned char)buf[i]);  }  printf("\n");} /* hex *//** Open network sockets.*/static int open_network(char *host, int data, int sock[], struct  sockaddr_in *sin){  struct ip_mreq mreq;      /* multicast group */  int i;  int nfds = 0;  extern int hpt(char *h, struct sockaddr *sa, unsigned char *ttl);  if (hpt(host, (struct sockaddr *)sin, 0) < 0) {    usage("");  }  /* multicast */  if (host) {    mreq.imr_multiaddr = sin->sin_addr;    mreq.imr_interface.s_addr = htonl(INADDR_ANY);    sin->sin_addr = mreq.imr_multiaddr;  }  /* unicast */  else {    mreq.imr_multiaddr.s_addr = INADDR_ANY;    sin->sin_addr.s_addr       = INADDR_ANY;  }  /* create/bind sockets */  for (i = 0; i < 2; i++) {    int one = 1;    /* open data socket only if necessary */    sock[i] = -1;    if (!data && i == 0) continue;    sock[i] = socket(PF_INET, SOCK_DGRAM, 0);    if (sock[i] < 0) {      perror("socket");      exit(1);    }    if (sock[i] > nfds) nfds = sock[i];    if (setsockopt(sock[i], SOL_SOCKET, SO_REUSEADDR, (char *) &one,                   sizeof(one)) == -1)      perror("setsockopt: reuseaddr");#ifdef SO_REUSEPORT /* BSD 4.4 */    if (setsockopt(sock[i], SOL_SOCKET, SO_REUSEPORT, (char *) &one,		   sizeof(one)) == -1)      perror("setsockopt: reuseport");#endif    sin->sin_port = htons(ntohs(sin->sin_port) + i);    if (bind(sock[i], (struct sockaddr *)sin, sizeof(*sin)) < 0) {      if (errno == EADDRNOTAVAIL) {        sin->sin_addr.s_addr = INADDR_ANY;        if (bind(sock[i], (struct sockaddr *)sin, sizeof(*sin)) < 0) {          perror("bind");          exit(1);        }      }      else {        perror("bind");        exit(1);      }    }    if (IN_CLASSD(ntohl(mreq.imr_multiaddr.s_addr))) {      if (setsockopt(sock[i], IPPROTO_IP,        IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) < 0) {          perror("IP_ADD_MEMBERSHIP");          exit(1);      }    }  }  return nfds;} /* open_network *//** Write a header to the current output file.* The header consists of an identifying string, followed* by a binary structure.*/static void rtpdump_header(FILE *out, struct sockaddr_in *sin,  struct timeval *start){  RD_hdr_t hdr;  fprintf(out, "#!rtpplay%s %s/%d\n", VERSION,    inet_ntoa(sin->sin_addr), sin->sin_port);  hdr.start.tv_sec  = htonl(start->tv_sec);  hdr.start.tv_usec = htonl(start->tv_usec);  hdr.source = sin->sin_addr.s_addr;  hdr.port   = sin->sin_port;  if (fwrite((char *)&hdr, sizeof(hdr), 1, out) < 1) {    perror("fwrite");    exit(1);  } } /* rtpdump_header *//** Return type of packet.*/static char *parse_type(int type, char *buf){  if (type == 0) {    rtp_hdr_t *r = (rtp_hdr_t *)buf;    return r->version == RTP_VERSION ? "RTP" : "VATD";  }  else {    rtcp_t *r = (rtcp_t *)buf;    return r->common.version == RTP_VERSION ? "RTCP" : "VATC";  }} /* parse_type *//** Return header length.*/static int parse_header(char *buf){  rtp_hdr_t *r = (rtp_hdr_t *)buf;  int hlen = 0;  if (r->version == 0) {    vat_hdr_t *v = (vat_hdr_t *)buf;    hlen = 8 + v->nsid * 4;  }  else if (r->version == RTP_VERSION) {    hlen = 12 + r->cc * 4;  }  return hlen;} /* parse_header *//** Return header length.*/static int parse_data(char *buf, int len){  rtp_hdr_t *r = (rtp_hdr_t *)buf;  int i;  int hlen = 0;  /* Show vat format packets. */  if (r->version == 0) {    vat_hdr_t *v = (vat_hdr_t *)buf;    printf("nsid=%d flags=0x%x confid=%u ts=%u\n",      v->nsid, v->flags, v->confid, v->ts);    hlen = 8 + v->nsid * 4;  }  else if (r->version == RTP_VERSION) {    hlen = 12 + r->cc * 4;    if (len < hlen) {      printf("RTP header too short (%d bytes for %d CSRCs).\n",         len, r->cc);      return hlen;    }    printf(    "v=%d p=%d x=%d cc=%d m=%d pt=%d (%s,%d,%d) seq=%u ts=%lu ssrc=0x%lx\n",      r->version, r->p, r->x, r->cc, r->m,       r->pt, pt_map[r->pt].enc, pt_map[r->pt].ch, pt_map[r->pt].rate,      ntohs(r->seq), ntohl(r->ts), ntohl(r->ssrc));    for (i = 0; i < r->cc; i++) {      printf("csrc[%d] = %0x ", i, r->csrc[i]);    }  }  else {    printf("RTP version wrong (%d).\n", r->version);  }  return hlen;} /* parse_data *//** Print minimal per-packet information: time, timestamp, sequence number.*/static void parse_short(struct timeval now, char *buf, int len){  rtp_hdr_t *r = (rtp_hdr_t *)buf;  if (r->version == 0) {    vat_hdr_t *v = (vat_hdr_t *)buf;    printf("%ld.%06ld %lu\n",      (v->flags ? -now.tv_sec : now.tv_sec), now.tv_usec,      ntohl(v->ts));  }  else if (r->version == 2) {    printf("%ld.%06ld %lu %u\n",      (r->m ? -now.tv_sec : now.tv_sec), now.tv_usec,      ntohl(r->ts), ntohs(r->seq));  }  else {    printf("RTP version wrong (%d).\n", r->version);  }} /* parse_short */void member_sdes(member_t m, rtcp_sdes_type_t t, char *b, int len){  static struct {    rtcp_sdes_type_t t;    char *name;  } map[] = {    {RTCP_SDES_END,    "end"},     {RTCP_SDES_CNAME,  "CNAME"},    {RTCP_SDES_NAME,   "NAME"},    {RTCP_SDES_EMAIL,  "EMAIL"},    {RTCP_SDES_PHONE,  "PHONE"},    {RTCP_SDES_LOC,    "LOC"},    {RTCP_SDES_TOOL,   "TOOL"},    {RTCP_SDES_NOTE,   "NOTE"},    {RTCP_SDES_PRIV,   "PRIV"},    {11,               "SOURCE"},    {0,0}  };  int i;  char num[10];  sprintf(num, "%d", t);  for (i = 0; map[i].name; i++) {    if (map[i].t == t) break;  }  printf("%s=\"%*.*s\" ",    map[i].name ? map[i].name : num, len, len, b);} /* member_sdes *//** Parse one SDES chunk (one SRC description). Total length is 'len'.* Return new buffer position or zero if error.*/static char *rtp_read_sdes(char *b, int len){  rtcp_sdes_item_t *rsp;  u_int32 src = *(u_int32 *)b;  int total_len = 0;  len -= 4;  /* subtract SSRC from available bytes */  if (len <= 0) {    return 0;  }  rsp = (rtcp_sdes_item_t *)(b + 4);  for (; rsp->type; rsp = (rtcp_sdes_item_t *)((char *)rsp + rsp->length + 2)) {    member_sdes(src, rsp->type, rsp->data, rsp->length);    total_len += rsp->length + 2;  }  if (total_len >= len) {	fprintf(stderr,       "Remaining length of %d bytes for SSRC item too short (has %u bytes)\n",      len, total_len);    return 0;  }  b = (char *)rsp + 1;  /* skip padding */  return b + ((4 - ((int)b & 0x3)) & 0x3);} /* rtp_read_sdes *//** Return length parsed, -1 on error.*/static int parse_control(char *buf, int len){  rtcp_t *r;         /* RTCP header */  int i;  r = (rtcp_t *)buf;  /* Backwards compatibility: VAT header. */  if (r->common.version == 0) {    struct CtrlMsgHdr *v = (struct CtrlMsgHdr *)buf;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -