Introduce basic vomp console test

This commit is contained in:
Jeremy Lakeman 2014-02-03 15:51:48 +10:30
parent 32ab923dcc
commit 7ed6be3690
6 changed files with 172 additions and 59 deletions

View File

@ -245,6 +245,7 @@ ATOM(bool_t, keyring, 0, boolean,, "")
ATOM(bool_t, security, 0, boolean,, "")
ATOM(bool_t, mdprequests, 0, boolean,, "")
ATOM(bool_t, msp, 0, boolean,, "")
ATOM(bool_t, monitor, 0, boolean,, "")
ATOM(bool_t, radio_link, 0, boolean,, "")
ATOM(bool_t, peers, 0, boolean,, "")
ATOM(bool_t, overlaybuffer, 0, boolean,, "")

View File

@ -76,7 +76,8 @@ int monitor_client_open(struct monitor_state **res)
struct socket_address addr;
if (make_local_sockaddr(&addr, "monitor.socket") == -1)
return -1;
INFOF("Attempting to connect to %s", alloca_socket_address(&addr));
if (config.debug.monitor)
DEBUGF("Attempting to connect to %s", alloca_socket_address(&addr));
if (socket_connect(fd, &addr.addr, addr.addrlen) == -1) {
close(fd);
return -1;
@ -89,6 +90,8 @@ int monitor_client_open(struct monitor_state **res)
int monitor_client_close(int fd, struct monitor_state *res){
free(res);
close(fd);
if (config.debug.monitor)
DEBUGF("Closed fd %d", fd);
return 0;
}
@ -105,6 +108,9 @@ int monitor_client_writeline(int fd,char *fmt, ...)
n=vsnprintf(msg, sizeof(msg), fmt, ap);
va_end(ap);
if (config.debug.monitor)
dump("Writing to monitor", msg, n);
return write(fd,msg,n);
}
@ -126,6 +132,8 @@ int monitor_client_writeline_and_data(int fd,unsigned char *data,int bytes,char
bcopy(data,out+n,bytes);
n+=bytes;
if (config.debug.monitor)
dump("Writing to monitor", out, n);
return write(fd,out,n);
}
@ -159,6 +167,10 @@ int monitor_client_read(int fd, struct monitor_state *res, struct monitor_comman
WHYF("read(%d, %p, %d) returned %d", fd, res->buffer + oldOffset, MONITOR_CLIENT_BUFFER_SIZE - oldOffset, bytesRead);
return -1;
}
if (config.debug.monitor)
dump("Read from monitor", res->buffer + oldOffset, bytesRead);
res->bufferBytes+=bytesRead;
again:

View File

@ -33,5 +33,6 @@ includeTests rhizomeprotocol
includeTests rhizomehttp
includeTests meshms
includeTests directory_service
includeTests vomp
runTests "$@"

76
tests/vomp Executable file
View File

@ -0,0 +1,76 @@
#!/bin/bash
# Tests for voice calls
#
# Copyright 2012 Serval Project, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
source "${0%/*}/../testframework.sh"
source "${0%/*}/../testdefs.sh"
teardown() {
stop_all_servald_servers
kill_all_servald_processes
assert_no_servald_processes
report_all_servald_servers
}
configure_servald_server() {
create_single_identity
add_servald_interface
executeOk_servald config \
set debug.mdprequests on \
set debug.monitor on \
set debug.vomp on \
set log.console.level DEBUG \
set log.console.show_time on
}
vomp_connect() {
executeOk_servald console < <(sleep 1 && echo "call $1 $2 $3" && sleep 3 && echo "say hello" && sleep 3 && echo "hangup")
tfw_cat --stdout --stderr
assertStdoutGrep --stdout --matches=1 "^Dialling$"
assertStdoutGrep --stdout --matches=1 "^Codec list"
assertStdoutGrep --stdout --matches=1 "^Ringing$"
assertStdoutGrep --stdout --matches=1 "^Picked up$"
assertStdoutGrep --stdout --matches=1 "^hi there$"
assertStdoutGrep --stdout --matches=1 "^Call ended$"
}
vomp_answer() {
executeOk_servald console < <(sleep 2 && echo "answer" && sleep 2 && echo "say hi there" && sleep 3 && echo "hangup")
tfw_cat --stdout --stderr
assertStdoutGrep --stdout --matches=1 "^Incoming call"
assertStdoutGrep --stdout --matches=1 "^Codec list"
assertStdoutGrep --stdout --matches=1 "^hello$"
assertStdoutGrep --stdout --matches=1 "^Call ended$"
}
doc_call_lifecycle="Successful call lifecycle"
setup_call_lifecycle() {
setup_servald
assert_no_servald_processes
start_servald_instances +A +B
}
test_call_lifecycle() {
set_instance +A
fork vomp_answer
set_instance +B
fork vomp_connect $SIDA $DIDB $DIDA
fork_wait_all
}
runTests "$@"

6
vomp.c
View File

@ -475,7 +475,7 @@ static void prepare_vomp_header(
ob_append_byte(payload, VOMP_VERSION);
ob_append_ui16(payload, call->local.session);
ob_append_ui16(payload, call->remote.session);
ob_append_ui16(payload, (call->remote.state<<4)|call->local.state);
ob_append_byte(payload, (call->remote.state<<4)|call->local.state);
// keep trying to punch a NAT tunnel for 10s
// note that requests are rate limited internally to one packet per second
@ -526,6 +526,8 @@ static int vomp_send_status_remote(struct vomp_call_state *call)
call->local.sequence++;
ob_flip(payload);
if (config.debug.vomp)
ob_dump(payload, "payload");
overlay_send_frame(&header, payload);
ob_free(payload);
@ -563,6 +565,8 @@ int vomp_received_audio(struct vomp_call_state *call, int audio_codec, int time,
ob_append_bytes(payload, audio, audio_length);
ob_flip(payload);
if (config.debug.vomp)
ob_dump(payload, "payload");
overlay_send_frame(&header, payload);
ob_free(payload);

View File

@ -64,10 +64,23 @@
#include "strbuf.h"
#include "strbuf_helpers.h"
int call_token=-1;
int seen_audio=0;
int monitor_client_fd=-1;
struct monitor_state *monitor_state;
static void read_lines(struct sched_ent *alarm);
static int console_dial(const struct cli_parsed *parsed, struct cli_context *context);
static int console_answer(const struct cli_parsed *parsed, struct cli_context *context);
static int console_hangup(const struct cli_parsed *parsed, struct cli_context *context);
static int console_audio(const struct cli_parsed *parsed, struct cli_context *context);
static int console_usage(const struct cli_parsed *parsed, struct cli_context *context);
static void console_command(char *line);
static void monitor_read(struct sched_ent *alarm);
struct cli_schema console_commands[]={
{console_answer,{"answer",NULL},0,"Answer an incoming phone call"},
{console_dial,{"call","<sid>","[<local_number>]","[<remote_extension>]",NULL},0,"Start dialling a given person"},
{console_hangup,{"hangup",NULL},0,"Hangup the phone line"},
{console_usage,{"help",NULL},0,"This usage message"},
{console_audio,{"say","...",NULL},0,"Send a text string to the other party"},
{NULL, {NULL, NULL, NULL}, 0, NULL},
};
struct line_state{
struct sched_ent alarm;
@ -77,20 +90,45 @@ struct line_state{
void (*process_line)(char *line);
};
struct profile_total stdin_profile={
.name="read_lines",
};
struct line_state stdin_state={
.alarm = {
.poll = {.fd = STDIN_FILENO,.events = POLLIN},
.function = read_lines,
.stats=&stdin_profile
},
.fd=0,
.process_line=console_command,
};
struct profile_total monitor_profile={
.name="monitor_read",
};
struct sched_ent monitor_alarm={
.poll = {.fd = STDIN_FILENO,.events = POLLIN},
.function = monitor_read,
.stats=&monitor_profile,
};
int call_token=-1;
int seen_audio=0;
struct monitor_state *monitor_state;
static void send_hangup(int session_id){
monitor_client_writeline(monitor_client_fd, "hangup %06x\n",session_id);
monitor_client_writeline(monitor_alarm.poll.fd, "hangup %06x\n",session_id);
}
static void send_ringing(int session_id){
monitor_client_writeline(monitor_client_fd, "ringing %06x\n",session_id);
monitor_client_writeline(monitor_alarm.poll.fd, "ringing %06x\n",session_id);
}
static void send_pickup(int session_id){
monitor_client_writeline(monitor_client_fd, "pickup %06x\n",session_id);
monitor_client_writeline(monitor_alarm.poll.fd, "pickup %06x\n",session_id);
}
static void send_call(const char *sid, const char *caller_id, const char *remote_ext){
monitor_client_writeline(monitor_client_fd, "call %s %s %s\n", sid, caller_id, remote_ext);
monitor_client_writeline(monitor_alarm.poll.fd, "call %s %s %s\n", sid, caller_id, remote_ext);
}
static void send_audio(int session_id, unsigned char *buffer, int len, int codec){
monitor_client_writeline_and_data(monitor_client_fd, buffer, len, "audio %06x %d\n", session_id, codec);
monitor_client_writeline_and_data(monitor_alarm.poll.fd, buffer, len, "audio %06x %d\n", session_id, codec);
}
static int remote_call(char *UNUSED(cmd), int UNUSED(argc), char **argv, unsigned char *UNUSED(data), int UNUSED(dataLen), void *UNUSED(context))
@ -106,7 +144,7 @@ static int remote_call(char *UNUSED(cmd), int UNUSED(argc), char **argv, unsigne
call_token = token;
seen_audio = 0;
printf("Incoming call from %s (%s)\n",argv[3],argv[4]);
printf("Incoming call for %s (%s) from %s (%s)\n", argv[1], argv[2], argv[3], argv[4]);
fflush(stdout);
send_ringing(token);
return 1;
@ -116,7 +154,7 @@ static int remote_ringing(char *UNUSED(cmd), int UNUSED(argc), char **argv, unsi
{
int token = strtol(argv[0], NULL, 16);
if (call_token == token){
printf("They're ringing\n");
printf("Ringing\n");
fflush(stdout);
}else
send_hangup(token);
@ -127,7 +165,7 @@ static int remote_pickup(char *UNUSED(cmd), int UNUSED(argc), char **argv, unsig
{
int token = strtol(argv[0], NULL, 16);
if (call_token == token){
printf("They've picked up\n");
printf("Picked up\n");
fflush(stdout);
}else
send_hangup(token);
@ -169,9 +207,12 @@ static int remote_audio(char *UNUSED(cmd), int UNUSED(argc), char **argv, unsign
case VOMP_CODEC_TEXT:
data[dataLen]=0;
printf("%s\n",data);
fflush(stdout);
break;
default:
printf("Unhandled codec %d, len %d\n", codec, dataLen);
break;
}
fflush(stdout);
}else
send_hangup(token);
return 1;
@ -221,6 +262,7 @@ struct monitor_command_handler console_handlers[]={
{.command="AUDIO", .handler=remote_audio},
{.command="CODECS", .handler=remote_codecs},
{.command="INFO", .handler=remote_print},
{.command="ERROR", .handler=remote_print},
{.command="CALLSTATUS", .handler=remote_noop},
{.command="KEEPALIVE", .handler=remote_noop},
{.command="MONITORSTATUS", .handler=remote_noop},
@ -269,11 +311,11 @@ static int console_audio(const struct cli_parsed *parsed, struct cli_context *UN
static struct strbuf str_buf = STRUCT_STRBUF_EMPTY;
strbuf_init(&str_buf, buf, sizeof(buf));
unsigned i;
for (i = 0; i < parsed->argc; ++i) {
if (i)
for (i = 1; i < parsed->argc; ++i) {
if (i>1)
strbuf_putc(&str_buf, ' ');
if (parsed->args[i])
strbuf_toprint_quoted(&str_buf, "\"\"", parsed->args[i]);
strbuf_puts(&str_buf, parsed->args[i]);
else
strbuf_puts(&str_buf, "NULL");
}
@ -283,17 +325,6 @@ static int console_audio(const struct cli_parsed *parsed, struct cli_context *UN
return 0;
}
static int console_usage(const struct cli_parsed *parsed, struct cli_context *context);
struct cli_schema console_commands[]={
{console_answer,{"answer",NULL},0,"Answer an incoming phone call"},
{console_dial,{"call","<sid>","[<local_number>]","[<remote_extension>]",NULL},0,"Start dialling a given person"},
{console_hangup,{"hangup",NULL},0,"Hangup the phone line"},
{console_usage,{"help",NULL},0,"This usage message"},
{console_audio,{"say","...",NULL},0,"Send a text string to the other party"},
{NULL, {NULL, NULL, NULL}, 0, NULL},
};
static int console_usage(const struct cli_parsed *UNUSED(parsed), struct cli_context *UNUSED(context))
{
cli_usage(console_commands, XPRINTF_STDIO(stdout));
@ -329,6 +360,15 @@ static void read_lines(struct sched_ent *alarm){
struct line_state *state=(struct line_state *)alarm;
set_nonblock(STDIN_FILENO);
int bytes = read(state->alarm.poll.fd, state->line_buff + state->line_pos, sizeof(state->line_buff) - state->line_pos);
if (bytes<=0){
if (monitor_alarm.poll.fd!=-1){
unwatch(&monitor_alarm);
monitor_client_close(monitor_alarm.poll.fd, monitor_state);
monitor_alarm.poll.fd=-1;
}
return;
}
set_block(STDIN_FILENO);
int i = state->line_pos;
int processed=0;
@ -355,10 +395,11 @@ static void read_lines(struct sched_ent *alarm){
static void monitor_read(struct sched_ent *alarm){
if (monitor_client_read(alarm->poll.fd, monitor_state, console_handlers,
sizeof(console_handlers)/sizeof(struct monitor_command_handler))<0){
unwatch(alarm);
monitor_client_close(alarm->poll.fd, monitor_state);
alarm->poll.fd=-1;
monitor_client_fd=-1;
if (alarm->poll.fd!=-1){
unwatch(alarm);
monitor_client_close(alarm->poll.fd, monitor_state);
alarm->poll.fd=-1;
}
}
}
@ -366,40 +407,18 @@ int app_vomp_console(const struct cli_parsed *parsed, struct cli_context *UNUSED
{
if (config.debug.verbose)
DEBUG_cli_parsed(parsed);
static struct profile_total stdin_profile={
.name="read_lines",
};
struct line_state stdin_state={
.alarm = {
.poll = {.fd = STDIN_FILENO,.events = POLLIN},
.function = read_lines,
.stats=&stdin_profile
},
.fd=0,
.process_line=console_command,
};
static struct profile_total monitor_profile={
.name="monitor_read",
};
struct sched_ent monitor_alarm={
.poll = {.fd = STDIN_FILENO,.events = POLLIN},
.function = monitor_read,
.stats=&monitor_profile,
};
monitor_client_fd = monitor_client_open(&monitor_state);
monitor_alarm.poll.fd = monitor_client_open(&monitor_state);
monitor_client_writeline(monitor_client_fd, "monitor vomp %d\n",
monitor_client_writeline(monitor_alarm.poll.fd, "monitor vomp %d\n",
VOMP_CODEC_TEXT);
set_nonblock(monitor_client_fd);
set_nonblock(monitor_alarm.poll.fd);
monitor_alarm.poll.fd = monitor_client_fd;
watch(&monitor_alarm);
watch(&stdin_state.alarm);
while(monitor_client_fd!=-1){
while(monitor_alarm.poll.fd!=-1){
fd_poll();
}