FreeCalypso > hg > themwi-system-sw
view utils/sip-out-test.c @ 112:6aa63cf4620a
sip-in call clearing: select timeout implemented
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 28 Sep 2022 18:59:55 -0800 |
parents | ffb563a17f23 |
children |
line wrap: on
line source
/* * This program is a contraption for testing manually constructed * outgoing SIP calls to BulkVS. */ #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> #include <sys/errno.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <unistd.h> #define MAX_SIP_TX_PACKET 1472 static struct in_addr local_ip, remote_ip; static unsigned local_sip_port, local_rtp_port, remote_port; static char *invite_filename, *log_filename; static char invite_packet[MAX_SIP_TX_PACKET]; static unsigned invite_packet_len; static FILE *logF; static struct timeval curtime; static void read_invite_file() { FILE *inf; char linebuf[128], *cp, *dp; int lineno; unsigned size_accum, linelen; inf = fopen(invite_filename, "r"); if (!inf) { perror(invite_filename); exit(1); } size_accum = 0; dp = invite_packet; for (lineno = 1; fgets(linebuf, sizeof(linebuf), inf); lineno++) { cp = index(linebuf, '\n'); if (!cp) { fprintf(stderr, "%s line %d: too long or missing newline\n", invite_filename, lineno); exit(1); } *cp = '\0'; linelen = cp - linebuf; if (size_accum + linelen + 2 > MAX_SIP_TX_PACKET) { fprintf(stderr, "%s line %d: packet overflow\n", invite_filename, lineno); exit(1); } bcopy(linebuf, dp, linelen); dp += linelen; *dp++ = '\r'; *dp++ = '\n'; size_accum += linelen + 2; } fclose(inf); if (!size_accum) { fprintf(stderr, "error: %s is empty\n", invite_filename); exit(1); } invite_packet_len = size_accum; } static void log_common(msg, msglen, sin, dir, outf) char *msg, *dir; unsigned msglen; struct sockaddr_in *sin; FILE *outf; { unsigned sec, ms; sec = curtime.tv_sec % 86400; ms = curtime.tv_usec / 1000; fprintf(outf, "Msg %s %s:%u %u bytes %02u:%02u:%02u.%03u\n", dir, inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), msglen, sec / 3600, (sec / 60) % 60, sec % 60, ms); fwrite(msg, 1, msglen, outf); putc('\n', outf); fflush(outf); } static void log_sip_msg_rx(msg, msglen, sin) char *msg; unsigned msglen; struct sockaddr_in *sin; { log_common(msg, msglen, sin, "from", stdout); if (logF) log_common(msg, msglen, sin, "from", logF); } static void log_sip_msg_tx(msg, msglen, sin) char *msg; unsigned msglen; struct sockaddr_in *sin; { log_common(msg, msglen, sin, "to", stdout); if (logF) log_common(msg, msglen, sin, "to", logF); } main(argc, argv) char **argv; { struct sockaddr_in sin_local, sin_rtp, sin_rtcp, sin_remote, sin_rx; int sock_sip, sock_rtp, sock_rtcp, max_fd; socklen_t addrlen; fd_set fds; char recv_buf[4096]; int rc; /* grok command line arguments */ if (argc < 7 || argc > 8) { fprintf(stderr, "usage: %s local-ip local-sip local-rtp remote-ip remote-sip inv-file [logfile]\n", argv[0]); exit(1); } local_ip.s_addr = inet_addr(argv[1]); if (local_ip.s_addr == INADDR_NONE) { fprintf(stderr, "error: invalid IP address \"%s\"\n", argv[1]); exit(1); } local_sip_port = atoi(argv[2]); local_rtp_port = atoi(argv[3]); remote_ip.s_addr = inet_addr(argv[4]); if (remote_ip.s_addr == INADDR_NONE) { fprintf(stderr, "error: invalid IP address \"%s\"\n", argv[4]); exit(1); } remote_port = atoi(argv[5]); invite_filename = argv[6]; log_filename = argv[7]; /* fill sin structures */ sin_local.sin_family = AF_INET; sin_local.sin_addr = local_ip; sin_local.sin_port = htons(local_sip_port); sin_rtp.sin_family = AF_INET; sin_rtp.sin_addr = local_ip; sin_rtp.sin_port = htons(local_rtp_port); sin_rtcp.sin_family = AF_INET; sin_rtcp.sin_addr = local_ip; sin_rtcp.sin_port = htons(local_rtp_port+1); sin_remote.sin_family = AF_INET; sin_remote.sin_addr = remote_ip; sin_remote.sin_port = htons(remote_port); /* create and bind sockets */ sock_sip = socket(AF_INET, SOCK_DGRAM, 0); if (sock_sip < 0) { perror("socket"); exit(1); } rc = bind(sock_sip, (struct sockaddr *) &sin_local, sizeof(struct sockaddr_in)); if (rc < 0) { perror("bind"); exit(1); } sock_rtp = socket(AF_INET, SOCK_DGRAM, 0); if (sock_rtp < 0) { perror("socket"); exit(1); } rc = bind(sock_rtp, (struct sockaddr *) &sin_rtp, sizeof(struct sockaddr_in)); if (rc < 0) { perror("bind"); exit(1); } sock_rtcp = socket(AF_INET, SOCK_DGRAM, 0); if (sock_rtcp < 0) { perror("socket"); exit(1); } rc = bind(sock_rtcp, (struct sockaddr *) &sin_rtcp, sizeof(struct sockaddr_in)); if (rc < 0) { perror("bind"); exit(1); } /* read the INVITE packet */ read_invite_file(); /* open the log file, if we have one */ if (log_filename) { logF = fopen(log_filename, "a"); if (!logF) { perror(log_filename); exit(1); } } /* now get down to business */ max_fd = sock_sip; if (sock_rtp > max_fd) max_fd = sock_rtp; if (sock_rtcp > max_fd) max_fd = sock_rtcp; addrlen = sizeof(struct sockaddr_in); rc = sendto(sock_sip, invite_packet, invite_packet_len, 0, (struct sockaddr *) &sin_remote, addrlen); if (rc < 0) { perror("sendto"); exit(1); } gettimeofday(&curtime, 0); log_sip_msg_tx(invite_packet, invite_packet_len, &sin_remote); /* main select loop */ for (;;) { FD_ZERO(&fds); FD_SET(sock_sip, &fds); FD_SET(sock_rtp, &fds); FD_SET(sock_rtcp, &fds); rc = select(max_fd+1, &fds, 0, 0, 0); if (rc < 0) { if (errno == EINTR) continue; perror("select"); exit(1); } gettimeofday(&curtime, 0); if (FD_ISSET(sock_sip, &fds)) { addrlen = sizeof(struct sockaddr_in); rc = recvfrom(sock_sip, recv_buf, sizeof recv_buf, 0, (struct sockaddr *) &sin_rx, &addrlen); if (rc < 0) { perror("recvfrom"); exit(1); } log_sip_msg_rx(recv_buf, rc, &sin_rx); } if (FD_ISSET(sock_rtp, &fds)) { addrlen = sizeof(struct sockaddr_in); rc = recvfrom(sock_rtp, recv_buf, sizeof recv_buf, 0, (struct sockaddr *) &sin_rx, &addrlen); if (rc < 0) { perror("recvfrom"); exit(1); } } if (FD_ISSET(sock_rtcp, &fds)) { addrlen = sizeof(struct sockaddr_in); rc = recvfrom(sock_rtp, recv_buf, sizeof recv_buf, 0, (struct sockaddr *) &sin_rx, &addrlen); if (rc < 0) { perror("recvfrom"); exit(1); } } } }