00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stdint.h>
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <sys/time.h>
00028 #include <string.h>
00029 #include <unistd.h>
00030 #include <sys/param.h>
00031 #include <sys/socket.h>
00032 #include <netinet/in.h>
00033 #include <netinet/ip.h>
00034 #include <netinet/udp.h>
00035 #include <linux/if_ether.h>
00036
00037 #include <errno.h>
00038
00039 #include "str.h"
00040 #include "net_udp.h"
00041 #include "rtp.h"
00042
00043 #include <sys/types.h>
00044 #include <sys/uio.h>
00045 #include <unistd.h>
00046
00047 #define SECS_BETWEEN_1900_1970 2208988800u
00048 void ntp64_time(uint32_t * ntp_sec, uint32_t * ntp_frac)
00049 {
00050 struct timeval now;
00051 gettimeofday(&now, NULL);
00052
00053 *ntp_sec = now.tv_sec + SECS_BETWEEN_1900_1970;
00054 *ntp_frac =
00055 (now.tv_usec << 12) + (now.tv_usec << 8) -
00056 ((now.tv_usec * 3650) >> 6);
00057 }
00058
00059 static void init_rng(const int8_t *s)
00060 {
00061 static uint32_t seed;
00062 if (s == NULL) {
00063
00064 s = "ARANDOMSTRINGSOWEDONTCOREDUMP";
00065 }
00066 if (seed == 0) {
00067 pid_t p = getpid();
00068 while (*s) {
00069 seed += (uint32_t) * s++;
00070 seed = seed * 31 + 1;
00071 }
00072 seed = 1 + seed * 31 + (uint32_t) p;
00073 srand48(seed);
00074 }
00075 }
00076
00077 int32_t rtp_init(struct param *p)
00078 {
00079 static int8_t hname[MAXHOSTNAMELEN];
00080 int32_t res;
00081
00082 gethostname(hname, MAXHOSTNAMELEN);
00083 init_rng(hname);
00084
00085 if (p->dport % 2) {
00086 return -1;
00087 }
00088
00089 res = udp_init4(p);
00090
00091
00092 if (res != 0) {
00093 return -1;
00094 }
00095
00096 p->ip_id = 0;
00097 p->my_ssrc = (uint32_t) lrand48();
00098 p->rtp_seq = (uint16_t) lrand48();
00099
00100 return 0;
00101 }
00102
00103
00104
00105
00106
00107
00108 uint16_t
00109 in_chksum(const uint16_t *addr, register uint32_t len)
00110 {
00111 int32_t nleft = len;
00112 const uint16_t *w = addr;
00113 uint16_t answer;
00114 int32_t sum = 0;
00115
00116 while (nleft > 1) {
00117 sum += *w++;
00118 nleft -= 2;
00119 }
00120
00121 if (nleft == 1)
00122 sum += htons(*(uint8_t *)w<<8);
00123
00124 sum = (sum >> 16) + (sum & 0xffff);
00125 sum += (sum >> 16);
00126 answer = ~sum;
00127
00128 return (answer);
00129 }
00130
00131
00132 #define SOURCE_UDP_PORT 20020
00133 int
00134 rtp_send_data(struct param *p, uint32_t rtp_ts, int8_t pt, int32_t m, int8_t *data, int32_t data_len, unsigned char *h_buf, int h_offset, int h_len) {
00135 int32_t buffer_len, rc;
00136 int8_t *buffer = data;
00137 rtp_packet *packet;
00138
00139 struct iphdr *iph;
00140 struct udphdr *udph;
00141
00142
00143
00144
00145 buffer_len = data_len + RTP_HEADER_SIZE;
00146
00147
00148 unsigned char *h_ptr = h_buf;
00149 h_ptr += h_offset;
00150
00151
00152 h_ptr -= sizeof(rtp_packet);
00153 h_len += sizeof(rtp_packet);
00154 packet = (rtp_packet *)((void *)h_ptr);
00155
00156
00157
00158 packet->v = 2;
00159 packet->p = 0;
00160 packet->x = 0;
00161 packet->cc = 0;
00162 packet->m = m;
00163 packet->pt = pt;
00164 packet->seq = htons(p->rtp_seq++);
00165 packet->ts = htonl(rtp_ts);
00166 packet->ssrc = htonl(p->my_ssrc);
00167
00168 if(p->raw) {
00169 buffer_len += 8;
00170 h_ptr -= sizeof(struct udphdr);
00171 h_len += sizeof(struct udphdr);
00172 udph = (struct udphdr *)h_ptr;
00173 udph->len = htons(sizeof(struct udphdr) + buffer_len);
00174
00175 udph->check = 0;
00176 udph->dest = htons(p->dport);
00177 udph->source = htons(SOURCE_UDP_PORT);
00178
00179 h_ptr -= sizeof(struct iphdr);
00180 h_len += sizeof(struct iphdr);
00181 iph = (struct iphdr *)h_ptr;
00182 iph->version = 4;
00183 iph->ihl = 5;
00184 iph->tos = 0;
00185 iph->tot_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + buffer_len);
00186
00187 iph->id = htons((uint16_t) p->ip_id);
00188 iph->frag_off = htons(IP_DF);
00189 iph->ttl = (uint8_t) p->ttl;
00190 iph->protocol = IPPROTO_UDP;
00191 iph->saddr = p->src_addr4.s_addr;
00192 iph->daddr = (int)p->dst_addr4.s_addr;
00193 iph->check = 0;
00194 iph->check = in_chksum((uint16_t *) iph, iph->ihl << 2);
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 }
00216
00217 struct iovec iov[2];
00218 int iovcnt = sizeof(iov) / sizeof(struct iovec);
00219
00220 iov[0].iov_base = h_ptr;
00221 iov[0].iov_len = h_len;
00222
00223 iov[1].iov_base = buffer;
00224 iov[1].iov_len = data_len;
00225
00226 if(!p->raw) {
00227 rc = writev(p->fd_udp, iov, iovcnt);
00228 } else {
00229
00230 p->msg.msg_iov = iov;
00231 p->msg.msg_iovlen = iovcnt;
00232
00233
00234
00235
00236 rc = sendmsg(p->fd_raw, &p->msg, 0);
00237 p->ip_id++;
00238 }
00239 return rc;
00240 }
00241
00242
00243 void rtp_done(struct param * p) {
00244 udp_exit4(p);
00245 }
00246
00247
00248 int32_t ismulticast(struct param *p) {
00249 if(IN_MULTICAST(ntohl(p->dst_addr4.s_addr)))
00250 return 1;
00251 return 0;
00252 }
00253