Help and version params, since only three possible cmdline args, we check them manually
[transsip.git] / src / transsip.c
blob5fdb0aa785e3c58d5758c09ff0667d21e896481b
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 <sys/stat.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
21 #include <netdb.h>
22 #include <celt/celt.h>
23 #include <sys/ptrace.h>
24 #include <speex/speex_jitter.h>
25 #include <speex/speex_echo.h>
26 #include <sched.h>
28 #include "conf.h"
29 #include "version.h"
30 #include "curve.h"
31 #include "compiler.h"
32 #include "die.h"
33 #include "alsa.h"
34 #include "xmalloc.h"
35 #include "xutils.h"
36 #include "crypto_verify_32.h"
37 #include "crypto_box_curve25519xsalsa20poly1305.h"
38 #include "crypto_scalarmult_curve25519.h"
39 #include "crypto_auth_hmacsha512256.h"
41 noinline void *memset(void *__s, int __c, size_t __n);
42 extern void enter_shell_loop(void);
43 int show_key_export(char *home);
45 #define MAX_MSG 1500
46 #define SAMPLING_RATE 48000
47 #define FRAME_SIZE 256
48 #define PACKETSIZE 43
49 #define CHANNELS 1
51 static pthread_t ptid;
53 static char *port = "30111";
54 static char *stun_server = "stunserver.org";
55 static char *alsadev = "plughw:0,0";
57 extern sig_atomic_t quit;
58 sig_atomic_t did_stun = 0;
59 static sig_atomic_t incoming_call = 0;
61 static struct pollfd *pfds = NULL;
62 static struct alsa_dev *dev = NULL;
63 static CELTEncoder *encoder = NULL;
64 static CELTDecoder *decoder = NULL;
65 static JitterBuffer *jitter = NULL;
66 static SpeexEchoState *echostate = NULL;
68 static void check_file_or_die(char *home, char *file, int maybeempty)
70 char path[PATH_MAX];
71 struct stat st;
72 memset(path, 0, sizeof(path));
73 slprintf(path, sizeof(path), "%s/%s", home, file);
74 if (stat(path, &st))
75 panic("No such file %s! Type --keygen to generate initial config!\n",
76 path);
77 if (!S_ISREG(st.st_mode))
78 panic("%s is not a regular file!\n", path);
79 if ((st.st_mode & ~S_IFREG) != (S_IRUSR | S_IWUSR))
80 panic("You have set too many permissions on %s (%o)!\n",
81 path, st.st_mode);
82 if (maybeempty == 0 && st.st_size == 0)
83 panic("%s is empty!\n", path);
86 static void check_config_exists_or_die(char *home)
88 if (!home)
89 panic("No home dir specified!\n");
90 check_file_or_die(home, FILE_CONTACTS, 1);
91 check_file_or_die(home, FILE_SETTINGS, 0);
92 check_file_or_die(home, FILE_PRIVKEY, 0);
93 check_file_or_die(home, FILE_PUBKEY, 0);
94 check_file_or_die(home, FILE_USERNAME, 0);
97 static char *fetch_home_dir(void)
99 char *home = getenv("HOME");
100 if (!home)
101 panic("No HOME defined!\n");
102 return home;
105 static void write_username(char *home)
107 int fd, ret;
108 char path[PATH_MAX], *eof;
109 char user[512];
110 memset(path, 0, sizeof(path));
111 slprintf(path, sizeof(path), "%s/%s", home, FILE_USERNAME);
112 printf("Username: [%s] ", getenv("USER"));
113 fflush(stdout);
114 memset(user, 0, sizeof(user));
115 eof = fgets(user, sizeof(user), stdin);
116 user[sizeof(user) - 1] = 0;
117 user[strlen(user) - 1] = 0; /* omit last \n */
118 if (strlen(user) == 0)
119 strlcpy(user, getenv("USER"), sizeof(user));
120 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
121 if (fd < 0)
122 panic("Cannot open your username file!\n");
123 ret = write(fd, user, strlen(user));
124 if (ret != strlen(user))
125 panic("Could not write username!\n");
126 close(fd);
127 info("Username written to %s!\n", path);
130 static void create_transsipdir(char *home)
132 int ret, fd;
133 char path[PATH_MAX];
134 memset(path, 0, sizeof(path));
135 slprintf(path, sizeof(path), "%s/%s", home, ".transsip/");
136 errno = 0;
137 ret = mkdir(path, S_IRWXU);
138 if (ret < 0 && errno != EEXIST)
139 panic("Cannot create transsip dir!\n");
140 info("transsip directory %s created!\n", path);
141 /* We also create empty files for contacts and settings! */
142 memset(path, 0, sizeof(path));
143 slprintf(path, sizeof(path), "%s/%s", home, FILE_CONTACTS);
144 fd = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
145 if (fd < 0)
146 panic("Cannot open contacts file!\n");
147 close(fd);
148 info("Empty contacts file written to %s!\n", path);
149 memset(path, 0, sizeof(path));
150 slprintf(path, sizeof(path), "%s/%s", home, FILE_SETTINGS);
151 fd = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
152 if (fd < 0)
153 panic("Cannot open settings file!\n");
154 close(fd);
155 info("Empty settings file written to %s!\n", path);
158 static void create_keypair(char *home)
160 int fd;
161 ssize_t ret;
162 unsigned char publickey[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES] = { 0 };
163 unsigned char secretkey[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES] = { 0 };
164 char path[PATH_MAX];
165 const char * errstr = NULL;
166 int err = 0;
167 info("Reading from %s (this may take a while) ...\n", ENTROPY_SOURCE);
168 fd = open_or_die(ENTROPY_SOURCE, O_RDONLY);
169 ret = read_exact(fd, secretkey, sizeof(secretkey), 0);
170 if (ret != sizeof(secretkey)) {
171 err = EIO;
172 errstr = "Cannot read from "ENTROPY_SOURCE"!\n";
173 goto out;
175 close(fd);
176 crypto_scalarmult_curve25519_base(publickey, secretkey);
177 memset(path, 0, sizeof(path));
178 slprintf(path, sizeof(path), "%s/%s", home, FILE_PUBKEY);
179 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
180 if (fd < 0) {
181 err = EIO;
182 errstr = "Cannot open pubkey file!\n";
183 goto out;
185 ret = write(fd, publickey, sizeof(publickey));
186 if (ret != sizeof(publickey)) {
187 err = EIO;
188 errstr = "Cannot write public key!\n";
189 goto out;
191 close(fd);
192 info("Public key written to %s!\n", path);
193 memset(path, 0, sizeof(path));
194 slprintf(path, sizeof(path), "%s/%s", home, FILE_PRIVKEY);
195 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
196 if (fd < 0) {
197 err = EIO;
198 errstr = "Cannot open privkey file!\n";
199 goto out;
201 ret = write(fd, secretkey, sizeof(secretkey));
202 if (ret != sizeof(secretkey)) {
203 err = EIO;
204 errstr = "Cannot write private key!\n";
205 goto out;
207 out:
208 close(fd);
209 memset(publickey, 0, sizeof(publickey));
210 memset(secretkey, 0, sizeof(secretkey));
211 if (err)
212 panic("%s: %s", errstr, strerror(errno));
213 else
214 info("Private key written to %s!\n", path);
217 static void check_config_keypair_or_die(char *home)
219 int fd;
220 ssize_t ret;
221 int err;
222 const char * errstr = NULL;
223 unsigned char publickey[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES];
224 unsigned char publicres[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES];
225 unsigned char secretkey[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES];
226 char path[PATH_MAX];
227 memset(path, 0, sizeof(path));
228 slprintf(path, sizeof(path), "%s/%s", home, FILE_PRIVKEY);
229 fd = open(path, O_RDONLY);
230 if (fd < 0) {
231 err = EIO;
232 errstr = "Cannot open privkey file!\n";
233 goto out;
235 ret = read(fd, secretkey, sizeof(secretkey));
236 if (ret != sizeof(secretkey)) {
237 err = EIO;
238 errstr = "Cannot read private key!\n";
239 goto out;
241 close(fd);
242 memset(path, 0, sizeof(path));
243 slprintf(path, sizeof(path), "%s/%s", home, FILE_PUBKEY);
244 fd = open(path, O_RDONLY);
245 if (fd < 0) {
246 err = EIO;
247 errstr = "Cannot open pubkey file!\n";
248 goto out;
250 ret = read(fd, publickey, sizeof(publickey));
251 if (ret != sizeof(publickey)) {
252 err = EIO;
253 errstr = "Cannot read public key!\n";
254 goto out;
256 crypto_scalarmult_curve25519_base(publicres, secretkey);
257 err = crypto_verify_32(publicres, publickey);
258 if (err) {
259 err = EINVAL;
260 errstr = "WARNING: your keypair is corrupted!!! You need to "
261 "generate new keys!!!\n";
262 goto out;
264 out:
265 close(fd);
266 memset(publickey, 0, sizeof(publickey));
267 memset(publicres, 0, sizeof(publicres));
268 memset(secretkey, 0, sizeof(secretkey));
269 if (err)
270 panic("%s: %s\n", errstr, strerror(errno));
273 static int keygen(char *home)
275 create_transsipdir(home);
276 write_username(home);
277 create_keypair(home);
278 check_config_keypair_or_die(home);
279 printf("\nNow edit your .transsip/settings file before starting i.e.:\n");
280 printf(" port <your-transsip-port>\n");
281 printf(" stun stunserver.org\n");
282 printf(" alsa plughw:0,0\n");
283 return 0;
286 static void do_call_duplex(void)
288 #if 0
289 int ret, recv_started = 0;
291 alsa_start(dev);
292 while (likely(!quit)) {
293 ret = poll(pfds, nfds + 1, -1);
294 if (ret < 0)
295 panic("Poll returned with %d!\n", ret);
297 /* Received packets */
298 if (pfds[nfds].revents & POLLIN) {
299 n = recv(sd, msg, MAX_MSG, 0);
300 int recv_timestamp = ((int*) msg)[0];
302 JitterBufferPacket packet;
303 packet.data = msg + 4;
304 packet.len = n - 4;
305 packet.timestamp = recv_timestamp;
306 packet.span = FRAME_SIZE;
307 packet.sequence = 0;
309 jitter_buffer_put(jitter, &packet);
310 recv_started = 1;
313 /* Ready to play a frame (playback) */
314 if (alsa_play_ready(dev, pfds, nfds)) {
315 short pcm[FRAME_SIZE * CHANNELS];
316 if (recv_started) {
317 JitterBufferPacket packet;
318 /* Get audio from the jitter buffer */
319 packet.data = msg;
320 packet.len = MAX_MSG;
321 jitter_buffer_tick(jitter);
322 jitter_buffer_get(jitter, &packet, FRAME_SIZE,
323 NULL);
324 if (packet.len == 0)
325 packet.data=NULL;
326 celt_decode(dec_state, (const unsigned char *)
327 packet.data, packet.len, pcm);
328 } else {
329 for (i = 0; i < FRAME_SIZE * CHANNELS; ++i)
330 pcm[i] = 0;
333 /* Playback the audio and reset the echo canceller
334 if we got an underrun */
336 if (alsa_write(dev, pcm, FRAME_SIZE))
337 speex_echo_state_reset(echo_state);
338 /* Put frame into playback buffer */
339 speex_echo_playback(echo_state, pcm);
342 /* Audio available from the soundcard (capture) */
343 if (alsa_cap_ready(dev, pfds, nfds)) {
344 short pcm[FRAME_SIZE * CHANNELS],
345 pcm2[FRAME_SIZE * CHANNELS];
346 char outpacket[MAX_MSG];
348 alsa_read(dev, pcm, FRAME_SIZE);
350 /* Perform echo cancellation */
351 speex_echo_capture(echo_state, pcm, pcm2);
352 for (i = 0; i < FRAME_SIZE * CHANNELS; ++i)
353 pcm[i] = pcm2[i];
355 celt_encode(enc_state, pcm, NULL, (unsigned char *)
356 (outpacket + 4), PACKETSIZE);
358 /* Pseudo header: four null bytes and a 32-bit
359 timestamp */
360 ((int*)outpacket)[0] = send_timestamp;
361 send_timestamp += FRAME_SIZE;
363 rc = sendto(sd, outpacket, PACKETSIZE + 4, 0,
364 (struct sockaddr *) &remote_addr,
365 sizeof(remote_addr));
366 if (rc < 0)
367 panic("cannot send to socket");
370 #endif
373 void call_out(char *host, char *port)
375 /* send notify */
376 /* wait for accept */
377 /* transfer data */
379 printf("Trying to call %s:%s ...\n", host, port);
380 do_call_duplex();
383 void call_in(int take)
385 /* lookup addrbook */
386 /* send notify */
387 /* transfer data */
389 barrier();
390 if (incoming_call == 0) {
391 printf("No incoming call right now!\n");
392 return;
395 printf("Trying to take incoming call ...\n");
396 do_call_duplex();
399 static void *thread(void *null)
401 int sock = -1, ret, mtu, nfds, tmp;
402 struct addrinfo hints, *ahead, *ai;
403 CELTMode *mode;
405 while (did_stun == 0)
406 barrier();
408 memset(&hints, 0, sizeof(hints));
409 hints.ai_family = PF_UNSPEC;
410 hints.ai_socktype = SOCK_DGRAM;
411 hints.ai_protocol = IPPROTO_UDP;
412 hints.ai_flags = AI_PASSIVE;
414 ret = getaddrinfo(NULL, port, &hints, &ahead);
415 if (ret < 0)
416 panic("Cannot get address info!\n");
418 for (ai = ahead; ai != NULL && sock < 0; ai = ai->ai_next) {
419 sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
420 if (sock < 0)
421 continue;
422 if (ai->ai_family == AF_INET6) {
423 int one = 1;
424 #ifdef IPV6_V6ONLY
425 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
426 &one, sizeof(one));
427 if (ret < 0) {
428 close(sock);
429 sock = -1;
430 continue;
432 #else
433 close(sock);
434 sock = -1;
435 continue;
436 #endif /* IPV6_V6ONLY */
438 mtu = IP_PMTUDISC_DONT;
439 setsockopt(sock, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu));
440 ret = bind(sock, ai->ai_addr, ai->ai_addrlen);
441 if (ret < 0) {
442 close(sock);
443 sock = -1;
444 continue;
447 freeaddrinfo(ahead);
448 if (sock < 0)
449 panic("Cannot open socket!\n");
451 dev = alsa_open(alsadev, SAMPLING_RATE, CHANNELS, FRAME_SIZE);
452 if (!dev)
453 panic("Cannot open ALSA device %s!\n", alsadev);
455 mode = celt_mode_create(SAMPLING_RATE, FRAME_SIZE, NULL);
456 encoder = celt_encoder_create(mode, CHANNELS, NULL);
457 decoder = celt_decoder_create(mode, CHANNELS, NULL);
459 nfds = alsa_nfds(dev);
460 pfds = xmalloc(sizeof(*pfds) * (nfds + 1));
461 alsa_getfds(dev, pfds, nfds);
462 pfds[nfds].fd = sock;
463 pfds[nfds].events = POLLIN;
465 jitter = jitter_buffer_init(FRAME_SIZE);
466 tmp = FRAME_SIZE;
467 jitter_buffer_ctl(jitter, JITTER_BUFFER_SET_MARGIN, &tmp);
469 echostate = speex_echo_state_init(FRAME_SIZE, 10 * FRAME_SIZE);
470 tmp = SAMPLING_RATE;
471 speex_echo_ctl(echostate, SPEEX_ECHO_SET_SAMPLING_RATE, &tmp);
473 while (likely(!quit)) {
474 ret = poll(&pfds[nfds], 1, -1);
475 if (ret < 0)
476 panic("Poll returned with %d!\n", ret);
477 if (pfds[nfds].revents & POLLIN) {
478 /* Check for Auth pkt, if yes, set current caller and notifiy cli */
479 /* cli user must call take, that triggers call_in() */
480 printf(".\n");
484 xfree(pfds);
485 alsa_close(dev);
486 close(sock);
487 pthread_exit(0);
490 static void start_server(void)
492 int ret = pthread_create(&ptid, NULL, thread, NULL);
493 if (ret)
494 panic("Cannot create server thread!\n");
497 static void stop_server(void)
499 /* pthread_join(ptid, NULL);*/
502 static void help(void)
504 printf("\ntranssip %s, peer-to-peer elliptic-curve-crypto-based "
505 "telephony network\n", VERSION_STRING);
506 printf("http://www.transsip.org\n\n");
507 printf("Usage: transsip [options]\n");
508 printf("Options:\n");
509 printf(" -k|--keygen Generate public/private keypair\n");
510 printf(" -v|--version Show version\n");
511 printf(" -h|--help Guess what?!\n\n");
512 printf("Note:\n");
513 printf(" There is no default port specified, so that you are forced\n");
514 printf(" to select your own!\n");
515 printf("\n");
516 printf("Secret ingredient: 7647-14-5\n");
517 printf("\n");
518 printf("Please report bugs to <bugs@transsip.org>\n");
519 printf("Copyright (C) 2011 Daniel Borkmann <daniel@transsip.org>,\n");
520 printf("License: GNU GPL version 2\n");
521 printf("This is free software: you are free to change and redistribute it.\n");
522 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
523 die();
526 static void version(void)
528 printf("\ntranssip %s, peer-to-peer elliptic-curve-crypto-based "
529 "telephony network\n", VERSION_STRING);
530 printf("Build: %s\n", BUILD_STRING);
531 printf("http://www.transsip.org\n\n");
532 printf("Please report bugs to <bugs@transsip.org>\n");
533 printf("Copyright (C) 2011 Daniel Borkmann <daniel@transsip.org>,\n");
534 printf("License: GNU GPL version 2\n");
535 printf("This is free software: you are free to change and redistribute it.\n");
536 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
537 die();
540 int main(int argc, char **argv)
542 char *home = fetch_home_dir();
543 if (getuid() != geteuid())
544 seteuid(getuid());
545 if (getenv("LD_PRELOAD"))
546 panic("transsip cannot be preloaded!\n");
547 if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0)
548 panic("transsip cannot be ptraced!\n");
549 curve25519_selftest();
550 if (argc == 2 && (!strncmp("-k", argv[1], strlen("-k")) ||
551 !strncmp("--keygen", argv[1], strlen("--keygen")))) {
552 keygen(home);
553 show_key_export(home);
554 return 0;
556 if (argc == 2 && (!strncmp("-v", argv[1], strlen("-v")) ||
557 !strncmp("--version", argv[1], strlen("--version"))))
558 version();
559 if (argc == 2 && (!strncmp("-h", argv[1], strlen("-h")) ||
560 !strncmp("--help", argv[1], strlen("--help"))))
561 help();
562 check_config_exists_or_die(home);
563 check_config_keypair_or_die(home);
564 start_server();
565 enter_shell_loop();
566 stop_server();
567 return 0;
570 int get_port(void)
572 return atoi(port);
575 char *get_stun_server(void)
577 return stun_server;
580 int show_key_export(char *home)
582 int fd, i;
583 ssize_t ret;
584 char path[PATH_MAX], tmp[64];
585 check_config_exists_or_die(home);
586 check_config_keypair_or_die(home);
587 printf("Your public peer information:\n ");
588 fflush(stdout);
589 memset(path, 0, sizeof(path));
590 slprintf(path, sizeof(path), "%s/%s", home, FILE_USERNAME);
591 fd = open_or_die(path, O_RDONLY);
592 while ((ret = read(fd, tmp, sizeof(tmp))) > 0) {
593 ret = write(STDOUT_FILENO, tmp, ret);
595 close(fd);
596 printf(" ");
597 memset(path, 0, sizeof(path));
598 slprintf(path, sizeof(path), "%s/%s", home, FILE_PUBKEY);
599 fd = open_or_die(path, O_RDONLY);
600 ret = read(fd, tmp, sizeof(tmp));
601 if (ret != crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES)
602 panic("Cannot read public key!\n");
603 for (i = 0; i < ret; ++i)
604 if (i == ret - 1)
605 printf("%02x\n\n", (unsigned char) tmp[i]);
606 else
607 printf("%02x:", (unsigned char) tmp[i]);
608 close(fd);
609 fflush(stdout);
610 return 0;