Version 0.1.12 from FTP
[asterisk/asterisk.git] / rtp.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Real-time Protocol Support
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <pthread.h>
17 #include <string.h>
18 #include <sys/time.h>
19 #include <signal.h>
20 #include <errno.h>
21 #include <unistd.h>
22 #include <netinet/in.h>
23 #include <sys/time.h>
24 #include <sys/socket.h>
25 #include <arpa/inet.h>
26 #include <fcntl.h>
27
28 #include <asterisk/rtp.h>
29 #include <asterisk/logger.h>
30 #include <asterisk/options.h>
31 #include <asterisk/channel.h>
32
33 static int dtmftimeout = 300;   /* 300 samples */
34
35 struct ast_rtp {
36         int s;
37         char resp;
38         struct ast_frame f;
39         unsigned char rawdata[1024 + AST_FRIENDLY_OFFSET];
40         unsigned int ssrc;
41         unsigned int lastts;
42         unsigned int lastrxts;
43         int dtmfcount;
44         struct sockaddr_in us;
45         struct sockaddr_in them;
46         struct timeval rxcore;
47         struct timeval txcore;
48         int *ioid;
49         unsigned short seqno;
50         struct sched_context *sched;
51         struct io_context *io;
52         void *data;
53         ast_rtp_callback callback;
54 };
55
56
57 void ast_rtp_set_data(struct ast_rtp *rtp, void *data)
58 {
59         rtp->data = data;
60 }
61
62 void ast_rtp_set_callback(struct ast_rtp *rtp, ast_rtp_callback callback)
63 {
64         rtp->callback = callback;
65 }
66
67 static void send_dtmf(struct ast_rtp *rtp)
68 {
69         printf("Sending dtmf: %d (%c)\n", rtp->resp, rtp->resp);
70         rtp->f.frametype = AST_FRAME_DTMF;
71         rtp->f.subclass = rtp->resp;
72         rtp->f.datalen = 0;
73         rtp->f.timelen = 0;
74         rtp->f.mallocd = 0;
75         rtp->f.src = "RTP";
76         rtp->resp = 0;
77         if (rtp->callback)
78                 rtp->callback(rtp, &rtp->f, rtp->data);
79         
80 }
81
82 static void process_rfc2833(struct ast_rtp *rtp, unsigned char *data, int len)
83 {
84         unsigned int event;
85         char resp = 0;
86         event = ntohl(*((unsigned int *)(data)));
87         event >>= 24;
88 #if 0
89         printf("Event: %08x (len = %d)\n", event, len);
90 #endif  
91         if (event < 10) {
92                 resp = '0' + event;
93         } else if (event < 11) {
94                 resp = '*';
95         } else if (event < 12) {
96                 resp = '#';
97         } else if (event < 16) {
98                 resp = 'A' + (event - 12);
99         }
100         if (rtp->resp && (rtp->resp != resp)) {
101                 send_dtmf(rtp);
102         }
103         rtp->resp = resp;
104         rtp->dtmfcount = dtmftimeout;
105 }
106
107 static int rtpread(int *id, int fd, short events, void *cbdata)
108 {
109         struct ast_rtp *rtp = cbdata;
110         int res;
111         struct sockaddr_in sin;
112         int len;
113         unsigned int seqno;
114         int payloadtype;
115         int hdrlen = 12;
116         unsigned int timestamp;
117         
118         unsigned int *rtpheader;
119         
120         len = sizeof(sin);
121         
122         res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
123                                         0, (struct sockaddr *)&sin, &len);
124
125         rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
126         if (res < 0) {
127                 ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
128                 if (errno == EBADF)
129                         CRASH;
130                 return 1;
131         }
132         if (res < hdrlen) {
133                 ast_log(LOG_WARNING, "RTP Read too short\n");
134                 return 1;
135         }
136         /* Get fields */
137         seqno = ntohl(rtpheader[0]);
138         payloadtype = (seqno & 0x7f0000) >> 16;
139         seqno &= 0xffff;
140         timestamp = ntohl(rtpheader[1]);
141 #if 0
142         printf("Got RTP packet from %s:%d (type %d, seq %d, ts %d, len = %d)\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
143 #endif  
144         rtp->f.frametype = AST_FRAME_VOICE;
145         rtp->f.subclass = rtp2ast(payloadtype);
146         if (rtp->f.subclass < 0) {
147                 if (payloadtype == 101) {
148                         /* It's special -- rfc2833 process it */
149                         process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
150                 } else
151                         ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", payloadtype);
152                 return 1;
153         }
154
155         if (!rtp->lastrxts)
156                 rtp->lastrxts = timestamp;
157
158         if (rtp->dtmfcount) {
159 #if 0
160                 printf("dtmfcount was %d\n", rtp->dtmfcount);
161 #endif          
162                 rtp->dtmfcount -= (timestamp - rtp->lastrxts);
163                 if (rtp->dtmfcount < 0)
164                         rtp->dtmfcount = 0;
165 #if 0
166                 if (dtmftimeout != rtp->dtmfcount)
167                         printf("dtmfcount is %d\n", rtp->dtmfcount);
168 #endif
169         }
170         rtp->lastrxts = timestamp;
171
172         /* Send any pending DTMF */
173         if (rtp->resp && !rtp->dtmfcount) {
174                 send_dtmf(rtp);
175                 /* Setup the voice frame again */
176                 rtp->f.frametype = AST_FRAME_VOICE;
177                 rtp->f.subclass = rtp2ast(payloadtype);
178         }
179         rtp->f.mallocd = 0;
180         rtp->f.datalen = res - hdrlen;
181         rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
182         rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
183         switch(rtp->f.subclass) {
184         case AST_FORMAT_ULAW:
185         case AST_FORMAT_ALAW:
186                 rtp->f.timelen = rtp->f.datalen / 8;
187                 break;
188         case AST_FORMAT_SLINEAR:
189                 rtp->f.timelen = rtp->f.datalen / 16;
190                 break;
191         case AST_FORMAT_GSM:
192                 rtp->f.timelen = 20 * (rtp->f.datalen / 33);
193                 break;
194         case AST_FORMAT_ADPCM:
195                 rtp->f.timelen = rtp->f.datalen / 8;
196                 break;
197         default:
198                 ast_log(LOG_NOTICE, "Unable to calculate timelen for format %d\n", rtp->f.subclass);
199                 break;
200         }
201         rtp->f.src = "RTP";
202         if (rtp->callback)
203                 rtp->callback(rtp, &rtp->f, rtp->data);
204         return 1;
205 }
206
207 static struct {
208         int rtp;
209         int ast;
210 } cmap[] = {
211         { 0, AST_FORMAT_ULAW },
212         { 3, AST_FORMAT_GSM },
213         { 4, AST_FORMAT_G723_1 },
214         { 5, AST_FORMAT_ADPCM },
215         { 8, AST_FORMAT_ALAW },
216         { 18, AST_FORMAT_G729A },
217 };
218
219 int rtp2ast(int id)
220 {
221         int x;
222         for (x=0;x<sizeof(cmap) / sizeof(cmap[0]); x++) {
223                 if (cmap[x].rtp == id)
224                         return cmap[x].ast;
225         }
226         return -1;
227 }
228
229 int ast2rtp(int id)
230 {
231         int x;
232         for (x=0;x<sizeof(cmap) / sizeof(cmap[0]); x++) {
233                 if (cmap[x].ast == id)
234                         return cmap[x].rtp;
235         }
236         return -1;
237 }
238
239 struct ast_rtp *ast_rtp_new(struct sched_context *sched, struct io_context *io)
240 {
241         struct ast_rtp *rtp;
242         int x;
243         int flags;
244         rtp = malloc(sizeof(struct ast_rtp));
245         if (!rtp)
246                 return NULL;
247         memset(rtp, 0, sizeof(struct ast_rtp));
248         rtp->them.sin_family = AF_INET;
249         rtp->us.sin_family = AF_INET;
250         rtp->s = socket(AF_INET, SOCK_DGRAM, 0);
251         rtp->ssrc = rand();
252         rtp->seqno = rand() & 0xffff;
253         if (rtp->s < 0) {
254                 free(rtp);
255                 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
256                 return NULL;
257         }
258         flags = fcntl(rtp->s, F_GETFL);
259         fcntl(rtp->s, F_SETFL, flags | O_NONBLOCK);
260         for (;;) {
261                 /* Find us a place */
262                 x = (rand() % (65000-1025)) + 1025;
263                 /* Must be an even port number by RTP spec */
264                 x = x & ~1;
265                 rtp->us.sin_port = htons(x);
266                 if (!bind(rtp->s, &rtp->us, sizeof(rtp->us)))
267                         break;
268                 if (errno != EADDRINUSE) {
269                         ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno));
270                         close(rtp->s);
271                         free(rtp);
272                         return NULL;
273                 }
274         }
275         rtp->io = io;
276         rtp->sched = sched;
277         rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
278         return rtp;
279 }
280
281 void ast_rtp_set_peer(struct ast_rtp *rtp, struct sockaddr_in *them)
282 {
283         rtp->them.sin_port = them->sin_port;
284         rtp->them.sin_addr = them->sin_addr;
285 }
286
287 void ast_rtp_get_us(struct ast_rtp *rtp, struct sockaddr_in *us)
288 {
289         memcpy(us, &rtp->us, sizeof(rtp->us));
290 }
291
292 void ast_rtp_destroy(struct ast_rtp *rtp)
293 {
294         if (rtp->ioid)
295                 ast_io_remove(rtp->io, rtp->ioid);
296         if (rtp->s > -1)
297                 close(rtp->s);
298         free(rtp);
299 }
300
301 static unsigned int calc_txstamp(struct ast_rtp *rtp)
302 {
303         struct timeval now;
304         unsigned int ms;
305         if (!rtp->txcore.tv_sec && !rtp->txcore.tv_usec) {
306                 gettimeofday(&rtp->txcore, NULL);
307         }
308         gettimeofday(&now, NULL);
309         ms = (now.tv_sec - rtp->txcore.tv_sec) * 1000;
310         ms += (now.tv_usec - rtp->txcore.tv_usec);
311         return ms;
312 }
313
314 int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *_f)
315 {
316         int hdrlen = 12;
317         struct ast_frame *f;
318         int codec;
319         int res;
320         unsigned int ms;
321         unsigned int *rtpheader;
322         
323         /* Make sure we have enough space for RTP header */
324         
325         if (_f->frametype != AST_FRAME_VOICE) {
326                 ast_log(LOG_WARNING, "RTP can only send voice\n");
327                 return -1;
328         }
329
330         codec = ast2rtp(_f->subclass);
331         if (codec < 0) {
332                 ast_log(LOG_WARNING, "Don't know how to send format %d packets with RTP\n", _f->subclass);
333                 return -1;
334         }
335
336         if (_f->offset < hdrlen) {
337                 f = ast_frdup(_f);
338         } else
339                 f = _f;
340                 
341         ms = calc_txstamp(rtp) * 8;
342         switch(f->subclass) {
343         case AST_FORMAT_ULAW:
344         case AST_FORMAT_ALAW:
345                 break;
346         default:
347                 ast_log(LOG_WARNING, "Not sure about timestamp format for codec format %d\n", f->subclass);
348         }
349         rtp->lastts += f->datalen;
350         /* Get a pointer to the header */
351         rtpheader = (unsigned int *)(f->data - hdrlen);
352         rtpheader[0] = htonl((2 << 30) | (codec << 16) | (rtp->seqno++));
353         rtpheader[1] = htonl(rtp->lastts);
354         rtpheader[2] = htonl(rtp->ssrc); 
355         if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
356                 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, &rtp->them, sizeof(rtp->them));
357                 if (res <0) 
358                         ast_log(LOG_NOTICE, "RTP Transmission error to %s:%d: %s\n", inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
359 #if 0
360                 printf("Sent %d bytes of RTP data to %s:%d\n", res, inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
361 #endif          
362         }
363         return 0;
364 }