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

📄 rtp.c

📁 用C实现的在LINUX系统下的聊天程序.无需登录就可以下载
💻 C
📖 第 1 页 / 共 2 页
字号:
/* rtp.c - Real Time Protocol                                             *//*                                                                        *//* This program is free software; you can redistribute it and/or modify   *//* it under the terms of the GNU General Public License as published by   *//* the Free Software Foundation; either version 2, or (at your option)    *//* any later version.                                                     *//*                                                                        *//* This program is distributed in the hope that it will be useful,        *//* but WITHOUT ANY WARRANTY; without even the implied warranty of         *//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *//* GNU General Public License for more details.                           *//*                                                                        *//* You should have received a copy of the GNU General Public License      *//* along with this program; if not, write to the Free Software            *//* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA              *//* 02111-1307, USA.                                                       */#include "rtp.h"/* used in NTP time calculation */#define SECS_BETWEEN_1900_1970 2208988800u/* tool identification */char ecomm_id[] = "e-Comm (C) ComunIP";/* Functions for double hashing */unsigned int _rtp_members_h1 (const void *key) {  return (((rtp_source_t *) key) -> ssrc % RTP_HASH_SIZE);}unsigned int _rtp_members_h2 (const void *key) {  return (1 + ((rtp_source_t *) key) -> ssrc % (RTP_HASH_SIZE - 2));}/* Match function */int _rtp_members_match (const void *key1, const void *key2) {  return (((rtp_source_t *) key1) -> ssrc == ((rtp_source_t *) key2) -> ssrc);}/* Initializes a RTP session */void rtp_init (rtp_t *s, int flags) {  uint8_t *username = getenv("LOGNAME");  uint8_t *hostname = getenv("HOSTNAME");  pthread_mutex_init (&s -> guard, NULL);  /* set RTP build flags */  s -> flags = flags;  s -> seq = (uint16_t) rand32();               /* initialize sequencing  */  s -> cycles = 0;  s -> ssrc = (uint32_t) rand32();              /* get random SSRC id     */  s -> pcount = 0;  s -> ocount = 0;  s -> cc = 0;  memset (s -> cname, '\0', RTP_SDES_MAX);  memset (s -> name, '\0', RTP_SDES_MAX);  memset (s -> email, '\0', RTP_SDES_MAX);  memset (s -> phone, '\0', RTP_SDES_MAX);  memset (s -> loc, '\0', RTP_SDES_MAX);  memset (s -> tool, '\0', RTP_SDES_MAX);  memset (s -> note, '\0', RTP_SDES_MAX);  sprintf(s -> cname, "%s@%s", username, hostname);  sprintf(s -> tool, "%s", ecomm_id);  ohtbl_init (&s -> members, RTP_HASH_SIZE, _rtp_members_h1,        _rtp_members_h2, _rtp_members_match, NULL,        RTP_HASH_TOLERANCE / 2);  return;}/* Destroy RTP session */void rtp_destroy (rtp_t *s) {  rtp_source_t *member;  pthread_mutex_lock (&s -> guard);  ohtbl_flush (&s -> members);  while ((member = (rtp_source_t *) ohtbl_traverse(&s -> members)) != NULL) {    phtbl_destroy (&member -> pqueue);    pthread_mutex_destroy (&member -> guard);  }  ohtbl_destroy (&s -> members);  pthread_mutex_destroy (&s -> guard);  return;}/* Add new csrc to RTP parameters,   returns 0 on fail, 1 on success */int rtp_add_csrc (rtp_t *s, uint32_t csrc) {  int idx;              /* index */  /* put csrc in network byte order */  csrc = htonl (csrc);  pthread_mutex_lock (&s -> guard);  /* checks for maximal csrc number */  if (s -> cc >= 15) {    pthread_mutex_unlock (&s -> guard);    return (0);  }  /* check if new csrc doesn't exist in csrc list */   for (idx = 0; idx < s -> cc; idx++) {    if (s -> csrc[idx] == csrc) {      pthread_mutex_unlock (&s -> guard);      return (0);    }  }  /* just append new csrc to list */  s -> csrc[s -> cc++] = csrc;  pthread_mutex_unlock (&s -> guard);  return (1);}/* Remove a csrc from list,   returns 0 on fail, 1 on success */int rtp_del_csrc (rtp_t *s, uint32_t csrc) {  int cur, prev;        /* current and previous index */  /* put csrc in network byte order */  csrc = htonl (csrc);  pthread_mutex_lock (&s -> guard);  /* tries to remove element */  for (cur = 0, prev = 0; prev < s -> cc; cur++, prev++) {    if (s -> csrc[cur] == csrc)      cur++;    s -> csrc[prev] = s -> csrc[cur];  }  /* checks for empty csrc list */  if (s -> cc > 0 && prev != cur) {    s -> cc--;    pthread_mutex_unlock (&s -> guard);    return (1);  }  pthread_mutex_unlock (&s -> guard);  return (0);}int rtp_update_sr (rtp_source_t *member, vstr_t *p) {  rtcp_sr_t *sr = (rtcp_sr_t *) p -> head;  member -> lsr = sr -> rtp_ts;  return (0);}int rtp_update_rr (rtp_source_t *member, vstr_t *p) {  rtcp_report_t *rr = (rtcp_report_t *) p -> head;  struct timeval ts;  gettimeofday (&ts, NULL);  member -> rtt = (ts.tv_usec + ts.tv_sec * 1000000) - (rr -> lsr + rr -> dlsr);  member -> jitter = rr -> jitter;  return (0);}void rtp_update_sdes_item (char *data, int size, vstr_t *p, int *flag, int item) {  if (!(*flag & item)) {    *flag |= item;    vstr_get_head (p, data, size);  }  else    vstr_adv_head (p, size);  return;}int rtp_update_sdes (rtp_source_t *member, vstr_t *p) {  int flag = 0;  rtcp_sdes_item_t *item = (rtcp_sdes_item_t *) p -> head;  char *c;  int i = 0;  while (item -> type != RTCP_SDES_END) {    vstr_adv_head (p, sizeof(uint16_t));    switch (item -> type) {      case RTCP_SDES_CNAME:        rtp_update_sdes_item (member -> cname, item -> length, p, &flag, SDES_CNAME);        break;      case RTCP_SDES_NAME:        rtp_update_sdes_item (member -> name, item -> length, p, &flag, SDES_NAME);        break;      case RTCP_SDES_EMAIL:        rtp_update_sdes_item (member -> email, item -> length, p, &flag, SDES_EMAIL);        break;      case RTCP_SDES_PHONE:        rtp_update_sdes_item (member -> phone, item -> length, p, &flag, SDES_PHONE);        break;      case RTCP_SDES_LOC:        rtp_update_sdes_item (member -> loc, item -> length, p, &flag, SDES_LOC);        break;      case RTCP_SDES_TOOL:        rtp_update_sdes_item (member -> tool, item -> length, p, &flag, SDES_TOOL);        break;      case RTCP_SDES_NOTE:        rtp_update_sdes_item (member -> note, item -> length, p, &flag, SDES_NOTE);        break;    }    item = (rtcp_sdes_item_t *) p -> head;  }  /* discard trailling null bytes */  c = (char *) p -> head;  while (i++ < sizeof(uint32_t) && *c == '\0') {    vstr_adv_head (p, sizeof(uint8_t));    c = (char *) p -> head;  }  return (0);}void rtp_discard_sdes (vstr_t *p) {  rtcp_sdes_item_t *item = (rtcp_sdes_item_t *) p -> head;  char *c;  int i = 0;  while (item -> type != RTCP_SDES_END) {    vstr_adv_head (p, sizeof(uint16_t) + item -> length);    item = (rtcp_sdes_item_t *) p -> head;  }  /* discard trailling null bytes */  c = (char *) p -> head;  while (i++ < sizeof(uint32_t) && *c == '\0') {    vstr_adv_head (p, sizeof(uint8_t));    c = (char *) p -> head;  }  return;}/* Create a new RTP packet */void rtp_send (rtp_t *s, rtp_param_t *param, vstr_t *p) {  struct timeval ts;  rtp_packet_t *rtp_packet = (rtp_packet_t *) p -> data;  /* initialize RTP packet */  vstr_set (p, RTP_PACKET_IDX, RTP_PACKET_IDX);  /* get timestamp */  gettimeofday (&ts, NULL);  /* build the header in network byte order */  rtp_packet -> ver = RTP_VERSION;  rtp_packet -> p = (param -> flags & FLAG_PADDING) ? 1 : 0;  rtp_packet -> x = (param -> flags & FLAG_EXTENSION) ? 1 : 0;  rtp_packet -> m = (param -> flags & FLAG_MARKER) ? 1 : 0;  rtp_packet -> pt = param -> pt;  rtp_packet -> ssrc = htonl(s -> ssrc);  rtp_packet -> ts = htonl(ts.tv_usec + ts.tv_sec * 1000000);  vstr_adv_tail (p, RTP_HEADER_SIZE);  pthread_mutex_lock (&s -> guard);  rtp_packet -> seq = htons(s -> seq);  rtp_packet -> cc = s -> cc;  /* update sequence number and check new cycle */  if (++s -> seq == 0)    s -> cycles++;  /* update packet and octet counters */  s -> pcount++;  s -> ocount += p -> size;  /* checks for optional CSRC list */  if (s -> cc > 0)    vstr_put_tail (p, s -> csrc, s -> cc * sizeof(uint32_t));  pthread_mutex_unlock (&s -> guard);  /* checks for optional header extension */  if (rtp_packet -> x != 0) {    /* add optional header extension */    rtp_packet -> xdef = htons (param -> xdef);    rtp_packet -> xlen = htons (param -> xlen);    vstr_put_tail (p, &(rtp_packet -> xdef), 2 * sizeof(uint16_t));    if (rtp_packet -> xlen != 0) {      rtp_packet -> xhdr = (uint32_t *) p -> tail;      vstr_put_tail (p, param -> xhdr, param -> xlen * sizeof(uint32_t));    }  }  /* appends payload to packet */  rtp_packet -> payload = p -> tail;  vstr_put_tail (p, param -> payload, param -> len);  return;}/* Free a received RTP packet */void rtp_packet_free (rtp_packet_t *rtp_packet) {  free (rtp_packet);  return;}/* Updates jitter based on received packet */void rtp_update_jitter (rtp_source_t *r, uint32_t pkt_ts) {  long d;  long transit;  unsigned long arrival;  struct timeval ts;  /* interarrival jitter statistics */  gettimeofday (&ts, NULL);  arrival = ts.tv_usec + ts.tv_sec * 1000000;  transit = arrival - pkt_ts;  if (r -> transit == 0)    r -> transit = transit;  else {    d = transit - r -> transit;    r -> transit = transit;    /* absolute value */    if (d < 0)      d = -d;    r -> jitter += (1.0 / 16.0) * ((double) d - r -> jitter);  }  return;}/* Functions for packet queue */unsigned int _rtp_pqueue_hash (const void *key) {  return ((unsigned int)((rtp_packet_t *) key) -> seq);}int _rtp_pqueue_match (const void *key1, const void *key2) {  return (((rtp_packet_t *) key1) -> seq == ((rtp_packet_t *) key2) -> seq);}int _rtp_pqueue_solve (const void *key1, const void *key2) {  uint32_t current = ((rtp_packet_t *) key1) -> ts;  uint32_t next = ((rtp_packet_t *) key2) -> ts;  if (current < (uint32_t) -RTP_SOLVE_TIME)    return (next > current);  else    return (next + (uint32_t) RTP_SOLVE_TIME > current + (uint32_t) RTP_SOLVE_TIME);}/* New member */rtp_source_t *rtp_new_member (uint32_t ssrc) {  rtp_source_t *member;  member = (rtp_source_t *) alloc (sizeof(rtp_source_t));  member -> ssrc = ssrc;  pthread_mutex_init (&member -> guard, NULL);  member -> max_seq = 0;  member -> cycles = 0;  member -> received = 0;  member -> lost = 0;  member -> frac = 0;  member -> last_seq = 0;  member -> transit = 0;  member -> jitter = 0;  member -> lsr = 0;  member -> dlsr = 0;  member -> min_seq = 0;  member -> fail_count = 0;  member -> cname[0] = '\0';  member -> name[0] = '\0';  member -> email[0] = '\0';  member -> phone[0] = '\0';  member -> loc[0] = '\0';  member -> tool[0] = '\0';  member -> note[0] = '\0';  phtbl_init (&member -> pqueue, RTP_MAX_QUEUE, _rtp_pqueue_hash,        _rtp_pqueue_match, free, _rtp_pqueue_solve);  return (member);}/* Free member */void rtp_free_member (rtp_source_t *ptr) {  free (ptr);  return;}/* Find member in table */rtp_source_t *rtp_find_member (ohtbl_t *htbl, uint32_t ssrc) {  rtp_source_t get;  get.ssrc = ssrc;  return ((rtp_source_t *) ohtbl_lookup(htbl, &get));}/* Add member to table */int rtp_add_member (ohtbl_t *htbl, rtp_source_t *member) {  return (ohtbl_insert (htbl, member));}/* Remove member from table */rtp_source_t *rtp_remove_member (ohtbl_t *htbl, uint32_t ssrc) {  rtp_source_t remove;

⌨️ 快捷键说明

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