Factor out code to fill in a sockaddr_un to a single function and remove overlay_mdp.c's duplicate socket handling (which was incomplete).

All platforms except Android use normal sockets (although this is easy to change and the choice is keyed off a single define).
This gives consistent handling to unix domain sockets which were previously a mishmash where some were always normal, some always abstract and some chose (but in different ways). It also gives consistent error checking.

Doesn't pass tests yet though.
This commit is contained in:
Daniel O'Connor 2012-06-24 00:38:47 +09:30
parent 510711586f
commit c4f19f8a82
10 changed files with 385 additions and 339 deletions

View File

@ -63,7 +63,7 @@ SERVALD_LOCAL_CFLAGS = \
-DHAVE_STRING_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_SOCKET_H=1 \ -DHAVE_STRING_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_SOCKET_H=1 \
-DHAVE_SYS_MMAN_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_POLL_H=1 -DHAVE_NETDB_H=1 \ -DHAVE_SYS_MMAN_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_POLL_H=1 -DHAVE_NETDB_H=1 \
-DHAVE_JNI_H=1 -DHAVE_STRUCT_UCRED=1 -DHAVE_CRYPTO_SIGN_NACL_GE25519_H=1 \ -DHAVE_JNI_H=1 -DHAVE_STRUCT_UCRED=1 -DHAVE_CRYPTO_SIGN_NACL_GE25519_H=1 \
-DBYTE_ORDER=_BYTE_ORDER -DHAVE_LINUX_STRUCT_UCRED \ -DBYTE_ORDER=_BYTE_ORDER -DHAVE_LINUX_STRUCT_UCRED -DUSE_ABSTRACT_NAMESPACE
-I$(NACL_INC) \ -I$(NACL_INC) \
-I$(SQLITE3_INC) -I$(SQLITE3_INC)

View File

@ -51,7 +51,8 @@ SRCS= main.c \
audiodevices.c \ audiodevices.c \
audio_msm_g1.c \ audio_msm_g1.c \
audio_alsa.c \ audio_alsa.c \
audio_reflector.c audio_reflector.c \
socket.c
HAVE_VOIPTEST= @HAVE_VOIPTEST@ HAVE_VOIPTEST= @HAVE_VOIPTEST@
ifeq ($(HAVE_VOIPTEST), 1) ifeq ($(HAVE_VOIPTEST), 1)
@ -76,6 +77,7 @@ CFLAGS+=-Wall -Wno-unused-value
#CFLAGS+=-Wunreachable-code #CFLAGS+=-Wunreachable-code
#CFLAGS+=-O0 #CFLAGS+=-O0
CFLAGS+=-DDO_TIMING_CHECKS CFLAGS+=-DDO_TIMING_CHECKS
#CFLAGS+=-DUSE_ABSTRACT_NAMESPACE
DEFS= @DEFS@ DEFS= @DEFS@

View File

@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <fcntl.h> #include <fcntl.h>
#include "serval.h" #include "serval.h"
#include "socket.h"
char cmd[1024]; char cmd[1024];
int cmdLen=0; int cmdLen=0;
@ -63,6 +64,7 @@ int app_monitor_cli(int argc, const char *const *argv, struct command_line_optio
const char *sid=NULL; const char *sid=NULL;
cli_arg(argc, argv, o, "sid", &sid, NULL, ""); cli_arg(argc, argv, o, "sid", &sid, NULL, "");
struct sockaddr_un addr; struct sockaddr_un addr;
socklen_t len;
if (!strcasecmp(sid,"reflect")) { if (!strcasecmp(sid,"reflect")) {
pipeAudio=1; reflectAudio=1; pipeAudio=1; reflectAudio=1;
@ -75,13 +77,9 @@ int app_monitor_cli(int argc, const char *const *argv, struct command_line_optio
} }
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX; socket_setname(&addr, confValueGet("monitor.socket", DEFAULT_MONITOR_SOCKET_NAME), &len);
addr.sun_path[0]=0;
snprintf(&addr.sun_path[1],100,"%s", INFOF("socket path is \'%s\'", addr.sun_path);
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]);
if (connect(fd, (struct sockaddr*)&addr, len) == -1) { if (connect(fd, (struct sockaddr*)&addr, len) == -1) {
perror("connect"); perror("connect");

View File

@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#include "serval.h" #include "serval.h"
#include "socket.h"
#include "rhizome.h" #include "rhizome.h"
#include <sys/stat.h> #include <sys/stat.h>
@ -63,63 +64,40 @@ int monitor_process_data(int index);
static void monitor_new_socket(int s); static void monitor_new_socket(int s);
int monitor_named_socket = -1; int monitor_named_socket = -1;
int monitor_setup_sockets() int
{ monitor_setup_sockets(void) {
struct sockaddr_un name; int reuseP, send_buffer_size;
int len;
bzero(&name, sizeof(name));
name.sun_family = AF_UNIX;
if (monitor_named_socket != -1) if (monitor_named_socket != -1)
return 0; return 0;
/* ignore SIGPIPE so that we don't explode */ /* ignore SIGPIPE so that we don't explode */
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
if ((monitor_named_socket = socket(AF_UNIX, SOCK_STREAM, 0))==-1) {
WHY_perror("socket");
goto error;
}
#ifdef linux if ((monitor_named_socket = socket_bind(confValueGet("monitor.socket", DEFAULT_MONITOR_SOCKET_NAME))) == -1) {
/* 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,
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/%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);
#endif
if(bind(monitor_named_socket, (struct sockaddr *)&name, len)==-1) {
WHY_perror("bind"); WHY_perror("bind");
goto error; goto error;
} }
if (listen(monitor_named_socket,MAX_MONITOR_SOCKETS) == -1) { if (listen(monitor_named_socket,MAX_MONITOR_SOCKETS) == -1) {
WHY_perror("listen"); WHY_perror("listen");
goto error; goto error;
} }
int reuseP=1; reuseP = 1;
if (setsockopt(monitor_named_socket, SOL_SOCKET, SO_REUSEADDR, if (setsockopt(monitor_named_socket, SOL_SOCKET, SO_REUSEADDR,
&reuseP, sizeof(reuseP)) < 0) { &reuseP, sizeof(reuseP)) < 0) {
WHY_perror("setsockopt"); WHY_perror("setsockopt");
WHY("Could not indicate reuse addresses. Not necessarily a problem (yet)"); goto error;
} }
int send_buffer_size=64*1024; send_buffer_size = 64 * 1024;
if (setsockopt(monitor_named_socket, SOL_SOCKET, SO_RCVBUF, if (setsockopt(monitor_named_socket, SOL_SOCKET, SO_RCVBUF,
&send_buffer_size, sizeof(send_buffer_size))==-1) &send_buffer_size, sizeof(send_buffer_size)) == -1) {
WHY_perror("setsockopt"); WHY_perror("setsockopt");
goto error;
}
if (debug & (DEBUG_IO | DEBUG_VERBOSE_IO)) WHY("Monitor server socket setup"); if (debug & (DEBUG_IO | DEBUG_VERBOSE_IO)) WHY("Monitor server socket setup");
return 0; return 0;
@ -127,6 +105,7 @@ int monitor_setup_sockets()
error: error:
close(monitor_named_socket); close(monitor_named_socket);
monitor_named_socket = -1; monitor_named_socket = -1;
return -1; return -1;
} }

View File

@ -17,98 +17,46 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#include "serval.h" #include "serval.h"
#include "socket.h"
#include <sys/stat.h> #include <sys/stat.h>
int mdp_abstract_socket=-1; int mdp_socket = -1;
int mdp_named_socket=-1;
int overlay_mdp_setup_sockets() int overlay_mdp_setup_sockets()
{ {
struct sockaddr_un name; struct sockaddr_un name;
int len; socklen_t len;
int reuseP, send_buffer_size;
name.sun_family = AF_UNIX; if (mdp_socket != -1)
return 0;
#ifndef HAVE_LINUX_IF_H socket_setname(&name, confValueGet("mdp.socket", DEFAULT_MDP_SOCKET_NAME), &len);
/* Abstrack name space (i.e., non-file represented) unix domain sockets are a
linux-only thing. */
mdp_abstract_socket = -1;
#else
if (mdp_abstract_socket==-1) {
/* Abstract name space unix sockets is a special Linux thing, which is
convenient for us because Android is Linux, but does not have a shared
writable path that is on a UFS partition, so we cannot use traditional
named unix domain sockets. So the abstract name space gives us a solution. */
name.sun_path[0]=0;
/* 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,
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); mdp_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
if (mdp_abstract_socket>-1) { reuseP = 1;
int dud=0; if(setsockopt(mdp_socket, SOL_SOCKET, SO_REUSEADDR,
int reuseP=1; &reuseP, sizeof(reuseP)) < 0) {
if(setsockopt( mdp_abstract_socket, SOL_SOCKET, SO_REUSEADDR,
&reuseP, sizeof(reuseP)) < 0)
{
WARN_perror("setsockopt"); WARN_perror("setsockopt");
WARN("Could not indicate reuse addresses. Not necessarily a problem (yet)"); goto error;
} }
int r=bind(mdp_abstract_socket, (struct sockaddr *)&name, len); if (bind(mdp_socket, (struct sockaddr *)&name, len) == -1) {
if (r) {
WARN_perror("bind"); WARN_perror("bind");
dud=1; goto error;
r=0;
WARN("bind() of abstract name space socket failed (not an error on non-linux systems");
}
if (dud) {
close(mdp_abstract_socket);
mdp_abstract_socket=-1;
WHY("Could not open abstract name-space socket (only a problem on Linux).");
} }
int send_buffer_size=64*1024; send_buffer_size = 64 * 1024;
int res = setsockopt(mdp_abstract_socket, SOL_SOCKET, SO_SNDBUF, if (setsockopt(mdp_socket, SOL_SOCKET, SO_SNDBUF,
&send_buffer_size, sizeof(send_buffer_size)); &send_buffer_size, sizeof(send_buffer_size))) {
}
}
#endif
if (mdp_named_socket==-1) {
if (!form_serval_instance_path(&name.sun_path[0], 100, "mdp.socket")) {
return WHY("Cannot construct name of unix domain socket.");
}
unlink(&name.sun_path[0]);
len = 0+strlen(&name.sun_path[0]) + sizeof(name.sun_family)+1;
mdp_named_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
if (mdp_named_socket>-1) {
int dud=0;
int reuseP=1;
if(setsockopt( mdp_named_socket, SOL_SOCKET, SO_REUSEADDR,
&reuseP, sizeof(reuseP)) < 0)
{
WARN_perror("setsockopt");
WARN("Could not indicate reuse addresses. Not necessarily a problem (yet)");
}
int r=bind(mdp_named_socket, (struct sockaddr *)&name, len);
if (r) { dud=1; r=0; WHY("bind() of named unix domain socket failed"); }
if (dud) {
close(mdp_named_socket);
mdp_named_socket=-1;
WHY("Could not open named unix domain socket.");
}
int send_buffer_size=64*1024;
int res = setsockopt(mdp_named_socket, SOL_SOCKET, SO_RCVBUF,
&send_buffer_size, sizeof(send_buffer_size));
if (res)
WHY_perror("setsockopt"); WHY_perror("setsockopt");
} goto error;
} }
return 0; return 0;
error:
close(mdp_socket);
mdp_socket = -1;
return -1;
} }
int overlay_mdp_get_fds(struct pollfd *fds,int *fdcount,int fdmax) int overlay_mdp_get_fds(struct pollfd *fds,int *fdcount,int fdmax)
@ -116,29 +64,24 @@ int overlay_mdp_get_fds(struct pollfd *fds,int *fdcount,int fdmax)
/* Make sure sockets are open */ /* Make sure sockets are open */
overlay_mdp_setup_sockets(); overlay_mdp_setup_sockets();
if ((*fdcount)>=fdmax) return -1; /* XXX: Should assert IMO DOC 2012/06/23 */
if (mdp_abstract_socket>-1) if (*fdcount >= fdmax)
{ return -1;
if (debug&DEBUG_IO) {
fprintf(stderr,"MDP abstract name space socket is poll() slot #%d (fd %d)\n",
*fdcount,mdp_abstract_socket);
}
fds[*fdcount].fd=mdp_abstract_socket;
fds[*fdcount].events=POLLIN;
(*fdcount)++;
}
if ((*fdcount)>=fdmax) return -1;
if (mdp_named_socket>-1)
{
if (debug&DEBUG_IO) {
fprintf(stderr,"MDP named unix domain socket is poll() slot #%d (fd %d)\n",
*fdcount,mdp_named_socket);
}
fds[*fdcount].fd=mdp_named_socket;
fds[*fdcount].events=POLLIN;
(*fdcount)++;
}
if (mdp_socket == -1)
return 0;
if (debug & DEBUG_IO)
INFOF("MDP abstract name space socket is poll() slot #%d (fd %d)",
*fdcount, mdp_socket);
fds[*fdcount].fd = mdp_socket;
fds[*fdcount].events=POLLIN;
(*fdcount)++;
/* XXX: as above */
if (*fdcount >= fdmax)
return -1;
return 0; return 0;
} }
@ -482,7 +425,7 @@ int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
addr.sun_family=AF_UNIX; addr.sun_family=AF_UNIX;
errno=0; errno=0;
int len=overlay_mdp_relevant_bytes(mdp); int len=overlay_mdp_relevant_bytes(mdp);
int r=sendto(mdp_named_socket,mdp,len,0,(struct sockaddr*)&addr,sizeof(addr)); int r=sendto(mdp_socket,mdp,len,0,(struct sockaddr*)&addr,sizeof(addr));
if (r==overlay_mdp_relevant_bytes(mdp)) { if (r==overlay_mdp_relevant_bytes(mdp)) {
return 0; return 0;
} }
@ -710,7 +653,7 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
if (overlay_mdp_sanitytest_sourceaddr(&mdp->out.src,userGeneratedFrameP, if (overlay_mdp_sanitytest_sourceaddr(&mdp->out.src,userGeneratedFrameP,
recvaddr,recvaddrlen)) recvaddr,recvaddrlen))
return overlay_mdp_reply_error return overlay_mdp_reply_error
(mdp_named_socket, (mdp_socket,
(struct sockaddr_un *)recvaddr, (struct sockaddr_un *)recvaddr,
recvaddrlen,8, recvaddrlen,8,
"Source address is invalid (you must bind to a source address before" "Source address is invalid (you must bind to a source address before"
@ -735,7 +678,7 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
NaCl cryptobox keys can be used for signing. */ NaCl cryptobox keys can be used for signing. */
if (broadcast) { if (broadcast) {
if (!(mdp->packetTypeAndFlags&MDP_NOCRYPT)) if (!(mdp->packetTypeAndFlags&MDP_NOCRYPT))
return overlay_mdp_reply_error(mdp_named_socket, return overlay_mdp_reply_error(mdp_socket,
recvaddr,recvaddrlen,5, recvaddr,recvaddrlen,5,
"Broadcast packets cannot be encrypted "); } "Broadcast packets cannot be encrypted "); }
@ -957,12 +900,15 @@ int overlay_mdp_poll()
socklen_t recvaddrlen=sizeof(recvaddrbuffer); socklen_t recvaddrlen=sizeof(recvaddrbuffer);
struct sockaddr_un *recvaddr_un=NULL; struct sockaddr_un *recvaddr_un=NULL;
if (mdp_named_socket>-1) { /* XXX: Should call overlay_mdp_setup_sockets? DOC 2012/06/23 */
if (mdp_socket == -1)
return 0;
ttl=-1; ttl=-1;
bzero((void *)recvaddrbuffer,sizeof(recvaddrbuffer)); bzero((void *)recvaddrbuffer,sizeof(recvaddrbuffer));
fcntl(mdp_named_socket, F_SETFL, fcntl(mdp_socket, F_SETFL,
fcntl(mdp_named_socket, F_GETFL, NULL)|O_NONBLOCK); fcntl(mdp_socket, F_GETFL, NULL)|O_NONBLOCK);
int len = recvwithttl(mdp_named_socket,buffer,sizeof(buffer),&ttl, int len = recvwithttl(mdp_socket,buffer,sizeof(buffer),&ttl,
recvaddr,&recvaddrlen); recvaddr,&recvaddrlen);
recvaddr_un=(struct sockaddr_un *)recvaddr; recvaddr_un=(struct sockaddr_un *)recvaddr;
@ -1035,7 +981,7 @@ int overlay_mdp_poll()
mdpreply.addrlist.server_sid_count=count; mdpreply.addrlist.server_sid_count=count;
/* Send back to caller */ /* Send back to caller */
return overlay_mdp_reply(mdp_named_socket, return overlay_mdp_reply(mdp_socket,
(struct sockaddr_un *)recvaddr,recvaddrlen, (struct sockaddr_un *)recvaddr,recvaddrlen,
&mdpreply); &mdpreply);
} }
@ -1044,7 +990,7 @@ int overlay_mdp_poll()
return overlay_mdp_dispatch(mdp,1,(struct sockaddr_un*)recvaddr,recvaddrlen); return overlay_mdp_dispatch(mdp,1,(struct sockaddr_un*)recvaddr,recvaddrlen);
break; break;
case MDP_BIND: /* Bind to port */ case MDP_BIND: /* Bind to port */
return overlay_mdp_process_bind_request(mdp_named_socket,mdp, return overlay_mdp_process_bind_request(mdp_socket,mdp,
recvaddr_un,recvaddrlen); recvaddr_un,recvaddrlen);
break; break;
default: default:
@ -1058,13 +1004,12 @@ int overlay_mdp_poll()
/* We ignore the result of the following, because it is just sending an /* We ignore the result of the following, because it is just sending an
error message back to the client. If this fails, where would we report error message back to the client. If this fails, where would we report
the error to? My point exactly. */ the error to? My point exactly. */
sendto(mdp_named_socket,mdp,len,0,(struct sockaddr *)recvaddr,recvaddrlen); sendto(mdp_socket,mdp,len,0,(struct sockaddr *)recvaddr,recvaddrlen);
} }
} }
fcntl(mdp_named_socket, F_SETFL, fcntl(mdp_socket, F_SETFL,
fcntl(mdp_named_socket, F_GETFL, NULL)&(~O_NONBLOCK)); fcntl(mdp_socket, F_GETFL, NULL)&(~O_NONBLOCK));
}
return 0; return 0;
} }
@ -1116,7 +1061,9 @@ int overlay_mdp_relevant_bytes(overlay_mdp_frame *mdp)
int mdp_client_socket=-1; int mdp_client_socket=-1;
int overlay_mdp_send(overlay_mdp_frame *mdp,int flags,int timeout_ms) int overlay_mdp_send(overlay_mdp_frame *mdp,int flags,int timeout_ms)
{ {
int len=4; int len;
socklen_t socklen;
struct sockaddr_un name;
if (mdp_client_socket==-1) if (mdp_client_socket==-1)
if (overlay_mdp_client_init() != 0) if (overlay_mdp_client_init() != 0)
@ -1127,16 +1074,14 @@ int overlay_mdp_send(overlay_mdp_frame *mdp,int flags,int timeout_ms)
len=overlay_mdp_relevant_bytes(mdp); len=overlay_mdp_relevant_bytes(mdp);
if (len<0) return WHY("MDP frame invalid (could not compute length)"); if (len<0) return WHY("MDP frame invalid (could not compute length)");
/* Construct name of socket to send to. */ socket_setname(&name, confValueGet("mdp.socket", DEFAULT_MDP_SOCKET_NAME), &socklen);
struct sockaddr_un name;
name.sun_family = AF_UNIX;
if (!FORM_SERVAL_INSTANCE_PATH(name.sun_path, "mdp.socket"))
return -1;
fcntl(mdp_client_socket, F_SETFL, fcntl(mdp_client_socket, F_SETFL,
fcntl(mdp_client_socket, F_GETFL, NULL)|O_NONBLOCK); fcntl(mdp_client_socket, F_GETFL, NULL)|O_NONBLOCK);
int result=sendto(mdp_client_socket, mdp, len, 0, int result=sendto(mdp_client_socket, mdp, len, 0,
(struct sockaddr *)&name, sizeof(struct sockaddr_un)); (struct sockaddr *)&name, socklen);
if (result<0) { if (result<0) {
mdp->packetTypeAndFlags=MDP_ERROR; mdp->packetTypeAndFlags=MDP_ERROR;
mdp->error.error=1; mdp->error.error=1;
@ -1177,72 +1122,77 @@ int overlay_mdp_send(overlay_mdp_frame *mdp,int flags,int timeout_ms)
} }
} }
char overlay_mdp_client_socket_path[1024]; char overlay_mdp_client_socket_path[1024] = { 0 };
int overlay_mdp_client_socket_path_len=-1;
int overlay_mdp_client_init() int overlay_mdp_client_init()
{ {
if (mdp_client_socket==-1) { struct sockaddr_un name;
/* Open socket to MDP server (thus connection is always local) */ unsigned int random_value;
if (0) WHY("Use of abstract name space socket for Linux not implemented"); int send_buffer_size;
socklen_t len;
if (mdp_client_socket != -1)
return 0;
/* Open socket to MDP server (thus connection is always local) */
mdp_client_socket = socket(AF_UNIX, SOCK_DGRAM, 0); mdp_client_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
if (mdp_client_socket < 0) { if (mdp_client_socket < 0) {
WHY_perror("socket"); WHY_perror("socket");
return WHY("Could not open socket to MDP server"); goto error;
} }
/* We must bind to a temporary file name */ /* We must bind to a temporary file name */
struct sockaddr_un name; if (urandombytes((unsigned char *)&random_value,sizeof(int))) {
unsigned int random_value; WHY("urandombytes() failed");
if (urandombytes((unsigned char *)&random_value,sizeof(int))) goto error;
return WHY("urandombytes() failed"); }
name.sun_family = AF_UNIX;
if (overlay_mdp_client_socket_path_len==-1) { if (overlay_mdp_client_socket_path[0] == 0) {
char fmt[1024]; snprintf(overlay_mdp_client_socket_path, sizeof(overlay_mdp_client_socket_path),
if (!FORM_SERVAL_INSTANCE_PATH(fmt, "mdp-client-%d-%08x.socket")) "mdp-client-%d-%08x.socket", getpid(), random_value);
return WHY("Could not form MDP client socket name");
snprintf(overlay_mdp_client_socket_path,1024,fmt,getpid(),random_value);
overlay_mdp_client_socket_path_len=strlen(overlay_mdp_client_socket_path)+1;
if(debug & DEBUG_IO) DEBUGF("MDP client socket name='%s'",overlay_mdp_client_socket_path); if(debug & DEBUG_IO) DEBUGF("MDP client socket name='%s'",overlay_mdp_client_socket_path);
} }
if (overlay_mdp_client_socket_path_len > 104 - 1)
FATALF("MDP socket path too long (%d > %d)", overlay_mdp_client_socket_path_len, 104 - 1);
bcopy(overlay_mdp_client_socket_path,name.sun_path, socket_setname(&name, overlay_mdp_client_socket_path, &len);
overlay_mdp_client_socket_path_len);
unlink(name.sun_path); if (bind(mdp_client_socket, (struct sockaddr *)&name, len) == -1) {
int len = 1 + strlen(name.sun_path) + sizeof(name.sun_family) + 1;
int r=bind(mdp_client_socket, (struct sockaddr *)&name, len);
if (r) {
WHY_perror("bind"); WHY_perror("bind");
return WHY("Could not bind MDP client socket to file name"); goto error;
} }
int send_buffer_size=128*1024; send_buffer_size = 128 * 1024;
int res = setsockopt(mdp_client_socket, SOL_SOCKET, SO_RCVBUF, if (setsockopt(mdp_client_socket, SOL_SOCKET, SO_RCVBUF,
&send_buffer_size, sizeof(send_buffer_size)); &send_buffer_size, sizeof(send_buffer_size))) {
if (res) WHYF("setsockopt() failed: errno=%d",errno); WHY_perror("setsockopt");
goto error;
} }
return 0; return 0;
error:
close(mdp_client_socket);
mdp_client_socket = -1;
return -1;
} }
int overlay_mdp_client_done() int
{ overlay_mdp_client_done(void) {
overlay_mdp_frame mdp;
if (mdp_client_socket != -1) { if (mdp_client_socket != -1) {
/* Tell MDP server to release all our bindings */ /* Tell MDP server to release all our bindings */
overlay_mdp_frame mdp;
mdp.packetTypeAndFlags=MDP_GOODBYE; mdp.packetTypeAndFlags=MDP_GOODBYE;
overlay_mdp_send(&mdp,0,0); overlay_mdp_send(&mdp,0,0);
} }
if (overlay_mdp_client_socket_path_len>-1) if (overlay_mdp_client_socket_path[0] != 0)
unlink(overlay_mdp_client_socket_path); socket_done(overlay_mdp_client_socket_path);
if (mdp_client_socket != -1) if (mdp_client_socket != -1)
close(mdp_client_socket); close(mdp_client_socket);
mdp_client_socket = -1; mdp_client_socket = -1;
return 0; return 0;
} }
@ -1282,6 +1232,7 @@ int overlay_mdp_recv(overlay_mdp_frame *mdp,int *ttl)
/* Null terminate received address so that the stat() call below can succeed */ /* Null terminate received address so that the stat() call below can succeed */
if (recvaddrlen<1024) recvaddrbuffer[recvaddrlen]=0; if (recvaddrlen<1024) recvaddrbuffer[recvaddrlen]=0;
if (len>0) { if (len>0) {
#ifndef USE_ABSTRACT_NAMESPACE
/* Make sure recvaddr matches who we sent it to */ /* Make sure recvaddr matches who we sent it to */
if (strncmp(mdp_socket_name, recvaddr_un->sun_path, sizeof(recvaddr_un->sun_path))) { if (strncmp(mdp_socket_name, recvaddr_un->sun_path, sizeof(recvaddr_un->sun_path))) {
/* Okay, reply was PROBABLY not from the server, but on OSX if the path /* Okay, reply was PROBABLY not from the server, but on OSX if the path
@ -1294,6 +1245,7 @@ int overlay_mdp_recv(overlay_mdp_frame *mdp,int *ttl)
if ((sb1.st_ino!=sb2.st_ino)||(sb1.st_dev!=sb2.st_dev)) if ((sb1.st_ino!=sb2.st_ino)||(sb1.st_dev!=sb2.st_dev))
return WHY("Reply did not come from server"); return WHY("Reply did not come from server");
} }
#endif
int expected_len = overlay_mdp_relevant_bytes(mdp); int expected_len = overlay_mdp_relevant_bytes(mdp);

View File

@ -1498,7 +1498,7 @@ int overlay_route_node_info(overlay_mdp_frame *mdp,
} }
} }
return overlay_mdp_reply(mdp_named_socket,addr,addrlen,mdp); return overlay_mdp_reply(mdp_socket,addr,addrlen,mdp);
return 0; return 0;
} }

View File

@ -1166,8 +1166,7 @@ int overlay_mdp_poll();
int overlay_mdp_reply_error(int sock, int overlay_mdp_reply_error(int sock,
struct sockaddr_un *recvaddr,int recvaddrlen, struct sockaddr_un *recvaddr,int recvaddrlen,
int error_number,char *message); int error_number,char *message);
extern int mdp_abstract_socket; extern int mdp_socket;
extern int mdp_named_socket;
typedef struct sockaddr_mdp { typedef struct sockaddr_mdp {
@ -1539,5 +1538,12 @@ extern int sigIoFlag;
void sigPipeHandler(int signal); void sigPipeHandler(int signal);
void sigIoHandler(int signal); void sigIoHandler(int signal);
#ifdef USE_ABSTRACT_NAMESPACE
/* Long ones for abstract name space */
#define DEFAULT_MONITOR_SOCKET_NAME "org.servalproject.servald.monitor.socket" #define DEFAULT_MONITOR_SOCKET_NAME "org.servalproject.servald.monitor.socket"
#define DEFAULT_MDP_SOCKET_NAME "org.servalproject.servald.mdp.socket" #define DEFAULT_MDP_SOCKET_NAME "org.servalproject.servald.mdp.socket"
#else
/* Short ones elsewhere */
#define DEFAULT_MONITOR_SOCKET_NAME "monitor.socket"
#define DEFAULT_MDP_SOCKET_NAME "mdp.socket"
#endif

104
socket.c Normal file
View File

@ -0,0 +1,104 @@
/*
Copyright (C) 2012 Daniel O'Connor, Serval Project.
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.
*/
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#include <stdio.h>
#include <strings.h>
#include <sys/errno.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <sys/un.h>
#include <unistd.h>
#include "serval.h"
#include "socket.h"
/* Create a socket and bind it to name in the abstract namespace for android or
* $SERVALINSTANCE_PATH/name for everything else.
*
* Use abstract namespace as Android has no writable FS which supports sockets.
* Don't use it for anything else because it makes testing harder (as we can't run
* more than one servald on a given system.
*/
int
socket_bind(const char *name) {
int s, oerrno;
struct sockaddr_un sockname;
socklen_t len;
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
return -1;
socket_setname(&sockname, name, &len);
unlink(sockname.sun_path);
if (bind(s, (struct sockaddr *)&sockname, len) == -1) {
oerrno = errno;
close(s);
errno = oerrno;
return -1;
}
return s;
}
/* Set sockname to name handling abstract name space sockets etc. */
void
socket_setname(struct sockaddr_un *sockname, const char *name, socklen_t *len) {
bzero(sockname, sizeof(*sockname));
sockname->sun_family = AF_UNIX;
#ifdef USE_ABSTRACT_NAMESPACE
sockname->sun_path[0] = 0;
/* Note: -2 here not -1 because sprintf will put the trailling nul in */
*len = snprintf(sockname->sun_path + 1, sizeof(sockname->sun_path) - 2, "%s", name);
if (*len > sizeof(sockname->sun_path) - 2)
FATALF("Socket path too long (%d > %d)", *len, sizeof(sockname->sun_path) - 2);
/* Doesn't include trailing nul */
*len = 1 + strlen(sockname->sun_path + 1) + sizeof(sockname->sun_family);
#else
*len = snprintf(sockname->sun_path, sizeof(sockname->sun_path) - 1, "%s/%s",
serval_instancepath(), name);
if (*len > sizeof(sockname->sun_path) - 1)
FATALF("Socket path too long (%d > %d)", *len, sizeof(sockname->sun_path) - 1);
#ifdef SUN_LEN
*len = SUN_LEN(sockname);
#else
/* Includes trailing nul */
*len = 1 + strlen(sockname->sun_path) + sizeof(sockname->sun_family);
#endif
#endif
}
/* Cleanup socket opened by socket_bind */
void
socket_done(const char *name) {
#ifndef USE_ABSTRACT_NAMESPACE
struct sockaddr_un sockname;
socklen_t len;
socket_setname(&sockname, name, &len);
unlink(sockname.sun_path);
#endif
}

5
socket.h Normal file
View File

@ -0,0 +1,5 @@
int socket_bind(const char *name);
void socket_setname(struct sockaddr_un *sockname, const char *name, socklen_t *len);
void socket_done(const char *name);

34
vomp.c
View File

@ -321,7 +321,7 @@ int vomp_send_status(vomp_call_state *call,int flags,overlay_mdp_frame *arg)
long long now=overlay_gettime_ms(); long long now=overlay_gettime_ms();
for(i=0;i<vomp_interested_usock_count;i++) for(i=0;i<vomp_interested_usock_count;i++)
if (vomp_interested_expiries[i]>=now) { if (vomp_interested_expiries[i]>=now) {
overlay_mdp_reply(mdp_named_socket, overlay_mdp_reply(mdp_socket,
vomp_interested_usocks[i], vomp_interested_usocks[i],
vomp_interested_usock_lengths[i], vomp_interested_usock_lengths[i],
&mdp); &mdp);
@ -474,7 +474,7 @@ int vomp_mdp_event(overlay_mdp_frame *mdp,
if (!memcmp(recvaddr->sun_path, if (!memcmp(recvaddr->sun_path,
vomp_interested_usocks[i],recvaddrlen)) vomp_interested_usocks[i],recvaddrlen))
/* found it -- so we are already monitoring this one */ /* found it -- so we are already monitoring this one */
return overlay_mdp_reply_error(mdp_named_socket,recvaddr,recvaddrlen, return overlay_mdp_reply_error(mdp_socket,recvaddr,recvaddrlen,
0,"Success"); 0,"Success");
if (vomp_interested_expiries[i]<now) candidate=i; if (vomp_interested_expiries[i]<now) candidate=i;
} }
@ -487,7 +487,7 @@ int vomp_mdp_event(overlay_mdp_frame *mdp,
} }
vomp_interested_usocks[i]=malloc(recvaddrlen); vomp_interested_usocks[i]=malloc(recvaddrlen);
if (!vomp_interested_usocks[i]) if (!vomp_interested_usocks[i])
return overlay_mdp_reply_error(mdp_named_socket, recvaddr,recvaddrlen, return overlay_mdp_reply_error(mdp_socket, recvaddr,recvaddrlen,
4002,"Out of memory"); 4002,"Out of memory");
bcopy(recvaddr,vomp_interested_usocks[i], bcopy(recvaddr,vomp_interested_usocks[i],
recvaddrlen); recvaddrlen);
@ -505,10 +505,10 @@ int vomp_mdp_event(overlay_mdp_frame *mdp,
} }
return overlay_mdp_reply_error return overlay_mdp_reply_error
(mdp_named_socket,recvaddr,recvaddrlen,0,"Success"); (mdp_socket,recvaddr,recvaddrlen,0,"Success");
} else { } else {
return overlay_mdp_reply_error return overlay_mdp_reply_error
(mdp_named_socket,recvaddr,recvaddrlen, (mdp_socket,recvaddr,recvaddrlen,
4003,"Too many listeners (try again in a minute?)"); 4003,"Too many listeners (try again in a minute?)");
} }
} }
@ -536,12 +536,12 @@ int vomp_mdp_event(overlay_mdp_frame *mdp,
} }
vomp_interested_usock_count--; vomp_interested_usock_count--;
return overlay_mdp_reply_error return overlay_mdp_reply_error
(mdp_named_socket,recvaddr,recvaddrlen, (mdp_socket,recvaddr,recvaddrlen,
0,"Success. You have been removed."); 0,"Success. You have been removed.");
} }
} }
return overlay_mdp_reply_error return overlay_mdp_reply_error
(mdp_named_socket,recvaddr,recvaddrlen, (mdp_socket,recvaddr,recvaddrlen,
0,"Success. You were never listening."); 0,"Success. You were never listening.");
} }
break; break;
@ -585,7 +585,7 @@ int vomp_mdp_event(overlay_mdp_frame *mdp,
} }
} }
return overlay_mdp_reply(mdp_named_socket,recvaddr,recvaddrlen,&mdpreply); return overlay_mdp_reply(mdp_socket,recvaddr,recvaddrlen,&mdpreply);
} }
break; break;
case VOMPEVENT_DIAL: case VOMPEVENT_DIAL:
@ -598,7 +598,7 @@ int vomp_mdp_event(overlay_mdp_frame *mdp,
/* Populate call structure */ /* Populate call structure */
if (vomp_call_count>=VOMP_MAX_CALLS) if (vomp_call_count>=VOMP_MAX_CALLS)
return overlay_mdp_reply_error return overlay_mdp_reply_error
(mdp_named_socket,recvaddr,recvaddrlen,4004, (mdp_socket,recvaddr,recvaddrlen,4004,
"All call slots in use"); "All call slots in use");
int slot=vomp_call_count++; int slot=vomp_call_count++;
vomp_call_state *call=&vomp_call_states[slot]; vomp_call_state *call=&vomp_call_states[slot];
@ -618,7 +618,7 @@ int vomp_mdp_event(overlay_mdp_frame *mdp,
{ {
if (urandombytes((unsigned char *)&call->local.session,sizeof(int))) if (urandombytes((unsigned char *)&call->local.session,sizeof(int)))
return overlay_mdp_reply_error return overlay_mdp_reply_error
(mdp_named_socket,recvaddr,recvaddrlen,4005, (mdp_socket,recvaddr,recvaddrlen,4005,
"Insufficient entropy"); "Insufficient entropy");
call->local.session&=VOMP_SESSION_MASK; call->local.session&=VOMP_SESSION_MASK;
printf("session=0x%08x\n",call->local.session); printf("session=0x%08x\n",call->local.session);
@ -638,7 +638,7 @@ int vomp_mdp_event(overlay_mdp_frame *mdp,
WHY("sending MDP reply back"); WHY("sending MDP reply back");
dump("recvaddr",(unsigned char *)recvaddr,recvaddrlen); dump("recvaddr",(unsigned char *)recvaddr,recvaddrlen);
int result= overlay_mdp_reply_error int result= overlay_mdp_reply_error
(mdp_named_socket,recvaddr,recvaddrlen,0, "Success"); (mdp_socket,recvaddr,recvaddrlen,0, "Success");
if (result) WHY("Failed to send MDP reply"); if (result) WHY("Failed to send MDP reply");
return result; return result;
} }
@ -650,12 +650,12 @@ int vomp_mdp_event(overlay_mdp_frame *mdp,
=vomp_find_call_by_session(mdp->vompevent.call_session_token); =vomp_find_call_by_session(mdp->vompevent.call_session_token);
if (!call) if (!call)
return overlay_mdp_reply_error return overlay_mdp_reply_error
(mdp_named_socket,recvaddr,recvaddrlen,4006, (mdp_socket,recvaddr,recvaddrlen,4006,
"No such call"); "No such call");
if (call->local.state==VOMP_STATE_INCALL) vomp_call_stop_audio(call); if (call->local.state==VOMP_STATE_INCALL) vomp_call_stop_audio(call);
call->local.state=VOMP_STATE_CALLENDED; call->local.state=VOMP_STATE_CALLENDED;
monitor_call_status(call); monitor_call_status(call);
overlay_mdp_reply_error(mdp_named_socket, overlay_mdp_reply_error(mdp_socket,
recvaddr,recvaddrlen,0,"Success"); recvaddr,recvaddrlen,0,"Success");
return vomp_send_status(call,VOMP_TELLREMOTE|VOMP_TELLINTERESTED,NULL); return vomp_send_status(call,VOMP_TELLREMOTE|VOMP_TELLINTERESTED,NULL);
} }
@ -667,7 +667,7 @@ int vomp_mdp_event(overlay_mdp_frame *mdp,
=vomp_find_call_by_session(mdp->vompevent.call_session_token); =vomp_find_call_by_session(mdp->vompevent.call_session_token);
if (!call) if (!call)
return overlay_mdp_reply_error return overlay_mdp_reply_error
(mdp_named_socket,recvaddr,recvaddrlen,4006, (mdp_socket,recvaddr,recvaddrlen,4006,
"No such call"); "No such call");
if (call->local.state==VOMP_STATE_RINGINGIN) { if (call->local.state==VOMP_STATE_RINGINGIN) {
call->local.state=VOMP_STATE_INCALL; call->local.state=VOMP_STATE_INCALL;
@ -675,11 +675,11 @@ int vomp_mdp_event(overlay_mdp_frame *mdp,
call->ringing=0; call->ringing=0;
/* state machine does job of starting audio stream, just tell everyone about /* state machine does job of starting audio stream, just tell everyone about
the changed state. */ the changed state. */
overlay_mdp_reply_error(mdp_named_socket, overlay_mdp_reply_error(mdp_socket,
recvaddr,recvaddrlen,0,"Success"); recvaddr,recvaddrlen,0,"Success");
return vomp_send_status(call,VOMP_TELLREMOTE|VOMP_TELLINTERESTED,NULL); return vomp_send_status(call,VOMP_TELLREMOTE|VOMP_TELLINTERESTED,NULL);
} else { } else {
overlay_mdp_reply_error(mdp_named_socket, overlay_mdp_reply_error(mdp_socket,
recvaddr,recvaddrlen,4009, recvaddr,recvaddrlen,4009,
"Call is not RINGINGIN, so cannot be picked up"); "Call is not RINGINGIN, so cannot be picked up");
} }
@ -699,7 +699,7 @@ int vomp_mdp_event(overlay_mdp_frame *mdp,
break; break;
default: default:
/* didn't understand it, so respond with an error */ /* didn't understand it, so respond with an error */
return overlay_mdp_reply_error(mdp_named_socket, return overlay_mdp_reply_error(mdp_socket,
recvaddr,recvaddrlen,4001, recvaddr,recvaddrlen,4001,
"Invalid VOMPEVENT request (use DIAL,HANGUP,CALLREJECT,AUDIOSTREAMING,REGISTERINTERST,WITHDRAWINTERST only)"); "Invalid VOMPEVENT request (use DIAL,HANGUP,CALLREJECT,AUDIOSTREAMING,REGISTERINTERST,WITHDRAWINTERST only)");