2
|
1 /* rtp.cpp
|
|
2 *
|
|
3 * Copyright (C) DFS Deutsche Flugsicherung (2004, 2005).
|
|
4 * All Rights Reserved.
|
|
5 * Author: Andre Adrian
|
|
6 *
|
|
7 * subset of Real Time Protocol Version 2 (RFC3550)
|
|
8 * handling of extension and padding is missing
|
|
9 *
|
|
10 * Version 0.3
|
|
11 */
|
|
12
|
|
13 #include <stdio.h> /* printf() */
|
|
14 #include <stdlib.h>
|
|
15
|
|
16 #include <sys/types.h> /* u_long */
|
|
17 #include <sys/time.h> /* gettimeofday() */
|
|
18 #include <unistd.h> /* get..() */
|
|
19 #include <time.h> /* clock() */
|
|
20 #include <sys/utsname.h> /* uname() */
|
|
21 #include <netinet/in.h>
|
|
22 #include <assert.h>
|
|
23
|
|
24 #include "intercomd.h"
|
|
25 #include "rtp.h"
|
|
26
|
|
27 /*
|
|
28 * Return random unsigned 32-bit quantity. Use 'type' argument if
|
|
29 * you need to generate several different values in close succession.
|
|
30 * (partly from RFC 3550 A.6 Generating a Random 32-bit Identifier)
|
|
31 */
|
|
32 unsigned long random32(int type)
|
|
33 {
|
|
34 struct {
|
|
35 int type;
|
|
36 struct timeval tv;
|
|
37 clock_t cpu;
|
|
38 pid_t pid;
|
|
39 u_long hid;
|
|
40 uid_t uid;
|
|
41 gid_t gid;
|
|
42 struct utsname name;
|
|
43 } s;
|
|
44
|
|
45 gettimeofday(&s.tv, 0);
|
|
46 uname(&s.name);
|
|
47 s.type = type;
|
|
48 s.cpu = clock();
|
|
49 s.pid = getpid();
|
|
50 s.hid = gethostid();
|
|
51 s.uid = getuid();
|
|
52 s.gid = getgid();
|
|
53 /* also: system uptime */
|
|
54
|
|
55 unsigned long *us = (unsigned long *) &s;
|
|
56
|
|
57 /* use xor to make a (bad) random */
|
|
58 /* Note: remainder of long div of 32bit prim is better */
|
|
59 unsigned long random = 0;
|
|
60 unsigned int i;
|
|
61 for (i = 0; i < sizeof(s) / sizeof(long); ++i) {
|
|
62 random ^= *us++;
|
|
63 }
|
|
64 return random;
|
|
65 } /* random32 */
|
|
66
|
|
67
|
|
68 RTP::RTP()
|
|
69 {
|
|
70 version = 2;
|
|
71 padding = 0;
|
|
72 extension = 0;
|
|
73 csrc_count = 0;
|
|
74 marker = 0;
|
|
75 payload_type = PT_PCMU;
|
|
76 ssrc = 0;
|
|
77 sequence = 0;
|
|
78 timestamp = 0;
|
|
79 }
|
|
80
|
|
81 void RTP::init(int payload_type_, unsigned long ssrc_)
|
|
82 {
|
|
83 version = 2;
|
|
84 padding = 0;
|
|
85 extension = 0;
|
|
86 csrc_count = 0;
|
|
87 marker = 0;
|
|
88 payload_type = payload_type_;
|
|
89 ssrc = ssrc_;
|
|
90 /* My interpretation of RFC3550 A.6: one seed is good enough */
|
|
91 sequence = random32(payload_type_);
|
|
92 timestamp = sequence;
|
|
93 }
|
|
94
|
|
95 void RTP::next(int frameduration)
|
|
96 {
|
|
97 ++sequence;
|
|
98 timestamp += frameduration;
|
|
99 }
|
|
100
|
|
101 void RTP::reset_csrc()
|
|
102 {
|
|
103 csrc_count = 0;
|
|
104 }
|
|
105
|
|
106 int RTP::add_csrc(unsigned long csrc_)
|
|
107 {
|
|
108 return_if (csrc_count >= 15, ERROR);
|
|
109 csrc[csrc_count++] = csrc_;
|
|
110
|
|
111 // printf("add_csrc = %08x\n", csrc_);
|
|
112 return OKAY;
|
|
113 }
|
|
114
|
|
115 int RTP::find_csrc(unsigned long ssrc_)
|
|
116 {
|
|
117 unsigned int i;
|
|
118
|
|
119 if (0 == csrc_count) return NO;
|
|
120 // printf("find_csrc = %08x ", ssrc_);
|
|
121 for (i = 0; i < csrc_count; ++i) {
|
|
122 // printf("%08x ", csrc[i]);
|
|
123 if (csrc[i] == ssrc_) {
|
|
124 // printf("hit\n");
|
|
125 return YES;
|
|
126 }
|
|
127 }
|
|
128 return NO;
|
|
129 }
|
|
130
|
|
131 int RTP::check()
|
|
132 {
|
|
133 // RFC3550 A.1 RTP Data Header Validity Checks
|
|
134
|
|
135 // RTP version field must equal 2.
|
|
136 if (version != 2)
|
|
137 return -1;
|
|
138
|
|
139 // The payload type must be known
|
|
140 switch (payload_type) {
|
|
141 case PT_PCMU:
|
|
142 case PT_GSM:
|
|
143 case PT_PCMA:
|
|
144 case PT_G729:
|
|
145 case PT_iLBC:
|
|
146 case PT_EFR:
|
|
147 case PT_G726:
|
|
148 case PT_SPX:
|
|
149 /* do nothing */
|
|
150 break;
|
|
151 default:
|
|
152 return -1;
|
|
153 }
|
|
154
|
|
155 // The X bit must be zero if the profile does not specify that the
|
|
156 // header extension mechanism may be used. Otherwise, the extension
|
|
157 // length field must be less than the total packet size minus the
|
|
158 // fixed header length and padding.
|
|
159 if (extension)
|
|
160 return -1; // hack!
|
|
161
|
|
162 // The length of the packet must be consistent with CC and payload
|
|
163 // type (if payloads have a known length).
|
|
164 // equal to SR or RR.
|
|
165 // if (csrc_count != 0)
|
|
166 // return -1; // hack!
|
|
167
|
|
168 // If the P bit is set, then the last octet of the packet must
|
|
169 // contain a valid octet count, in particular, less than the total
|
|
170 // packet length minus the header size.
|
|
171 if (padding)
|
|
172 return -1; // hack!
|
|
173 return 0;
|
|
174 }
|
|
175
|
|
176 char *RTP_network_copy(char *to, RTP * from)
|
|
177 {
|
|
178 unsigned long *ulfrom = (unsigned long *) from;
|
|
179 unsigned long *ulto = (unsigned long *) to;
|
|
180 int i;
|
|
181 for (i = 0; i < 3 + from->get_cc(); ++i) {
|
|
182 *ulto++ = htonl(*ulfrom++);
|
|
183 }
|
|
184 return (char *) ulto;
|
|
185 }
|
|
186
|
|
187 char *RTP_host_copy(RTP * to, char *from)
|
|
188 {
|
|
189 unsigned long *ulfrom = (unsigned long *) from;
|
|
190 unsigned long *ulto = (unsigned long *) to;
|
|
191 int i;
|
|
192 for (i = 0; i < 3; ++i) {
|
|
193 *ulto++ = ntohl(*ulfrom++);
|
|
194 }
|
|
195 for (i = 0; i < to->get_cc(); ++i) {
|
|
196 *ulto++ = ntohl(*ulfrom++);
|
|
197 }
|
|
198 return (char *) ulfrom;
|
|
199 }
|