1386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
2386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * rtp.c
3386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
4386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * library functions for the real-time transport protocol
5386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
6386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * David A. McGrew
7386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * Cisco Systems, Inc.
8386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
9386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
10386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
11386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include "rtp_priv.h"
12386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
13386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include <stdio.h>
14386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include <string.h>
15386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
16386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include <sys/types.h>
17386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#ifdef HAVE_SYS_SOCKET_H
18386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari# include <sys/socket.h>
19386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
20386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
21386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#define PRINT_DEBUG    0    /* set to 1 to print out debugging data */
22386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#define VERBOSE_DEBUG  0    /* set to 1 to print out more data      */
23386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
24386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariunsigned int
25386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarirtp_sendto(rtp_sender_t sender, const void* msg, int len) {
26386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int octets_sent;
27386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t stat;
28386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int pkt_len = len + RTP_HEADER_LEN;
29386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
30386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* marshal data */
31386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  strncpy(sender->message.body, msg, len);
32386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
33386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* update header */
34386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  sender->message.header.seq = ntohs(sender->message.header.seq) + 1;
35386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  sender->message.header.seq = htons(sender->message.header.seq);
36386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  sender->message.header.ts = ntohl(sender->message.header.ts) + 1;
37386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  sender->message.header.ts = htonl(sender->message.header.ts);
38386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
39386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* apply srtp */
40386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  stat = srtp_protect(sender->srtp_ctx, &sender->message.header, &pkt_len);
41386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stat) {
42386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#if PRINT_DEBUG
43386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    fprintf(stderr, "error: srtp protection failed with code %d\n", stat);
44386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
45386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return -1;
46386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
47386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#if VERBOSE_DEBUG
48386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_print_packet(&sender->message.header, pkt_len);
49386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
50386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  octets_sent = sendto(sender->socket, (void*)&sender->message,
51386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		       pkt_len, 0, (struct sockaddr *)&sender->addr,
52386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		       sizeof (struct sockaddr_in));
53386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
54386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (octets_sent != pkt_len) {
55386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#if PRINT_DEBUG
56386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    fprintf(stderr, "error: couldn't send message %s", (char *)msg);
57386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    perror("");
58386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
59386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
60386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
61386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return octets_sent;
62386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
63386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
64386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariunsigned int
65386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarirtp_recvfrom(rtp_receiver_t receiver, void *msg, int *len) {
66386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int octets_recvd;
67386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t stat;
68386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
69386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  octets_recvd = recvfrom(receiver->socket, (void *)&receiver->message,
70386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			 *len, 0, (struct sockaddr *) NULL, 0);
71386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
72386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* verify rtp header */
73386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (receiver->message.header.version != 2) {
74386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    *len = 0;
75386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return -1;
76386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
77386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
78386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#if PRINT_DEBUG
79386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  fprintf(stderr, "%d octets received from SSRC %u\n",
80386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	  octets_recvd, receiver->message.header.ssrc);
81386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
82386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#if VERBOSE_DEBUG
83386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_print_packet(&receiver->message.header, octets_recvd);
84386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
85386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
86386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* apply srtp */
87386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  stat = srtp_unprotect(receiver->srtp_ctx,
88386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			&receiver->message.header, &octets_recvd);
89386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stat) {
90386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    fprintf(stderr,
91386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	    "error: srtp unprotection failed with code %d%s\n", stat,
92386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	    stat == err_status_replay_fail ? " (replay check failed)" :
93386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	    stat == err_status_auth_fail ? " (auth check failed)" : "");
94386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return -1;
95386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
96386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  strncpy(msg, receiver->message.body, octets_recvd);
97386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
98386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return octets_recvd;
99386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
100386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
101386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariint
102386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarirtp_sender_init(rtp_sender_t sender,
103386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		int socket,
104386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		struct sockaddr_in addr,
105386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		unsigned int ssrc) {
106386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
107386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* set header values */
108386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  sender->message.header.ssrc    = htonl(ssrc);
109386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  sender->message.header.ts      = 0;
110386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  sender->message.header.seq     = (uint16_t) rand();
111386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  sender->message.header.m       = 0;
112386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  sender->message.header.pt      = 0x1;
113386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  sender->message.header.version = 2;
114386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  sender->message.header.p       = 0;
115386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  sender->message.header.x       = 0;
116386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  sender->message.header.cc      = 0;
117386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
118386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* set other stuff */
119386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  sender->socket = socket;
120386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  sender->addr = addr;
121386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
122386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return 0;
123386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
124386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
125386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariint
126386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarirtp_receiver_init(rtp_receiver_t rcvr,
127386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		  int socket,
128386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		  struct sockaddr_in addr,
129386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		  unsigned int ssrc) {
130386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
131386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* set header values */
132386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  rcvr->message.header.ssrc    = htonl(ssrc);
133386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  rcvr->message.header.ts      = 0;
134386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  rcvr->message.header.seq     = 0;
135386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  rcvr->message.header.m       = 0;
136386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  rcvr->message.header.pt      = 0x1;
137386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  rcvr->message.header.version = 2;
138386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  rcvr->message.header.p       = 0;
139386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  rcvr->message.header.x       = 0;
140386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  rcvr->message.header.cc      = 0;
141386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
142386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* set other stuff */
143386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  rcvr->socket = socket;
144386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  rcvr->addr = addr;
145386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
146386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return 0;
147386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
148386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
149386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariint
150386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarirtp_sender_init_srtp(rtp_sender_t sender, const srtp_policy_t *policy) {
151386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return srtp_create(&sender->srtp_ctx, policy);
152386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
153386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
154386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariint
155386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarirtp_receiver_init_srtp(rtp_receiver_t sender, const srtp_policy_t *policy) {
156386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return srtp_create(&sender->srtp_ctx, policy);
157386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
158386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
159386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarirtp_sender_t
160386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarirtp_sender_alloc() {
161386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return (rtp_sender_t)malloc(sizeof(rtp_sender_ctx_t));
162386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
163386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
164386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarirtp_receiver_t
165386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarirtp_receiver_alloc() {
166386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return (rtp_receiver_t)malloc(sizeof(rtp_receiver_ctx_t));
167386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
168