Removed files, reorganized code i.e. renamed write_or_die.c to xutils.c
[transsip.git] / src / transsip.c
blob171a1a916721cbfd7f7fd8c0c59d3b167ec7d9cb
1 /*
2 * transsip - the telephony network
3 * By Daniel Borkmann <daniel@transsip.org>
4 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
5 * Swiss federal institute of technology (ETH Zurich)
6 * Subject to the GPL, version 2.
7 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <pthread.h>
15 #include <signal.h>
16 #include <sys/types.h>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
20 #include <netdb.h>
21 #include <celt/celt.h>
22 #include <speex/speex_jitter.h>
23 #include <speex/speex_echo.h>
24 #include <sched.h>
26 #include "cli.h"
27 #include "conf.h"
28 #include "compiler.h"
29 #include "die.h"
30 #include "alsa.h"
31 #include "xmalloc.h"
33 #define MAX_MSG 1500
34 #define SAMPLING_RATE 48000
35 #define FRAME_SIZE 256
36 #define PACKETSIZE 43
37 #define CHANNELS 1
39 static pthread_t ptid;
41 static char *port = "30111";
42 static char *stun_server = "stunserver.org";
43 static char *alsadev = "plughw:0,0";
45 extern sig_atomic_t quit;
46 sig_atomic_t did_stun = 0;
47 static sig_atomic_t incoming_call = 0;
49 static struct pollfd *pfds = NULL;
50 static struct alsa_dev *dev = NULL;
51 static CELTEncoder *encoder = NULL;
52 static CELTDecoder *decoder = NULL;
53 static JitterBuffer *jitter = NULL;
54 static SpeexEchoState *echostate = NULL;
56 static void do_call_duplex(void)
58 #if 0
59 int ret, recv_started = 0;
61 alsa_start(dev);
62 while (likely(!quit)) {
63 ret = poll(pfds, nfds + 1, -1);
64 if (ret < 0)
65 panic("Poll returned with %d!\n", ret);
67 /* Received packets */
68 if (pfds[nfds].revents & POLLIN) {
69 n = recv(sd, msg, MAX_MSG, 0);
70 int recv_timestamp = ((int*) msg)[0];
72 JitterBufferPacket packet;
73 packet.data = msg + 4;
74 packet.len = n - 4;
75 packet.timestamp = recv_timestamp;
76 packet.span = FRAME_SIZE;
77 packet.sequence = 0;
79 jitter_buffer_put(jitter, &packet);
80 recv_started = 1;
83 /* Ready to play a frame (playback) */
84 if (alsa_play_ready(dev, pfds, nfds)) {
85 short pcm[FRAME_SIZE * CHANNELS];
86 if (recv_started) {
87 JitterBufferPacket packet;
88 /* Get audio from the jitter buffer */
89 packet.data = msg;
90 packet.len = MAX_MSG;
91 jitter_buffer_tick(jitter);
92 jitter_buffer_get(jitter, &packet, FRAME_SIZE,
93 NULL);
94 if (packet.len == 0)
95 packet.data=NULL;
96 celt_decode(dec_state, (const unsigned char *)
97 packet.data, packet.len, pcm);
98 } else {
99 for (i = 0; i < FRAME_SIZE * CHANNELS; ++i)
100 pcm[i] = 0;
103 /* Playback the audio and reset the echo canceller
104 if we got an underrun */
106 if (alsa_write(dev, pcm, FRAME_SIZE))
107 speex_echo_state_reset(echo_state);
108 /* Put frame into playback buffer */
109 speex_echo_playback(echo_state, pcm);
112 /* Audio available from the soundcard (capture) */
113 if (alsa_cap_ready(dev, pfds, nfds)) {
114 short pcm[FRAME_SIZE * CHANNELS],
115 pcm2[FRAME_SIZE * CHANNELS];
116 char outpacket[MAX_MSG];
118 alsa_read(dev, pcm, FRAME_SIZE);
120 /* Perform echo cancellation */
121 speex_echo_capture(echo_state, pcm, pcm2);
122 for (i = 0; i < FRAME_SIZE * CHANNELS; ++i)
123 pcm[i] = pcm2[i];
125 celt_encode(enc_state, pcm, NULL, (unsigned char *)
126 (outpacket + 4), PACKETSIZE);
128 /* Pseudo header: four null bytes and a 32-bit
129 timestamp */
130 ((int*)outpacket)[0] = send_timestamp;
131 send_timestamp += FRAME_SIZE;
133 rc = sendto(sd, outpacket, PACKETSIZE + 4, 0,
134 (struct sockaddr *) &remote_addr,
135 sizeof(remote_addr));
136 if (rc < 0)
137 panic("cannot send to socket");
140 #endif
143 void call_out(char *host, char *port)
145 /* send notify */
146 /* wait for accept */
147 /* transfer data */
149 printf("Trying to call %s:%s ...\n", host, port);
150 do_call_duplex();
153 void call_in(int take)
155 /* lookup addrbook */
156 /* send notify */
157 /* transfer data */
159 barrier();
160 if (incoming_call == 0) {
161 printf("No incoming call right now!\n");
162 return;
165 printf("Trying to take incoming call ...\n");
166 do_call_duplex();
169 static void *thread(void *null)
171 int sock = -1, ret, mtu, nfds, tmp;
172 struct addrinfo hints, *ahead, *ai;
173 CELTMode *mode;
175 while (did_stun == 0)
176 barrier();
178 memset(&hints, 0, sizeof(hints));
179 hints.ai_family = PF_UNSPEC;
180 hints.ai_socktype = SOCK_DGRAM;
181 hints.ai_protocol = IPPROTO_UDP;
182 hints.ai_flags = AI_PASSIVE;
184 ret = getaddrinfo(NULL, port, &hints, &ahead);
185 if (ret < 0)
186 panic("Cannot get address info!\n");
188 for (ai = ahead; ai != NULL && sock < 0; ai = ai->ai_next) {
189 sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
190 if (sock < 0)
191 continue;
192 if (ai->ai_family == AF_INET6) {
193 int one = 1;
194 #ifdef IPV6_V6ONLY
195 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
196 &one, sizeof(one));
197 if (ret < 0) {
198 close(sock);
199 sock = -1;
200 continue;
202 #else
203 close(sock);
204 sock = -1;
205 continue;
206 #endif /* IPV6_V6ONLY */
208 mtu = IP_PMTUDISC_DONT;
209 setsockopt(sock, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu));
210 ret = bind(sock, ai->ai_addr, ai->ai_addrlen);
211 if (ret < 0) {
212 close(sock);
213 sock = -1;
214 continue;
217 freeaddrinfo(ahead);
218 if (sock < 0)
219 panic("Cannot open socket!\n");
221 dev = alsa_open(alsadev, SAMPLING_RATE, CHANNELS, FRAME_SIZE);
222 if (!dev)
223 panic("Cannot open ALSA device %s!\n", alsadev);
225 mode = celt_mode_create(SAMPLING_RATE, FRAME_SIZE, NULL);
226 encoder = celt_encoder_create(mode, CHANNELS, NULL);
227 decoder = celt_decoder_create(mode, CHANNELS, NULL);
229 nfds = alsa_nfds(dev);
230 pfds = xmalloc(sizeof(*pfds) * (nfds + 1));
231 alsa_getfds(dev, pfds, nfds);
232 pfds[nfds].fd = sock;
233 pfds[nfds].events = POLLIN;
235 jitter = jitter_buffer_init(FRAME_SIZE);
236 tmp = FRAME_SIZE;
237 jitter_buffer_ctl(jitter, JITTER_BUFFER_SET_MARGIN, &tmp);
239 echostate = speex_echo_state_init(FRAME_SIZE, 10 * FRAME_SIZE);
240 tmp = SAMPLING_RATE;
241 speex_echo_ctl(echostate, SPEEX_ECHO_SET_SAMPLING_RATE, &tmp);
243 while (likely(!quit)) {
244 ret = poll(&pfds[nfds], 1, -1);
245 if (ret < 0)
246 panic("Poll returned with %d!\n", ret);
247 if (pfds[nfds].revents & POLLIN) {
248 /* Check for Auth pkt, if yes, set current caller and notifiy cli */
249 /* cli user must call take, that triggers call_in() */
250 printf(".\n");
254 xfree(pfds);
255 alsa_close(dev);
256 close(sock);
257 pthread_exit(0);
260 static void start_server(void)
262 int ret = pthread_create(&ptid, NULL, thread, NULL);
263 if (ret)
264 panic("Cannot create server thread!\n");
267 static void stop_server(void)
269 /* pthread_join(ptid, NULL);*/
272 int main(int argc, char **argv)
274 start_server();
275 enter_shell_loop();
276 stop_server();
277 return 0;
280 int get_port(void)
282 return atoi(port);
285 char *get_stun_server(void)
287 return stun_server;