mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-04-17 23:46:12 +00:00
Merge branch 'master' into andrew
Conflicts: log.c
This commit is contained in:
commit
274e5c007c
@ -42,6 +42,8 @@ SERVALD_SRC_FILES = \
|
||||
serval-dna/keyring.c \
|
||||
serval-dna/vomp.c \
|
||||
serval-dna/lsif.c \
|
||||
serval-dna/dna_helper.c \
|
||||
serval-dna/sighandlers.c \
|
||||
serval-dna/monitor.c \
|
||||
serval-dna/monitor-cli.c \
|
||||
serval-dna/codecs.c \
|
||||
|
14
Makefile.in
14
Makefile.in
@ -45,6 +45,8 @@ SRCS= main.c \
|
||||
lsif.c \
|
||||
monitor.c \
|
||||
monitor-cli.c \
|
||||
dna_helper.c \
|
||||
sighandlers.c \
|
||||
codecs.c \
|
||||
audiodevices.c \
|
||||
audio_msm_g1.c \
|
||||
@ -68,11 +70,15 @@ HDRS= fifo.h \
|
||||
sqlite-amalgamation-3070900/sqlite3.h
|
||||
|
||||
LDFLAGS=@LDFLAGS@ @PORTAUDIO_LIBS@ @SRC_LIBS@ @SPANDSP_LIBS@ @CODEC2_LIBS@ @PTHREAD_LIBS@
|
||||
CFLAGS= @CPPFLAGS@ @CFLAGS@ @PORTAUDIO_CFLAGS@ @SRC_CFLAGS@ @SPANDSP_CFLAGS@ @PTHREAD_CFLAGS@ $(VOIPTEST_CFLAGS) -Wall -Wno-unused-value
|
||||
|
||||
CFLAGS= @CPPFLAGS@ @CFLAGS@ @PORTAUDIO_CFLAGS@ @SRC_CFLAGS@ @SPANDSP_CFLAGS@ @PTHREAD_CFLAGS@ $(VOIPTEST_CFLAGS)
|
||||
CFLAGS+=-Wall -Wno-unused-value
|
||||
#CFLAGS+=-Wunreachable-code
|
||||
#CFLAGS+=-O0
|
||||
|
||||
DEFS= @DEFS@
|
||||
|
||||
|
||||
all: dna libservald.so
|
||||
all: dna
|
||||
|
||||
sqlite3.o: sqlite3.c
|
||||
@echo CC $<
|
||||
@ -86,6 +92,8 @@ dna: $(OBJS)
|
||||
@echo LINK $@
|
||||
@$(CC) $(CFLAGS) -Wall -o $@ $(OBJS) $(LDFLAGS)
|
||||
|
||||
# This does not build on 64 bit elf platforms as NaCL isn't built with -fPIC
|
||||
# DOC 20120615
|
||||
libservald.so: $(OBJS)
|
||||
@echo LINK $@
|
||||
@$(CC) $(CFLAGS) -Wall -shared -o $@ $(OBJS) $(LDFLAGS)
|
||||
|
16
README.DUMMYNETS
Normal file
16
README.DUMMYNETS
Normal file
@ -0,0 +1,16 @@
|
||||
@PGS/20120615
|
||||
|
||||
Sometimes it is helpful to run more than one servald instance on a given machine
|
||||
for debugging purposes. To make this easier, there is a dummy interface driver
|
||||
that servald knows about. To use it:
|
||||
|
||||
1. create an empty file, e.g., dummynet0, somewhere convenient
|
||||
|
||||
2. For each servald instance you wish to use it, set the interface specification to include the dummynet file. Use a specification like "+>pathtodummynetfile", where pathtodummynetfile is the relative path from the instance path of that servald instance to the dummynet file. For example, you might run:
|
||||
% servald config set interfaces "+eth0,+>../dummynet0"
|
||||
|
||||
3. Run each servald instance. They should now use the dummy network.
|
||||
|
||||
NOTE: Because dummynets are files, not sockets, poll/select does not work on them. As a result the main overlay loop has slightly different behaviour and timing characteristics when a dummynet is in use.
|
||||
|
||||
TODO: Convert dummynet interface to use a unixdomain socket, and a simple dummynet server that reflects packets among the clients connected, so that all socket semantics (including use of poll/select) are preserved.
|
2
codecs.c
2
codecs.c
@ -48,6 +48,6 @@ int bufferAudioForPlayback(int codec,long long start_time,long long end_time,
|
||||
decode codecs etc here. */
|
||||
|
||||
/* send audio to device */
|
||||
int bytesWritten=audev->write(&data[0],dataLen);
|
||||
// int bytesWritten=audev->write(&data[0],dataLen);
|
||||
return 0;
|
||||
}
|
||||
|
111
commandline.c
111
commandline.c
@ -426,8 +426,10 @@ int app_dna_lookup(int argc, const char *const *argv, struct command_line_option
|
||||
if (create_serval_instance_dir() == -1)
|
||||
return -1;
|
||||
|
||||
int sid_count=0;
|
||||
unsigned char sids[128][SID_SIZE];
|
||||
int uri_count=0;
|
||||
#define MAXREPLIES 256
|
||||
#define MAXURILEN 256
|
||||
char uris[MAXREPLIES][MAXURILEN];
|
||||
|
||||
const char *did;
|
||||
if (cli_arg(argc, argv, o, "did", &did, NULL, "*") == -1)
|
||||
@ -484,20 +486,29 @@ int app_dna_lookup(int argc, const char *const *argv, struct command_line_option
|
||||
WHYF(" Error message: %s", mdp.error.message);
|
||||
}
|
||||
else if ((rx.packetTypeAndFlags&MDP_TYPE_MASK)==MDP_TX) {
|
||||
/* Display match unless it is a duplicate.
|
||||
XXX - For wildcard searches, each sid will only show up once. */
|
||||
int i;
|
||||
for(i=0;i<sid_count;i++)
|
||||
if (!memcmp(&rx.in.src.sid[0],&sids[i][0],SID_SIZE))
|
||||
break;
|
||||
if (i==sid_count) {
|
||||
cli_puts(overlay_render_sid(&rx.in.src.sid[0])); cli_delim(":");
|
||||
cli_puts((char *)&rx.in.payload[0]); cli_delim(":");
|
||||
cli_puts((char *)&rx.in.payload[32]); cli_delim("\n");
|
||||
if (sid_count<128) {
|
||||
bcopy(&rx.in.src.sid[0],&sids[i][0],SID_SIZE);
|
||||
sid_count++;
|
||||
}
|
||||
/* Extract DID, Name, URI from response. */
|
||||
if (strlen((char *)rx.in.payload)<512) {
|
||||
char did[512];
|
||||
char name[512];
|
||||
char uri[512];
|
||||
if (!parseDnaReply(rx.in.payload,rx.in.payload_length,
|
||||
did,name,uri))
|
||||
{
|
||||
/* Have we seen this response before? */
|
||||
int i;
|
||||
for(i=0;i<uri_count;i++)
|
||||
if (!strcmp(uri,uris[i])) break;
|
||||
if (i==uri_count) {
|
||||
/* Not previously seen, so report it */
|
||||
cli_puts(uri); cli_delim(":");
|
||||
cli_puts(did); cli_delim(":");
|
||||
cli_puts(name); cli_delim("\n");
|
||||
/* Remember that we have seen it */
|
||||
if (uri_count<MAXREPLIES&&strlen(uri)<MAXURILEN) {
|
||||
strcpy(uris[uri_count++],uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else WHYF("packettype=0x%x",rx.packetTypeAndFlags);
|
||||
@ -1505,18 +1516,19 @@ int app_keyring_list(int argc, const char *const *argv, struct command_line_opti
|
||||
{
|
||||
int kpn;
|
||||
keypair *kp;
|
||||
unsigned char *sid=NULL,*did=NULL;
|
||||
unsigned char *sid=NULL,*did=NULL,*name=NULL;
|
||||
for(kpn=0;kpn<k->contexts[cn]->identities[in]->keypair_count;kpn++)
|
||||
{
|
||||
kp=k->contexts[cn]->identities[in]->keypairs[kpn];
|
||||
if (kp->type==KEYTYPE_CRYPTOBOX) sid=kp->public_key;
|
||||
if (kp->type==KEYTYPE_DID) did=kp->private_key;
|
||||
if (kp->type==KEYTYPE_DID) { did=kp->private_key; name=kp->public_key; }
|
||||
}
|
||||
if (sid||did) {
|
||||
int i;
|
||||
if (sid) for(i=0;i<SID_SIZE;i++) cli_printf("%02x",sid[i]);
|
||||
if (sid||did) {
|
||||
if (sid) cli_printf("%s",overlay_render_sid(sid));
|
||||
cli_delim(":");
|
||||
if (did) cli_puts((char*)did);
|
||||
cli_delim(":");
|
||||
if (name) cli_puts((char*)name);
|
||||
cli_delim("\n");
|
||||
}
|
||||
}
|
||||
@ -1630,6 +1642,34 @@ int app_test_rfs(int argc, const char *const *argv, struct command_line_option *
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_crypt_test(int argc, const char *const *argv, struct command_line_option *o)
|
||||
{
|
||||
unsigned char nonce[crypto_box_curve25519xsalsa20poly1305_NONCEBYTES];
|
||||
unsigned char k[crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES];
|
||||
|
||||
unsigned char plain_block[65536];
|
||||
|
||||
urandombytes(nonce,sizeof(nonce));
|
||||
urandombytes(k,sizeof(k));
|
||||
|
||||
int len,i;
|
||||
|
||||
overlay_gettime_ms();
|
||||
|
||||
for(len=16;len<=65536;len*=2) {
|
||||
unsigned long long start=overlay_gettime_ms();
|
||||
for (i=0;i<1000;i++) {
|
||||
bzero(&plain_block[0],crypto_box_curve25519xsalsa20poly1305_ZEROBYTES);
|
||||
crypto_box_curve25519xsalsa20poly1305_afternm
|
||||
(plain_block,plain_block,len,nonce,k);
|
||||
}
|
||||
unsigned long long end=overlay_gettime_ms();
|
||||
printf("%d bytes - 100 tests took %lldms - mean time = %.2fms\n",
|
||||
len,end-start,(end-start)*1.0/i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_node_info(int argc, const char *const *argv, struct command_line_option *o)
|
||||
{
|
||||
const char *sid;
|
||||
@ -1641,7 +1681,7 @@ int app_node_info(int argc, const char *const *argv, struct command_line_option
|
||||
|
||||
mdp.packetTypeAndFlags=MDP_NODEINFO;
|
||||
if (argc>3) resolveDid=1;
|
||||
mdp.nodeinfo.resolve_did=0; // so we know that we don't have a result yet.
|
||||
mdp.nodeinfo.resolve_did=1; // Request resolution of DID and Name by local server if it can.
|
||||
|
||||
/* get SID or SID prefix
|
||||
XXX - Doesn't correctly handle odd-lengthed SID prefixes (ignores last digit).
|
||||
@ -1718,18 +1758,19 @@ int app_node_info(int argc, const char *const *argv, struct command_line_option
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
int bytes=m2.in.payload_length;
|
||||
|
||||
if ((bytes+1)>=sizeof(mdp.nodeinfo.did)+sizeof(mdp.nodeinfo.name)){
|
||||
WHYF("Result is too large");
|
||||
continue;
|
||||
}
|
||||
bcopy(&m2.in.payload[0],&mdp.nodeinfo.did[0],32);
|
||||
bcopy(&m2.in.payload[32],&mdp.nodeinfo.name[0],64);
|
||||
mdp.nodeinfo.did[bytes]=0;
|
||||
mdp.nodeinfo.resolve_did=1;
|
||||
break;
|
||||
{
|
||||
char did[512];
|
||||
char name[512];
|
||||
char uri[512];
|
||||
if (!parseDnaReply(m2.in.payload,m2.in.payload_length,
|
||||
did,name,uri))
|
||||
{
|
||||
/* Got a good DNA reply, copy it into place */
|
||||
bcopy(did,mdp.nodeinfo.did,32);
|
||||
bcopy(name,mdp.nodeinfo.name,64);
|
||||
mdp.nodeinfo.resolve_did=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1845,6 +1886,8 @@ command_line_option command_line_options[]={
|
||||
"Test RFS field calculation"},
|
||||
{app_monitor_cli,{"monitor","[<sid>]",NULL},0,
|
||||
"Interactive servald monitor interface. Specify SID to auto-dial that peer and insert dummy audio data"},
|
||||
{app_crypt_test,{"crypt","test",NULL},0,
|
||||
"Run cryptography speed test"},
|
||||
#ifdef HAVE_VOIPTEST
|
||||
{app_pa_phone,{"phone",NULL},0,
|
||||
"Run phone test application"},
|
||||
|
177
dna_helper.c
Normal file
177
dna_helper.c
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
Serval Distributed Numbering Architecture (DNA)
|
||||
Copyright (C) 2012 Paul Gardner-Stephen
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "serval.h"
|
||||
|
||||
/*
|
||||
The challenge with making an interface for calling an external program to
|
||||
resolve a DID into a URI is that it really should be asynchronous, so that
|
||||
servald can't pause due to delays in looking up DIDs by helper applications.
|
||||
|
||||
This can be partially mitigated by having a cache, so that at least for repeated
|
||||
requests the helper doesn't need to be called each time. This is very important
|
||||
because the DNA protocol relies on pre-emptive retries to ensure reception of
|
||||
a request over a lossy network.
|
||||
|
||||
The second part of the solution is to create an asynchronous queue for requests,
|
||||
by passing them via file descriptor to a single persistent instance of the DNA
|
||||
helper application, and polling the output of that application for results, and
|
||||
then passing them out to their destinations. This ensures that the process is
|
||||
asynchronous and non-blocking, regardless of how much time the helper application
|
||||
requires. Then the helper will just be another file descriptor to poll in the
|
||||
main loop.
|
||||
*/
|
||||
|
||||
int dna_helper_stdin=-1;
|
||||
int dna_helper_stdout=-1;
|
||||
|
||||
int parseDnaReply(unsigned char *bytes,int count,
|
||||
char *did,char *name,char *uri)
|
||||
{
|
||||
bzero(did,32); bzero(name,64);
|
||||
bzero(uri,512);
|
||||
int i,l;
|
||||
|
||||
l=0;
|
||||
for(i=0;i<511&&i<count&&bytes[i]!=0x0a;i++)
|
||||
did[l++]=bytes[i];
|
||||
did[l]=0;
|
||||
if (i>=count||i>=511) return WHY("DNA response does not contain name field");
|
||||
l=0; i++;
|
||||
for(;i<511&&i<count&&bytes[i]!=0x0a;i++)
|
||||
name[l++]=bytes[i];
|
||||
name[l]=0;
|
||||
if (i>=count||i>=511) return WHY("DNA response does not contain URI field");
|
||||
l=0; i++;
|
||||
for(;i<511&&i<count&&bytes[i]!=0;i++)
|
||||
uri[l++]=bytes[i];
|
||||
uri[l]=0;
|
||||
/* DEBUGF("did='%s', name='%s', uri='%s'",did,name,uri); */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dna_helper_start(const char *command)
|
||||
{
|
||||
int stdin_fds[2];
|
||||
int stdout_fds[2];
|
||||
|
||||
if (pipe(stdin_fds)) return -1;
|
||||
if (pipe(stdout_fds)) {
|
||||
close(stdin_fds[0]); close(stdin_fds[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pid=-1;
|
||||
if ((pid=fork())!=0) {
|
||||
/* Child, should exec() to become helper after installing file descriptors. */
|
||||
if (dup2(stdin_fds[1],0)) exit(-1); /* replace stdin */
|
||||
if (dup2(stdout_fds[0],1)) exit(-1); /* replace stdout */
|
||||
if (dup2(stdout_fds[0],2)) exit(-1); /* replace stderr */
|
||||
execl(command,command,NULL);
|
||||
/* execl() should never return, since it replaces this process with a new
|
||||
one. Thus something bad must have happened. */
|
||||
exit(-1);
|
||||
} else {
|
||||
if (pid==-1) {
|
||||
/* fork failed */
|
||||
close(stdin_fds[0]); close(stdin_fds[1]);
|
||||
close(stdout_fds[0]); close(stdout_fds[1]);
|
||||
return -1;
|
||||
} else {
|
||||
/* Parent, should put file descriptors into place for use */
|
||||
dna_helper_stdin=stdin_fds[0];
|
||||
dna_helper_stdout=stdout_fds[1];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int dna_helper_enqueue(char *did, unsigned char *requestorSid)
|
||||
{
|
||||
/* Check if we have a helper configured. If not, then set
|
||||
dna_helper_stdin to magic value of -2 so that we don't waste time
|
||||
in future looking up the dna helper configuration value. */
|
||||
if (dna_helper_stdin==-2) return -1;
|
||||
if (dna_helper_stdin==-1) {
|
||||
const char *dna_helper = confValueGet("dna.helper",NULL);
|
||||
if (!dna_helper||!dna_helper[0]) {
|
||||
dna_helper_stdin=-2;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Okay, so we have a helper configured.
|
||||
Run it */
|
||||
dna_helper_start(dna_helper);
|
||||
if (dna_helper_stdin<0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Write request to dna helper.
|
||||
Request takes form: DID<space>SID-of-Requestor\n
|
||||
By passing the requestor's SID to the helper, we don't need to maintain
|
||||
any state, as all we have to do is wait for responses from the helper,
|
||||
which will include the requestor's SID.
|
||||
*/
|
||||
signal(SIGPIPE,sigPipeHandler);
|
||||
sigPipeFlag=0;
|
||||
write(dna_helper_stdin,did,strlen(did));
|
||||
write(dna_helper_stdin," ",1);
|
||||
write(dna_helper_stdin,overlay_render_sid(requestorSid),SID_SIZE*2);
|
||||
write(dna_helper_stdin,"\n",1);
|
||||
if (sigPipeFlag) {
|
||||
/* Assume broken pipe due to dead helper.
|
||||
Next request will cause it to be restarted.
|
||||
(Losing the current request is not a big problem, because
|
||||
DNA preemptively retries, anyway.
|
||||
XXX In fact, we should probably have a limit to the number of restarts
|
||||
in quick succession so that we don't waste lots of time with a buggy or
|
||||
suicidal helper.
|
||||
*/
|
||||
close(dna_helper_stdin);
|
||||
close(dna_helper_stdout);
|
||||
dna_helper_stdin=-1;
|
||||
dna_helper_stdout=-1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dna_return_resolution(overlay_mdp_frame *mdp, unsigned char *fromSid,
|
||||
const char *did,const char *name,const char *uri)
|
||||
{
|
||||
/* copy SID out into source address of frame */
|
||||
bcopy(fromSid,&mdp->out.src.sid[0],SID_SIZE);
|
||||
|
||||
/* and build reply as did\nname\nURI<NUL> */
|
||||
snprintf((char *)&mdp->out.payload[0],512,"%s\n%s\n%s",
|
||||
did,name,uri);
|
||||
mdp->out.payload_length=strlen((char *)mdp->out.payload)+1;
|
||||
|
||||
/* Dispatch response */
|
||||
mdp->packetTypeAndFlags&=MDP_FLAG_MASK;
|
||||
mdp->packetTypeAndFlags|=MDP_TX;
|
||||
overlay_mdp_dispatch(mdp,0 /* system generated */,
|
||||
NULL,0);
|
||||
|
||||
return 0;
|
||||
}
|
23
lsif.c
23
lsif.c
@ -112,7 +112,7 @@ int scrapeProcNetRoute()
|
||||
|
||||
int
|
||||
lsif(void) {
|
||||
char buf[8192], addrtxt[INET_ADDRSTRLEN], bcasttxt[INET_ADDRSTRLEN];
|
||||
char buf[8192];
|
||||
struct ifconf ifc;
|
||||
int sck, nInterfaces, ofs;
|
||||
struct ifreq *ifr;
|
||||
@ -165,12 +165,14 @@ lsif(void) {
|
||||
bcopy(&ifr->ifr_ifru.ifru_addr, &local, sizeof(local));
|
||||
bcopy(&ifr->ifr_ifru.ifru_broadaddr, &broadcast ,sizeof(broadcast));
|
||||
|
||||
assert(inet_ntop(AF_INET, (const void *)&local.sin_addr, addrtxt, INET_ADDRSTRLEN) != NULL);
|
||||
assert(inet_ntop(AF_INET, (const void *)&broadcast.sin_addr, bcasttxt, INET_ADDRSTRLEN) != NULL);
|
||||
|
||||
if (debug & DEBUG_OVERLAYINTERFACES) INFOF("name=%s addr=%s, broad=%s\n",
|
||||
if (debug & DEBUG_OVERLAYINTERFACES) {
|
||||
char addrtxt[INET_ADDRSTRLEN], bcasttxt[INET_ADDRSTRLEN];
|
||||
assert(inet_ntop(AF_INET, (const void *)&local.sin_addr, addrtxt, INET_ADDRSTRLEN) != NULL);
|
||||
assert(inet_ntop(AF_INET, (const void *)&broadcast.sin_addr, bcasttxt, INET_ADDRSTRLEN) != NULL);
|
||||
INFOF("name=%s addr=%s, broad=%s\n",
|
||||
ifr->ifr_name,
|
||||
addrtxt, bcasttxt);
|
||||
}
|
||||
overlay_interface_register(ifr->ifr_name, local, broadcast);
|
||||
nInterfaces++;
|
||||
}
|
||||
@ -187,7 +189,6 @@ lsif(void) {
|
||||
int
|
||||
doifaddrs(void) {
|
||||
struct ifaddrs *ifaddr, *ifa;
|
||||
char addrtxt[INET_ADDRSTRLEN], bcasttxt[INET_ADDRSTRLEN];
|
||||
char *name;
|
||||
struct sockaddr_in local, netmask, broadcast;
|
||||
|
||||
@ -217,10 +218,12 @@ doifaddrs(void) {
|
||||
/* Compute broadcast address */
|
||||
broadcast.sin_addr.s_addr |= (~netmask.sin_addr.s_addr);
|
||||
|
||||
assert(inet_ntop(AF_INET, (const void *)&local.sin_addr, addrtxt, INET_ADDRSTRLEN) != NULL);
|
||||
assert(inet_ntop(AF_INET, (const void *)&broadcast.sin_addr, bcasttxt, INET_ADDRSTRLEN) != NULL);
|
||||
|
||||
if (debug & DEBUG_OVERLAYINTERFACES) INFOF("name=%s addr=%s broad=%s", name, addrtxt, bcasttxt);
|
||||
if (debug & DEBUG_OVERLAYINTERFACES){
|
||||
char addrtxt[INET_ADDRSTRLEN], bcasttxt[INET_ADDRSTRLEN];
|
||||
assert(inet_ntop(AF_INET, (const void *)&local.sin_addr, addrtxt, INET_ADDRSTRLEN) != NULL);
|
||||
assert(inet_ntop(AF_INET, (const void *)&broadcast.sin_addr, bcasttxt, INET_ADDRSTRLEN) != NULL);
|
||||
INFOF("name=%s addr=%s broad=%s", name, addrtxt, bcasttxt);
|
||||
}
|
||||
|
||||
overlay_interface_register(name,local,broadcast);
|
||||
}
|
||||
|
@ -77,7 +77,8 @@ int app_monitor_cli(int argc, const char *const *argv, struct command_line_optio
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
addr.sun_path[0]=0;
|
||||
snprintf(&addr.sun_path[1],100,"org.servalproject.servald.monitor.socket");
|
||||
snprintf(&addr.sun_path[1],100,
|
||||
confValueGet("monitor.socket",DEFAULT_MONITOR_SOCKET_NAME));
|
||||
int len = 1+strlen(&addr.sun_path[1]) + sizeof(addr.sun_family);
|
||||
char *p=(char *)&addr;
|
||||
printf("last char='%c' %02x\n",p[len-1],p[len-1]);
|
||||
|
18
monitor.c
18
monitor.c
@ -84,14 +84,19 @@ int monitor_setup_sockets()
|
||||
}
|
||||
|
||||
#ifdef linux
|
||||
/* Use abstract namespace as Android has no writable FS which supports sockets */
|
||||
/* Use abstract namespace as Android has no writable FS which supports sockets.
|
||||
Abstract namespace is just plain better, anyway, as no dead files end up
|
||||
hanging around. */
|
||||
name.sun_path[0]=0;
|
||||
/* XXX: 104 comes from OSX sys/un.h - no #define (note Linux has UNIX_PATH_MAX and it's 108(!)) */
|
||||
snprintf(&name.sun_path[1],104-2,"org.servalproject.servald.monitor.socket");
|
||||
snprintf(&name.sun_path[1],104-2,
|
||||
confValueGet("monitor.socket",DEFAULT_MONITOR_SOCKET_NAME));
|
||||
/* Doesn't include trailing nul */
|
||||
len = 1+strlen(&name.sun_path[1]) + sizeof(name.sun_family);
|
||||
#else
|
||||
snprintf(name.sun_path,104-1,"%s/org.servalproject.servald.monitor.socket",serval_instancepath());
|
||||
snprintf(name.sun_path,104-1,"%s/",
|
||||
serval_instancepath(),
|
||||
confValueGet("monitor.socket",DEFAULT_MONITOR_SOCKET_NAME));
|
||||
unlink(name.sun_path);
|
||||
/* Includes trailing nul */
|
||||
len = 1+strlen(name.sun_path) + sizeof(name.sun_family);
|
||||
@ -520,8 +525,8 @@ int monitor_process_data(int index)
|
||||
|
||||
if (vomp_sample_size(c->sample_codec)!=c->data_offset)
|
||||
return
|
||||
WHYF("Ignoring sample block of incorrect size (expected %d, got %d bytes)",
|
||||
vomp_sample_size(c->sample_codec)!=c->data_offset);
|
||||
WHYF("Ignoring sample block of incorrect size (expected %d, got %d bytes for codec %d)",
|
||||
vomp_sample_size(c->sample_codec), c->data_offset, c->sample_codec);
|
||||
|
||||
fcntl(c->socket,F_SETFL,
|
||||
fcntl(c->socket, F_GETFL, NULL)|O_NONBLOCK);
|
||||
@ -723,7 +728,8 @@ int server_probe(int *pid)
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
addr.sun_path[0]=0;
|
||||
snprintf(&addr.sun_path[1],100,"org.servalproject.servald.monitor.socket");
|
||||
snprintf(&addr.sun_path[1],100,
|
||||
confValueGet("monitor.socket",DEFAULT_MONITOR_SOCKET_NAME));
|
||||
int len = 1+strlen(&addr.sun_path[1]) + sizeof(addr.sun_family);
|
||||
char *p=(char *)&addr;
|
||||
if (0) DEBUGF("last char='%c' %02x\n",p[len-1],p[len-1]);
|
||||
|
74
overlay.c
74
overlay.c
@ -70,6 +70,41 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#include "serval.h"
|
||||
|
||||
/* @PGS/20120615 */
|
||||
int last_valid=0;
|
||||
int last_line;
|
||||
const char *last_file;
|
||||
const char *last_func;
|
||||
long long last_time;
|
||||
|
||||
/* @PGS/20120615 */
|
||||
void TIMING_PAUSE()
|
||||
{
|
||||
last_valid=0;
|
||||
}
|
||||
|
||||
/* @PGS/20120615 */
|
||||
void _TIMING_CHECK(const char *file,const char *func,int line)
|
||||
{
|
||||
long long now=overlay_gettime_ms();
|
||||
if (last_valid) {
|
||||
if (now-last_time>5) {
|
||||
// More than 5ms spent in a given task, complain
|
||||
char msg[1024];
|
||||
snprintf(msg,1024,"Spent %lldms between %s:%d in %s() and here",
|
||||
now-last_time,last_file,last_line,last_func);
|
||||
logMessage(LOG_LEVEL_WARN,file,line,func,"%s",msg);
|
||||
}
|
||||
}
|
||||
|
||||
last_valid=1;
|
||||
last_file=file;
|
||||
last_func=func;
|
||||
last_line=line;
|
||||
last_time=now;
|
||||
}
|
||||
|
||||
|
||||
int overlayMode=0;
|
||||
|
||||
overlay_txqueue overlay_tx[OQ_MAX];
|
||||
@ -121,23 +156,31 @@ int overlayServerMode()
|
||||
|
||||
while(1) {
|
||||
|
||||
TIMING_CHECK();
|
||||
|
||||
server_shutdown_check();
|
||||
|
||||
TIMING_CHECK();
|
||||
|
||||
/* Work out how long we can wait before we need to tick */
|
||||
long long ms=overlay_time_until_next_tick();
|
||||
memabuseCheck();
|
||||
TIMING_CHECK();
|
||||
//int filesPresent=0;
|
||||
fds[0].fd=sock; fds[0].events=POLLIN;
|
||||
fdcount=1;
|
||||
rhizome_server_get_fds(fds,&fdcount,128);
|
||||
TIMING_CHECK();
|
||||
rhizome_fetching_get_fds(fds,&fdcount,128);
|
||||
TIMING_CHECK();
|
||||
overlay_mdp_get_fds(fds,&fdcount,128);
|
||||
TIMING_CHECK();
|
||||
monitor_get_fds(fds,&fdcount,128);
|
||||
TIMING_CHECK();
|
||||
|
||||
for(i=0;i<overlay_interface_count;i++)
|
||||
{
|
||||
/* Make socket non-blocking so that poll() behaves correctly.
|
||||
We then set non-blocking before actually reading from it */
|
||||
/* Make socket blocking so that poll() behaves correctly. */
|
||||
fcntl(overlay_interfaces[i].fd, F_SETFL,
|
||||
fcntl(overlay_interfaces[i].fd, F_GETFL, NULL)&(~O_NONBLOCK));
|
||||
|
||||
@ -159,7 +202,8 @@ int overlayServerMode()
|
||||
if (ms>5) ms=5;
|
||||
}
|
||||
}
|
||||
|
||||
TIMING_CHECK();
|
||||
|
||||
/* Progressively update link scores to neighbours etc, and find out how long before
|
||||
we should next tick the route table.
|
||||
Basically the faster the CPU and the sparser the route table, the less often we
|
||||
@ -169,9 +213,15 @@ int overlayServerMode()
|
||||
int vomp_tick_time=vomp_tick_interval();
|
||||
if (ms>vomp_tick_time) ms=vomp_tick_time;
|
||||
|
||||
TIMING_CHECK();
|
||||
if (debug&DEBUG_VERBOSE_IO)
|
||||
DEBUGF("Waiting via poll() for up to %lldms", ms);
|
||||
TIMING_PAUSE();
|
||||
/* Sanity check maximum poll timeout */
|
||||
if (ms<1) ms=1;
|
||||
if (ms>15000) ms=15000;
|
||||
int r = poll(fds, fdcount, ms);
|
||||
TIMING_CHECK();
|
||||
if (r == -1)
|
||||
WHY_perror("poll");
|
||||
else if (debug&DEBUG_VERBOSE_IO) {
|
||||
@ -182,7 +232,9 @@ int overlayServerMode()
|
||||
DEBUGF("fd #%d is ready (0x%x)\n", fds[i].fd, fds[i].revents);
|
||||
}
|
||||
/* Do high-priority audio handling first */
|
||||
TIMING_CHECK();
|
||||
vomp_tick();
|
||||
TIMING_CHECK();
|
||||
|
||||
if (r > 0) {
|
||||
/* We have data, so try to receive it */
|
||||
@ -204,27 +256,43 @@ int overlayServerMode()
|
||||
|
||||
}
|
||||
}
|
||||
TIMING_CHECK();
|
||||
overlay_rx_messages();
|
||||
TIMING_CHECK();
|
||||
if (rhizome_enabled()) {
|
||||
TIMING_CHECK();
|
||||
rhizome_server_poll();
|
||||
TIMING_CHECK();
|
||||
rhizome_fetch_poll();
|
||||
TIMING_CHECK();
|
||||
overlay_mdp_poll();
|
||||
TIMING_CHECK();
|
||||
monitor_poll();
|
||||
TIMING_CHECK();
|
||||
}
|
||||
} else {
|
||||
/* No data before tick occurred, so do nothing.
|
||||
Well, for now let's just check anyway. */
|
||||
if (debug&DEBUG_IO) fprintf(stderr,"poll() timeout.\n");
|
||||
TIMING_CHECK();
|
||||
overlay_rx_messages();
|
||||
TIMING_CHECK();
|
||||
if (rhizome_enabled()) {
|
||||
TIMING_CHECK();
|
||||
rhizome_server_poll();
|
||||
TIMING_CHECK();
|
||||
rhizome_fetch_poll();
|
||||
TIMING_CHECK();
|
||||
overlay_mdp_poll();
|
||||
TIMING_CHECK();
|
||||
monitor_poll();
|
||||
TIMING_CHECK();
|
||||
}
|
||||
}
|
||||
TIMING_CHECK();
|
||||
/* Check if we need to trigger any ticks on any interfaces */
|
||||
overlay_check_ticks();
|
||||
TIMING_CHECK();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -17,6 +17,7 @@ along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include "serval.h"
|
||||
|
||||
@ -113,7 +114,7 @@ int overlay_interface_arg(char *arg)
|
||||
if (!r) return WHY("calloc(struct interface rules),1) failed");
|
||||
|
||||
|
||||
if (sscanf(arg,"%[+-]%n%[^=+-]%n=%[^:]%n:%d%n:%[^:]%n",
|
||||
if (sscanf(arg,"%[+-]%n%[^=:,]%n=%[^:]%n:%d%n:%[^:]%n",
|
||||
sign,&n,interface_name,&n,typestring,&n,&port,&n,speed,&n)>=1)
|
||||
{
|
||||
if (n<strlen(arg)) { free(r); return WHY("Extra junk at end of interface specification"); }
|
||||
@ -180,17 +181,19 @@ int overlay_interface_args(const char *arg)
|
||||
|
||||
int
|
||||
overlay_interface_init_socket(int interface, struct sockaddr_in src_addr, struct sockaddr_in broadcast) {
|
||||
char srctxt[INET_ADDRSTRLEN];
|
||||
|
||||
#define I(X) overlay_interfaces[interface].X
|
||||
I(broadcast_address) = broadcast;
|
||||
I(fileP) = 0;
|
||||
|
||||
I(fd) = socket(PF_INET,SOCK_DGRAM,0);
|
||||
if (I(fd)<0) {
|
||||
if (I(fd) < 0) {
|
||||
WHY_perror("socket()");
|
||||
WHYF("Could not create UDP socket for interface: %s",strerror(errno));
|
||||
goto error;
|
||||
} else
|
||||
WHYF("interface #%d fd=%d",interface,I(fd));
|
||||
INFOF("interface #%d fd=%d",interface, I(fd));
|
||||
|
||||
int reuseP = 1;
|
||||
if (setsockopt(I(fd), SOL_SOCKET, SO_REUSEADDR, &reuseP, sizeof(reuseP)) < 0) {
|
||||
@ -214,18 +217,20 @@ overlay_interface_init_socket(int interface, struct sockaddr_in src_addr, struct
|
||||
a bad signal. */
|
||||
fcntl(I(fd), F_SETFL, fcntl(I(fd), F_GETFL, NULL) | O_CLOEXEC);
|
||||
|
||||
/* @PGS/20120615
|
||||
Use the broadcast address, so that we can reliably receive broadcast
|
||||
traffic on all platforms. BUT on OSX we really need a non-broadcast socket
|
||||
to send from, because you cannot send from a broadcast socket on OSX it seems.
|
||||
*/
|
||||
broadcast.sin_family = AF_INET;
|
||||
broadcast.sin_port = htons(I(port));
|
||||
/* XXX Is this right? Are we really setting the local side address?
|
||||
I was in a plane when at the time, so couldn't Google it.
|
||||
*/
|
||||
if (debug&DEBUG_PACKETRX) fprintf(stderr,"src_addr=%08x\n",(unsigned int)src_addr.sin_addr.s_addr);
|
||||
if (bind(I(fd),(struct sockaddr *)&src_addr,sizeof(src_addr))) {
|
||||
if (bind(I(fd), (struct sockaddr *)&broadcast, sizeof(broadcast))) {
|
||||
WHY_perror("bind");
|
||||
WHY("MP HLR server could not bind to requested UDP port (bind() failed)");
|
||||
goto error;
|
||||
}
|
||||
if (debug&(DEBUG_PACKETRX|DEBUG_IO)) fprintf(stderr,"Bound to port 0x%04x\n",src_addr.sin_port);
|
||||
assert(inet_ntop(AF_INET, (const void *)&broadcast.sin_addr, srctxt, INET_ADDRSTRLEN) != NULL);
|
||||
if (debug & (DEBUG_PACKETRX | DEBUG_IO)) INFOF("Bound to %s:%d", srctxt, ntohs(broadcast.sin_port));
|
||||
|
||||
return 0;
|
||||
|
||||
@ -266,9 +271,18 @@ int overlay_interface_init(char *name,struct sockaddr_in src_addr,struct sockadd
|
||||
if (name[0]=='>') {
|
||||
I(fileP)=1;
|
||||
char dummyfile[1024];
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(dummyfile, &name[1]) || (I(fd) = open(dummyfile,O_APPEND|O_RDWR)) < 1) {
|
||||
if (name[1]=='/') {
|
||||
/* Absolute path */
|
||||
snprintf(dummyfile,1024,"%s",&name[1]);
|
||||
} else
|
||||
/* Relative to instance path */
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(dummyfile, &name[1]))
|
||||
return WHY("could not form dummy interfance name");
|
||||
|
||||
if ((I(fd) = open(dummyfile,O_APPEND|O_RDWR)) < 1) {
|
||||
return WHY("could not open dummy interface file for append");
|
||||
}
|
||||
|
||||
/* Seek to end of file as initial reading point */
|
||||
I(offset)=lseek(I(fd),0,SEEK_END); /* socket gets reused to hold file offset */
|
||||
/* XXX later add pretend location information so that we can decide which "packets" to receive
|
||||
@ -360,7 +374,6 @@ int overlay_rx_messages()
|
||||
} else {
|
||||
/* Read from UDP socket */
|
||||
int recvttl=1;
|
||||
errno=0;
|
||||
plen=recvwithttl(overlay_interfaces[i].fd,packet,sizeof(packet),
|
||||
&recvttl,&src_addr,&addrlen);
|
||||
if (plen<0) {
|
||||
@ -433,9 +446,14 @@ int overlay_broadcast_ensemble(int interface_number,
|
||||
if (overlay_interfaces[interface_number].fileP)
|
||||
{
|
||||
char buf[2048];
|
||||
bzero(&buf[0],128);
|
||||
/* Version information */
|
||||
buf[0]=1; buf[1]=0;
|
||||
buf[2]=0; buf[3]=0;
|
||||
/* PID of creator */
|
||||
buf[4]=getpid()&0xff; buf[5]=getpid()>>8;
|
||||
|
||||
/* TODO make a structure for all this stuff */
|
||||
/* bytes 4-5 = half-power beam height (uint16) */
|
||||
/* bytes 6-7 = half-power beam width (uint16) */
|
||||
/* bytes 8-11 = range in metres, centre beam (uint32) */
|
||||
@ -564,69 +582,72 @@ overlay_interface_register(char *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
time_t overlay_last_interface_discover_time=0;
|
||||
int overlay_interface_discover()
|
||||
{
|
||||
int have_route;
|
||||
|
||||
/* Don't waste too much time and effort on interface discovery,
|
||||
especially if we can't attach to a given interface for some reason. */
|
||||
if (overlay_last_interface_discover_time>time(0))
|
||||
overlay_last_interface_discover_time=time(0);
|
||||
if ((time(0)-overlay_last_interface_discover_time)<2) return 0;
|
||||
overlay_last_interface_discover_time=time(0);
|
||||
static time_t overlay_last_interface_discover_time = 0;
|
||||
int
|
||||
overlay_interface_discover(void) {
|
||||
int no_route, i;
|
||||
time_t now;
|
||||
struct interface_rules *r;
|
||||
struct sockaddr_in dummyaddr;
|
||||
|
||||
/* Don't waste too much time and effort on interface discovery,
|
||||
especially if we can't attach to a given interface for some reason. */
|
||||
now = time(NULL);
|
||||
if (overlay_last_interface_discover_time > now)
|
||||
overlay_last_interface_discover_time = now;
|
||||
|
||||
/* The Android ndk doesn't have ifaddrs.h, so we have to use the netlink interface.
|
||||
However, netlink is only available on Linux, so for BSD systems, e.g., Mac, we
|
||||
need to use the ifaddrs method.
|
||||
if ((now - overlay_last_interface_discover_time) < 2)
|
||||
return 0;
|
||||
|
||||
Also, ifaddrs will work on non-linux systems which is considered critical.
|
||||
*/
|
||||
overlay_last_interface_discover_time = now;
|
||||
|
||||
/* Mark all interfaces as not observed, so that we know if we need to cull any */
|
||||
int i;
|
||||
for(i=0;i<overlay_interface_count;i++) overlay_interfaces[i].observed--;
|
||||
for(i = 0; i < overlay_interface_count; i++)
|
||||
overlay_interfaces[i].observed = 0;
|
||||
|
||||
/* Check through for any virtual dummy interfaces */
|
||||
struct interface_rules *r=interface_filter;
|
||||
while(r) {
|
||||
if (r->namespec[0]=='>') {
|
||||
for(i=0;i<overlay_interface_count;i++) if (!strcasecmp(overlay_interfaces[i].name,r->namespec)) break;
|
||||
if (i<overlay_interface_count)
|
||||
/* We already know about this interface, so just update it */
|
||||
overlay_interfaces[i].observed=1;
|
||||
else {
|
||||
/* New interface, so register it */
|
||||
struct sockaddr_in dummyaddr;
|
||||
if (overlay_interface_init(r->namespec,dummyaddr,dummyaddr,
|
||||
1000000,PORT_DNA,OVERLAY_INTERFACE_WIFI))
|
||||
{ if (debug&DEBUG_OVERLAYINTERFACES)
|
||||
WHY("Could not initialise newly seen interface"); }
|
||||
else
|
||||
if (debug&DEBUG_OVERLAYINTERFACES) fprintf(stderr,"Registered interface %s\n",r->namespec);
|
||||
}
|
||||
for (r = interface_filter; r != NULL; r = r->next) {
|
||||
if (r->namespec[0] != '>')
|
||||
continue;
|
||||
|
||||
for(i = 0; i < overlay_interface_count; i++)
|
||||
if (!strcasecmp(overlay_interfaces[i].name,r->namespec))
|
||||
break;
|
||||
|
||||
if (i < overlay_interface_count)
|
||||
/* We already know about this interface, so just update it */
|
||||
overlay_interfaces[i].observed = 1;
|
||||
else {
|
||||
/* New interface, so register it */
|
||||
if (overlay_interface_init(r->namespec,dummyaddr,dummyaddr,
|
||||
1000000,PORT_DNA,OVERLAY_INTERFACE_WIFI)) {
|
||||
if (debug & DEBUG_OVERLAYINTERFACES) WHYF("Could not initialise newly seen interface %s", r->namespec);
|
||||
}
|
||||
else
|
||||
if (debug & DEBUG_OVERLAYINTERFACES) INFOF("Registered interface %s",r->namespec);
|
||||
}
|
||||
r=r->next;
|
||||
}
|
||||
have_route = 1;
|
||||
|
||||
/* Look for real interfaces */
|
||||
no_route = 1;
|
||||
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
if (have_route != 0)
|
||||
have_route = doifaddrs();
|
||||
if (no_route != 0)
|
||||
no_route = doifaddrs();
|
||||
#endif
|
||||
|
||||
#ifdef SIOCGIFCONF
|
||||
if (have_route != 0)
|
||||
have_route = lsif();
|
||||
if (no_route != 0)
|
||||
no_route = lsif();
|
||||
#endif
|
||||
|
||||
#ifdef linux
|
||||
if (have_route != 0)
|
||||
have_route = scrapeProcNetRoute();
|
||||
if (no_route != 0)
|
||||
no_route = scrapeProcNetRoute();
|
||||
#endif
|
||||
|
||||
if (have_route != 0) {
|
||||
FATAL("Unable to get any routing information");
|
||||
if (no_route != 0) {
|
||||
FATAL("Unable to get any interface information");
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -781,9 +802,12 @@ int overlay_queue_dump(overlay_txqueue *q)
|
||||
int overlay_tick_interface(int i, long long now)
|
||||
{
|
||||
int frame_pax=0;
|
||||
overlay_buffer *e=NULL;
|
||||
#define MAX_FRAME_PAX 1024
|
||||
overlay_frame *pax[MAX_FRAME_PAX];
|
||||
|
||||
TIMING_CHECK();
|
||||
|
||||
if (overlay_interfaces[i].bits_per_second<1) {
|
||||
/* An interface with no speed budget is for listening only, so doesn't get ticked */
|
||||
return 0;
|
||||
@ -794,7 +818,7 @@ int overlay_tick_interface(int i, long long now)
|
||||
/* Get a buffer ready, and limit it's size appropriately.
|
||||
XXX size limit should be reduced from MTU.
|
||||
XXX we should also take account of the volume of data likely to be in the TX buffer. */
|
||||
overlay_buffer *e=ob_new(overlay_interfaces[i].mtu);
|
||||
e=ob_new(overlay_interfaces[i].mtu);
|
||||
if (!e) return WHY("ob_new() failed");
|
||||
ob_limitsize(e,overlay_interfaces[i].mtu/4);
|
||||
|
||||
@ -803,7 +827,7 @@ int overlay_tick_interface(int i, long long now)
|
||||
unsigned char bytes[]={/* Magic */ 'O',0x10,
|
||||
/* Version */ 0x00,0x01};
|
||||
if (ob_append_bytes(e,bytes,4)) {
|
||||
ob_free(e);
|
||||
ob_free(e);
|
||||
return WHY("ob_append_bytes() refused to append magic bytes.");
|
||||
}
|
||||
|
||||
@ -820,6 +844,7 @@ int overlay_tick_interface(int i, long long now)
|
||||
Give priority to newly observed nodes so that good news travels quickly to help roaming.
|
||||
XXX - Don't forget about PONGing reachability reports to allow use of monodirectional links.
|
||||
*/
|
||||
TIMING_CHECK();
|
||||
overlay_stuff_packet_from_queue(i,e,OQ_MESH_MANAGEMENT,now,pax,&frame_pax,MAX_FRAME_PAX);
|
||||
|
||||
/* We previously limited manifest space to 3/4 of MTU, but that causes problems for
|
||||
@ -828,23 +853,30 @@ int overlay_tick_interface(int i, long long now)
|
||||
#warning reduce to <= mtu*3/4 once we have compacty binary canonical manifest format
|
||||
ob_limitsize(e,overlay_interfaces[i].mtu*4/4);
|
||||
|
||||
TIMING_CHECK();
|
||||
|
||||
/* Add advertisements for ROUTES not Rhizome bundles.
|
||||
Rhizome bundle advertisements are lower priority */
|
||||
overlay_route_add_advertisements(i,e);
|
||||
|
||||
ob_limitsize(e,overlay_interfaces[i].mtu);
|
||||
|
||||
TIMING_CHECK();
|
||||
|
||||
/* 4. XXX Add lower-priority queued data */
|
||||
overlay_stuff_packet_from_queue(i,e,OQ_ISOCHRONOUS_VIDEO,now,pax,&frame_pax,MAX_FRAME_PAX);
|
||||
overlay_stuff_packet_from_queue(i,e,OQ_ORDINARY,now,pax,&frame_pax,MAX_FRAME_PAX);
|
||||
overlay_stuff_packet_from_queue(i,e,OQ_OPPORTUNISTIC,now,pax,&frame_pax,MAX_FRAME_PAX);
|
||||
/* 5. XXX Fill the packet up to a suitable size with anything that seems a good idea */
|
||||
TIMING_CHECK();
|
||||
if (rhizome_enabled())
|
||||
overlay_rhizome_add_advertisements(i,e);
|
||||
|
||||
if (debug&DEBUG_PACKETCONSTRUCTION)
|
||||
dump("assembled packet",&e->bytes[0],e->length);
|
||||
|
||||
TIMING_CHECK();
|
||||
|
||||
/* Now send the frame. This takes the form of a special DNA packet with a different
|
||||
service code, which we setup earlier. */
|
||||
if (debug&DEBUG_OVERLAYINTERFACES)
|
||||
@ -923,10 +955,14 @@ int overlay_tick_interface(int i, long long now)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (e) ob_free(e); e=NULL;
|
||||
return 0;
|
||||
}
|
||||
else return WHY("overlay_broadcast_ensemble() failed");
|
||||
|
||||
else {
|
||||
if (e) ob_free(e); e=NULL;
|
||||
return WHY("overlay_broadcast_ensemble() failed");
|
||||
}
|
||||
TIMING_CHECK();
|
||||
}
|
||||
|
||||
|
||||
@ -936,15 +972,18 @@ overlay_check_ticks(void) {
|
||||
/* Check if any interface(s) are due for a tick */
|
||||
int i;
|
||||
|
||||
TIMING_CHECK();
|
||||
/* Check for changes to interfaces */
|
||||
overlay_interface_discover();
|
||||
|
||||
TIMING_CHECK();
|
||||
|
||||
long long now = overlay_gettime_ms();
|
||||
|
||||
/* Now check if the next tick time for the interfaces is no later than that time.
|
||||
If so, trigger a tick on the interface. */
|
||||
if (debug & DEBUG_OVERLAYINTERFACES) INFOF("Examining %d interfaces.",overlay_interface_count);
|
||||
for(i = 0; i < overlay_interface_count; i++) {
|
||||
TIMING_CHECK();
|
||||
/* Only tick live interfaces */
|
||||
if (overlay_interfaces[i].observed > 0) {
|
||||
if (debug & DEBUG_VERBOSE_IO) INFOF("Interface %s ticks every %dms, last at %lld.",
|
||||
@ -952,12 +991,16 @@ overlay_check_ticks(void) {
|
||||
overlay_interfaces[i].tick_ms,
|
||||
overlay_interfaces[i].last_tick_ms);
|
||||
if (now >= overlay_interfaces[i].last_tick_ms + overlay_interfaces[i].tick_ms) {
|
||||
/* This interface is due for a tick */
|
||||
overlay_tick_interface(i, now);
|
||||
overlay_interfaces[i].last_tick_ms = now;
|
||||
TIMING_CHECK();
|
||||
|
||||
/* This interface is due for a tick */
|
||||
overlay_tick_interface(i, now);
|
||||
TIMING_CHECK();
|
||||
overlay_interfaces[i].last_tick_ms = now;
|
||||
}
|
||||
} else
|
||||
if (debug & DEBUG_VERBOSE_IO) INFOF("Interface %s is awol.", overlay_interfaces[i].name);
|
||||
if (debug & DEBUG_VERBOSE_IO) INFOF("Interface %s is awol.", overlay_interfaces[i].name);
|
||||
TIMING_CHECK();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
113
overlay_mdp.c
113
overlay_mdp.c
@ -42,7 +42,8 @@ int overlay_mdp_setup_sockets()
|
||||
/* XXX The 100 should be replaced with the actual maximum allowed.
|
||||
Apparently POSIX requires it to be at least 100, but I would still feel
|
||||
more comfortable with using the appropriate constant. */
|
||||
snprintf(&name.sun_path[1],100,"org.servalproject.mesh.overlay.mdp");
|
||||
snprintf(&name.sun_path[1],100,
|
||||
confValueGet("mdp.socket",DEFAULT_MDP_SOCKET_NAME);
|
||||
len = 1+strlen(&name.sun_path[1]) + sizeof(name.sun_family);
|
||||
|
||||
mdp_abstract_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
@ -476,10 +477,20 @@ int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
|
||||
}
|
||||
if (match>-1) {
|
||||
struct sockaddr_un addr;
|
||||
printf("unix domain socket '%s'\n",mdp_bindings_sockets[match]);
|
||||
bcopy(mdp_bindings_sockets[match],&addr.sun_path[0],mdp_bindings_socket_name_lengths[match]);
|
||||
addr.sun_family=AF_UNIX;
|
||||
int r=sendto(mdp_named_socket,mdp,overlay_mdp_relevant_bytes(mdp),0,(struct sockaddr*)&addr,sizeof(addr));
|
||||
if (r==overlay_mdp_relevant_bytes(mdp)) return 0;
|
||||
errno=0;
|
||||
int len=overlay_mdp_relevant_bytes(mdp);
|
||||
int r=sendto(mdp_named_socket,mdp,len,0,(struct sockaddr*)&addr,sizeof(addr));
|
||||
if (r==overlay_mdp_relevant_bytes(mdp)) {
|
||||
return 0;
|
||||
}
|
||||
if (errno==ENOENT) {
|
||||
/* far-end of socket has died, so drop binding */
|
||||
printf("Closing dead MDP client '%s'\n",mdp_bindings_sockets[match]);
|
||||
overlay_mdp_releasebindings(&addr,mdp_bindings_socket_name_lengths[match]);
|
||||
}
|
||||
WHY_perror("sendto(e)");
|
||||
return WHY("Failed to pass received MDP frame to client");
|
||||
} else {
|
||||
@ -505,12 +516,22 @@ int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
|
||||
/* make sure it is null terminated */
|
||||
did[pll]=0;
|
||||
/* remember source sid for putting back later */
|
||||
unsigned char srcsid[32];
|
||||
bcopy(&mdp->out.src.sid[0],&srcsid[0],SID_SIZE);
|
||||
/* now switch addresses around for any replies */
|
||||
overlay_mdp_swap_src_dst(mdp);
|
||||
overlay_mdp_frame mdpreply;
|
||||
|
||||
int results=0;
|
||||
while(keyring_find_did(keyring,&cn,&in,&kp,did))
|
||||
{
|
||||
bzero(&mdpreply,sizeof(mdpreply));
|
||||
|
||||
/* mark as outgoing MDP message */
|
||||
mdpreply.packetTypeAndFlags=MDP_TX;
|
||||
|
||||
/* Set source and destination addresses */
|
||||
bcopy(&mdp->out.dst.sid,mdpreply.out.src.sid,SID_SIZE);
|
||||
bcopy(&mdp->out.src.sid,mdpreply.out.dst.sid,SID_SIZE);
|
||||
mdpreply.out.src.port=mdp->out.dst.port;
|
||||
mdpreply.out.dst.port=mdp->out.src.port;
|
||||
|
||||
/* package DID and Name into reply (we include the DID because
|
||||
it could be a wild-card DID search, but the SID is implied
|
||||
in the source address of our reply). */
|
||||
@ -518,46 +539,42 @@ int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
|
||||
->private_key_len>64)
|
||||
/* skip excessively long DID records */
|
||||
continue;
|
||||
/* copy SID out into source address of frame */
|
||||
/* and null-terminated DID */
|
||||
bcopy(&keyring->contexts[cn]->identities[in]->keypairs[0]
|
||||
->public_key[0],&mdp->out.src.sid[0],SID_SIZE);
|
||||
bcopy(keyring->contexts[cn]->identities[in]->keypairs[kp]
|
||||
->private_key,&mdp->out.payload[0],
|
||||
keyring->contexts[cn]->identities[in]->keypairs[kp]
|
||||
->private_key_len);
|
||||
bcopy(keyring->contexts[cn]->identities[in]->keypairs[kp]
|
||||
->public_key,&mdp->out.payload[keyring
|
||||
->contexts[cn]
|
||||
->identities[in]
|
||||
->keypairs[kp]
|
||||
->private_key_len],
|
||||
keyring->contexts[cn]->identities[in]->keypairs[kp]
|
||||
->private_key_len);
|
||||
/* set length */
|
||||
mdp->out.payload_length=
|
||||
unsigned char *unpackedDid=
|
||||
keyring->contexts[cn]->identities[in]->keypairs[kp]
|
||||
->private_key_len
|
||||
+keyring->contexts[cn]->identities[in]->keypairs[kp]
|
||||
->public_key_len;
|
||||
/* mark as outgoing MDP message */
|
||||
mdp->packetTypeAndFlags&=MDP_FLAG_MASK;
|
||||
mdp->packetTypeAndFlags|=MDP_TX;
|
||||
overlay_mdp_dispatch(mdp,0 /* system generated */,
|
||||
NULL,0);
|
||||
kp++;
|
||||
->private_key;
|
||||
unsigned char *packedSid=
|
||||
keyring->contexts[cn]->identities[in]->keypairs[0]
|
||||
->public_key;
|
||||
char *name=
|
||||
(char *)keyring->contexts[cn]->identities[in]->keypairs[kp]
|
||||
->public_key;
|
||||
/* copy SID out into source address of frame */
|
||||
bcopy(packedSid,&mdpreply.out.src.sid[0],SID_SIZE);
|
||||
/* and build reply as did\nname\nURI<NUL> */
|
||||
snprintf((char *)&mdpreply.out.payload[0],512,"%s\n%s\nsid://%s/%s",
|
||||
unpackedDid,name,overlay_render_sid(packedSid),
|
||||
unpackedDid);
|
||||
mdpreply.out.payload_length=strlen((char *)mdpreply.out.payload)+1;
|
||||
|
||||
/* deliver reply */
|
||||
overlay_mdp_dispatch(&mdpreply,0 /* system generated */,NULL,0);
|
||||
kp++;
|
||||
results++;
|
||||
}
|
||||
/* and switch addresses back around in case the caller was planning on
|
||||
using MDP structure again (this happens if there is a loop-back reply
|
||||
and the frame needs sending on, as happens with broadcasts. MDP ping
|
||||
is a simple application where this occurs).
|
||||
Similarly restore destination address & MDP payload content and
|
||||
length */
|
||||
overlay_mdp_swap_src_dst(mdp);
|
||||
bcopy(&srcsid[0],&mdp->out.src.sid[0],SID_SIZE);
|
||||
bcopy(&did[0],&mdp->out.payload[0],pll);
|
||||
mdp->out.payload_length=pll;
|
||||
if (!results) {
|
||||
/* No local results, so see if servald has been configured to use
|
||||
a DNA-helper that can provide additional mappings. This provides
|
||||
a generalised interface for resolving telephone numbers into URIs.
|
||||
The first use will be for resolving DIDs to SIP addresses for
|
||||
OpenBTS boxes run by the OTI/Commotion project.
|
||||
|
||||
The helper is run asynchronously, and the replies will be delivered
|
||||
when results become available, so this function will return
|
||||
immediately, so as not to cause blockages and delays in servald.
|
||||
*/
|
||||
dna_helper_enqueue(did,mdp->out.src.sid);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
@ -600,7 +617,8 @@ int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
|
||||
default:
|
||||
/* Unbound socket. We won't be sending ICMP style connection refused
|
||||
messages, partly because they are a waste of bandwidth. */
|
||||
return WHY("Received packet for which no listening process exists");
|
||||
return WHYF("Received packet for which no listening process exists (MDP ports: src=%d, dst=%d",
|
||||
mdp->out.src.port,mdp->out.dst.port);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -672,6 +690,8 @@ int overlay_mdp_sanitytest_sourceaddr(sockaddr_mdp *src,int userGeneratedFrameP,
|
||||
|
||||
printf("addr=%s port=%u (0x%x)\n",
|
||||
overlay_render_sid(src->sid),src->port,src->port);
|
||||
if (recvaddr) printf("recvaddr='%s'\n",
|
||||
recvaddr->sun_path);
|
||||
return WHY("No such socket binding:unix domain socket tuple exists -- someone might be trying to spoof someone else's connection");
|
||||
}
|
||||
|
||||
@ -1076,7 +1096,7 @@ int overlay_mdp_relevant_bytes(overlay_mdp_frame *mdp)
|
||||
end of the string, to avoid information leaks */
|
||||
len=&mdp->error.message[0]-(char *)mdp;
|
||||
len+=strlen(mdp->error.message)+1;
|
||||
INFOF("mdp return/error code: %d:%s",mdp->error.error,mdp->error.message);
|
||||
if (mdp->error.error) INFOF("mdp return/error code: %d:%s",mdp->error.error,mdp->error.message);
|
||||
break;
|
||||
case MDP_VOMPEVENT:
|
||||
/* XXX too hard to work out precisely for now. */
|
||||
@ -1138,9 +1158,10 @@ int overlay_mdp_send(overlay_mdp_frame *mdp,int flags,int timeout_ms)
|
||||
mdp->packetTypeAndFlags=MDP_ERROR;
|
||||
mdp->error.error=1;
|
||||
snprintf(mdp->error.message,128,"Timeout waiting for reply to MDP packet (packet was successfully sent).");
|
||||
return WHY("Timeout waiting for server response");
|
||||
return -1; /* WHY("Timeout waiting for server response"); */
|
||||
}
|
||||
|
||||
|
||||
int ttl=-1;
|
||||
if (!overlay_mdp_recv(mdp,&ttl)) {
|
||||
/* If all is well, examine result and return error code provided */
|
||||
|
2
peers.c
2
peers.c
@ -192,7 +192,7 @@ int sendToPeers(unsigned char *packet,int packet_len,int method,int peerId,struc
|
||||
|
||||
bzero(&peer_addr, sizeof(peer_addr));
|
||||
peer_addr.sin_family=AF_INET;
|
||||
peer_addr.sin_port = htons(4110);
|
||||
peer_addr.sin_port = htons(PORT_DNA);
|
||||
|
||||
if (method==REQ_PARALLEL) i=0; else { i=peerId; maxPeer=i; }
|
||||
for(;i<=maxPeer;i++)
|
||||
|
@ -31,8 +31,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
int rhizome_server_socket=-1;
|
||||
int sigPipeFlag=0;
|
||||
int sigIoFlag=0;
|
||||
|
||||
rhizome_http_request *rhizome_live_http_requests[RHIZOME_SERVER_MAX_LIVE_REQUESTS];
|
||||
int rhizome_server_live_request_count=0;
|
||||
@ -62,19 +60,6 @@ unsigned char favicon_bytes[]={
|
||||
,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
int favicon_len=318;
|
||||
|
||||
void sigPipeHandler(int signal)
|
||||
{
|
||||
sigPipeFlag++;
|
||||
return;
|
||||
}
|
||||
|
||||
void sigIoHandler(int signal)
|
||||
{
|
||||
WHY("sigio");
|
||||
sigIoFlag++;
|
||||
return;
|
||||
}
|
||||
|
||||
int rhizome_server_start()
|
||||
{
|
||||
if (rhizome_server_socket>-1) return 0;
|
||||
|
19
serval.h
19
serval.h
@ -114,6 +114,11 @@ struct in_addr {
|
||||
/* bzero(3) is deprecated in favour of memset(3). */
|
||||
#define bzero(addr,len) memset((addr), 0, (len))
|
||||
|
||||
/* @PGS/20120615 */
|
||||
#define TIMING_CHECK() _TIMING_CHECK(__FILE__,__FUNCTION__,__LINE__)
|
||||
void _TIMING_CHECK(const char *file,const char *func,int line);
|
||||
void TIMING_PAUSE();
|
||||
|
||||
/* UDP Port numbers for various Serval services.
|
||||
The overlay mesh works over DNA */
|
||||
#define PORT_DNA 4110
|
||||
@ -1517,3 +1522,17 @@ int stopAudio();
|
||||
#define SERVER_NOTRUNNING 3
|
||||
#define SERVER_RUNNING 4
|
||||
int server_probe(int *pid);
|
||||
|
||||
int dna_helper_enqueue(char *did, unsigned char *requestorSid);
|
||||
int dna_return_resolution(overlay_mdp_frame *mdp, unsigned char *fromSid,
|
||||
const char *did,const char *name,const char *uri);
|
||||
int parseDnaReply(unsigned char *bytes,int count,
|
||||
char *did,char *name,char *uri);
|
||||
|
||||
extern int sigPipeFlag;
|
||||
extern int sigIoFlag;
|
||||
void sigPipeHandler(int signal);
|
||||
void sigIoHandler(int signal);
|
||||
|
||||
#define DEFAULT_MONITOR_SOCKET_NAME "org.servalproject.servald.monitor.socket"
|
||||
#define DEFAULT_MDP_SOCKET_NAME "org.servalproject.servald.mdp.socket"
|
||||
|
33
sighandlers.c
Normal file
33
sighandlers.c
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
Serval Distributed Numbering Architecture (DNA)
|
||||
Copyright (C) 2012 Paul Gardner-Stephen
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
int sigPipeFlag=0;
|
||||
int sigIoFlag=0;
|
||||
|
||||
void sigPipeHandler(int signal)
|
||||
{
|
||||
sigPipeFlag++;
|
||||
return;
|
||||
}
|
||||
|
||||
void sigIoHandler(int signal)
|
||||
{
|
||||
sigIoFlag++;
|
||||
return;
|
||||
}
|
15
testdefs.sh
15
testdefs.sh
@ -191,13 +191,16 @@ signal_all_servald_processes() {
|
||||
# first SIGTERM then SIGHUP and finally SIGKILL
|
||||
# - assert that no more servald processes are running
|
||||
kill_all_servald_processes() {
|
||||
if signal_all_servald_processes TERM; then
|
||||
sleep 2
|
||||
if signal_all_servald_processes HUP; then
|
||||
sleep 2
|
||||
# PGS 20120621 - Made fast so that tests can be run quickly
|
||||
# TODO: Make this better by checking that things really have died, and take
|
||||
# exactly the time required, rather than using fixed delays
|
||||
# if signal_all_servald_processes TERM; then
|
||||
# sleep 2
|
||||
# if signal_all_servald_processes HUP; then
|
||||
# sleep 2
|
||||
signal_all_servald_processes KILL
|
||||
fi
|
||||
fi
|
||||
# fi
|
||||
# fi
|
||||
}
|
||||
|
||||
# Utility function:
|
||||
|
170
tests/dnaprotocol
Executable file
170
tests/dnaprotocol
Executable file
@ -0,0 +1,170 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Tests for Serval DNA server operations.
|
||||
#
|
||||
# Copyright 2012 Paul Gardner-Stephen
|
||||
#
|
||||
# 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"
|
||||
|
||||
setup() {
|
||||
setup_servald
|
||||
assert_no_servald_processes
|
||||
set_instance
|
||||
}
|
||||
|
||||
teardown() {
|
||||
# TODO Disabled until stopping multiple-instances are supported
|
||||
# TODO stop_all_servald_servers
|
||||
kill_all_servald_processes
|
||||
assert_no_servald_processes
|
||||
}
|
||||
|
||||
setup_servald_instance() {
|
||||
set_instance $1
|
||||
executeOk_servald config set interfaces "+>$2"
|
||||
executeOk_servald config set monitor.socket "org.servalproject.servald.monitor.socket.$1"
|
||||
executeOk_servald config set mdp.socket "org.servalproject.servald.mdp.socket.$1"
|
||||
executeOk_servald keyring add
|
||||
assert [ -e "$SERVALINSTANCE_PATH/serval.keyring" ]
|
||||
executeOk_servald keyring list
|
||||
tfw_cat --stdout
|
||||
sid=$(replayStdout | sed -ne "1s/^\($rexp_sid\):.*\$/\1/p")
|
||||
assert --message='main identity known' [ -n "$sid" ]
|
||||
executeOk_servald set did $sid 5550001 "Agent $1 Smith"
|
||||
start_servald_server $1
|
||||
executeOk_servald status
|
||||
tfw_cat --stdout
|
||||
}
|
||||
|
||||
setup_servald_instances() {
|
||||
setup_servald
|
||||
DUMMYNET=/tmp/dummy
|
||||
rm $DUMMYNET
|
||||
touch $DUMMYNET
|
||||
assert [ -e $DUMMYNET ]
|
||||
setup_servald_instance A $DUMMYNET
|
||||
SIDA=$sid
|
||||
setup_servald_instance B $DUMMYNET
|
||||
SIDB=$sid
|
||||
|
||||
# Now make sure that they can see each other
|
||||
sleep 5 # Should be plenty of time
|
||||
set_instance A
|
||||
echo "Dummynet file $DUMMYNET after 5 seconds: "`ls -l $DUMMYNET`
|
||||
executeOk_servald id peers
|
||||
assertStdoutLineCount '==' 1
|
||||
}
|
||||
|
||||
doc_MultipleServalDTest="Can start multiple servald instances communicating via a dummy interface"
|
||||
|
||||
setup_MultipleServalDTest() {
|
||||
setup
|
||||
}
|
||||
|
||||
test_MultipleServalDTest() {
|
||||
setup_servald_instances
|
||||
}
|
||||
|
||||
doc_DNAWildcardSearchFindsSelf="DNA lookup of wildcard finds (star method)"
|
||||
setup_DNAWildcardSearchFindsSelf() {
|
||||
setup
|
||||
}
|
||||
test_DNAWildcardSearchFindsSelf() {
|
||||
setup_servald_instances
|
||||
set_instance A
|
||||
executeOk_servald dna lookup "*"
|
||||
assertStdoutLineCount '==' 2
|
||||
assertStdoutGrep --matches=1 "^sid://$SIDA/5550001:5550001:Agent A Smith$"
|
||||
assertStdoutGrep --matches=1 "^sid://$SIDB/5550001:5550001:Agent B Smith$"
|
||||
}
|
||||
|
||||
doc_DNAWildcardSearchFindsSelfEmpty="DNA lookup of wildcard (empty query method)"
|
||||
setup_DNAWildcardSearchFindsSelfEmpty() {
|
||||
setup
|
||||
}
|
||||
test_DNAWildcardSearchFindsSelfEmpty() {
|
||||
setup_servald_instances
|
||||
set_instance A
|
||||
executeOk_servald dna lookup ""
|
||||
assertStdoutLineCount '==' 2
|
||||
assertStdoutGrep --matches=1 "^sid://$SIDA/5550001:5550001:Agent A Smith$"
|
||||
assertStdoutGrep --matches=1 "^sid://$SIDB/5550001:5550001:Agent B Smith$"
|
||||
}
|
||||
|
||||
doc_DNASpecificLookup="DNA Lookup by phone number"
|
||||
setup_DNASpecificLookup() {
|
||||
setup
|
||||
}
|
||||
test_DNASpecificLookup() {
|
||||
setup_servald_instances
|
||||
set_instance A
|
||||
# Make sure we get no false positives
|
||||
executeOk_servald dna lookup "5551234"
|
||||
assertStdoutLineCount '==' 0
|
||||
executeOk_servald dna lookup "555000"
|
||||
assertStdoutLineCount '==' 0
|
||||
executeOk_servald dna lookup "55500011"
|
||||
assertStdoutLineCount '==' 0
|
||||
# Make sure we get the right results, and no duplicates
|
||||
executeOk_servald dna lookup "5550001"
|
||||
assertStdoutLineCount '==' 2
|
||||
assertStdoutGrep --matches=1 "^sid://$SIDA/5550001:5550001:Agent A Smith$"
|
||||
assertStdoutGrep --matches=1 "^sid://$SIDB/5550001:5550001:Agent B Smith$"
|
||||
}
|
||||
|
||||
doc_DNANodeInfoLocalResolution="'node info' auto-resolves for local identities"
|
||||
setup_DNANodeInfoLocalResolution() {
|
||||
setup
|
||||
}
|
||||
test_DNANodeInfoLocalResolution() {
|
||||
setup_servald_instances
|
||||
set_instance A
|
||||
|
||||
# node info for a local identity returns DID/Name since it is free, even
|
||||
# if it isn't asked for.
|
||||
executeOk_servald node info $SIDA
|
||||
assertStdoutLineCount '==' 1
|
||||
assertStdoutGrep --matches=1 "Agent A Smith"
|
||||
assertStdoutGrep --matches=0 "did-not-resolved"
|
||||
}
|
||||
|
||||
doc_DNANodeInfoRemoteResolution="'node info' for remote identities"
|
||||
setup_DNANodeInfoRemoteResolution() {
|
||||
setup
|
||||
}
|
||||
test_DNANodeInfoRemoteResolution() {
|
||||
setup_servald_instances
|
||||
set_instance A
|
||||
|
||||
# if resolvedid is not specified for a remote identity, then don't resolve
|
||||
# it.
|
||||
executeOk_servald node info $SIDB
|
||||
assertStdoutLineCount '==' 1
|
||||
assertStdoutGrep --matches=0 "Agent B Smith"
|
||||
assertStdoutGrep --matches=1 "did-not-resolved"
|
||||
|
||||
# But if it resolvedid is specified, then do resolve it using DNA
|
||||
executeOk_servald node info $SIDB resolvedid
|
||||
assertStdoutLineCount '==' 1
|
||||
assertStdoutGrep --matches=1 "Agent B Smith"
|
||||
assertStdoutGrep --matches=0 "did-not-resolved"
|
||||
|
||||
}
|
||||
|
||||
|
||||
runTests "$@"
|
Loading…
x
Reference in New Issue
Block a user