Refactor socket name and address length handling

This commit is contained in:
Jeremy Lakeman 2013-11-25 12:15:20 +10:30
parent 5ea19ab538
commit 0d5d878521
20 changed files with 874 additions and 541 deletions

View File

@ -931,9 +931,6 @@ int app_mdp_ping(const struct cli_parsed *parsed, struct cli_context *context)
int64_t interval_ms = 1000;
str_to_uint64_interval_ms(opt_interval, &interval_ms, NULL);
overlay_mdp_frame mdp;
bzero(&mdp, sizeof(overlay_mdp_frame));
/* First sequence number in the echo frames */
unsigned int firstSeq=random();
unsigned int sequence_number=firstSeq;
@ -941,22 +938,23 @@ int app_mdp_ping(const struct cli_parsed *parsed, struct cli_context *context)
int broadcast = is_sid_t_broadcast(ping_sid);
/* Bind to MDP socket and await confirmation */
if ((mdp_sockfd = overlay_mdp_client_socket()) < 0)
if ((mdp_sockfd = mdp_socket()) < 0)
return WHY("Cannot create MDP socket");
sid_t srcsid;
mdp_port_t port=32768+(random()&32767);
if (overlay_mdp_getmyaddr(mdp_sockfd, 0, &srcsid)) {
overlay_mdp_client_close(mdp_sockfd);
return WHY("Could not get local address");
}
if (overlay_mdp_bind(mdp_sockfd, &srcsid, port)) {
overlay_mdp_client_close(mdp_sockfd);
return WHY("Could not bind to MDP socket");
}
struct mdp_header mdp_header;
bzero(&mdp_header, sizeof(mdp_header));
mdp_header.local.sid = BIND_PRIMARY;
mdp_header.remote.sid = ping_sid;
mdp_header.remote.port = MDP_PORT_ECHO;
mdp_header.qos = OQ_MESH_MANAGEMENT;
mdp_header.ttl = PAYLOAD_TTL_DEFAULT;
mdp_header.flags = MDP_FLAG_BIND;
if (broadcast)
mdp_header.flags |= MDP_FLAG_NO_CRYPT;
/* TODO Eventually we should try to resolve SID to phone number and vice versa */
cli_printf(context, "MDP PING %s (%s): 12 data bytes", alloca_tohex_sid_t(ping_sid), alloca_tohex_sid_t(ping_sid));
cli_printf(context, "MDP PING %s: 12 data bytes", alloca_tohex_sid_t(ping_sid));
cli_delim(context, "\n");
cli_flush(context);
@ -968,81 +966,91 @@ int app_mdp_ping(const struct cli_parsed *parsed, struct cli_context *context)
if (broadcast)
WARN("broadcast ping packets will not be encrypted");
for (; icount==0 || tx_count<icount; ++sequence_number) {
/* Now send the ping packets */
mdp.packetTypeAndFlags=MDP_TX;
if (broadcast) mdp.packetTypeAndFlags|=MDP_NOCRYPT;
mdp.out.src.port=port;
mdp.out.src.sid = srcsid;
mdp.out.dst.sid = ping_sid;
mdp.out.queue=OQ_MESH_MANAGEMENT;
/* Set port to well known echo port */
mdp.out.dst.port=MDP_PORT_ECHO;
mdp.out.payload_length=4+8;
int *seq=(int *)&mdp.out.payload;
*seq=sequence_number;
write_uint64(&mdp.out.payload[4], gettime_ms());
int res=overlay_mdp_send(mdp_sockfd, &mdp, 0, 0);
if (res) {
WHYF("could not dispatch PING frame #%d (error %d)%s%s",
sequence_number - firstSeq,
res,
mdp.packetTypeAndFlags == MDP_ERROR ? ": " : "",
mdp.packetTypeAndFlags == MDP_ERROR ? mdp.error.message : ""
);
} else
tx_count++;
// send a ping packet
{
uint8_t payload[12];
int *seq=(int *)payload;
*seq=sequence_number;
write_uint64(&payload[4], gettime_ms());
int r = mdp_send(mdp_sockfd, &mdp_header, payload, sizeof(payload));
if (r<0)
WHY_perror("mdp_send");
else
tx_count++;
}
/* Now look for replies until one second has passed, and print any replies
with appropriate information as required */
time_ms_t now = gettime_ms();
time_ms_t finish = now + (tx_count < icount?interval_ms:timeout_ms);
for (; !servalShutdown && now < finish; now = gettime_ms()) {
time_ms_t poll_timeout_ms = finish - gettime_ms();
int result = overlay_mdp_client_poll(mdp_sockfd, poll_timeout_ms);
if (result>0) {
int ttl=-1;
if (overlay_mdp_recv(mdp_sockfd, &mdp, port, &ttl)==0) {
switch(mdp.packetTypeAndFlags&MDP_TYPE_MASK) {
case MDP_ERROR:
WHYF("mdpping: overlay_mdp_recv: %s (code %d)", mdp.error.message, mdp.error.error);
break;
case MDP_TX:
{
int *rxseq=(int *)&mdp.in.payload;
time_ms_t txtime = read_uint64(&mdp.in.payload[4]);
int hop_count = 64 - mdp.in.ttl;
time_ms_t delay = gettime_ms() - txtime;
cli_printf(context, "%s: seq=%d time=%"PRId64"ms hops=%d %s%s",
alloca_tohex_sid_t(mdp.in.src.sid),
(*rxseq)-firstSeq+1,
(int64_t)delay,
hop_count,
mdp.packetTypeAndFlags&MDP_NOCRYPT?"":" ENCRYPTED",
mdp.packetTypeAndFlags&MDP_NOSIGN?"":" SIGNED");
cli_delim(context, "\n");
cli_flush(context);
// TODO Put duplicate pong detection here so that stats work properly.
rx_count++;
ret=0;
rx_ms+=delay;
if (rx_mintime>delay||rx_mintime==-1) rx_mintime=delay;
if (delay>rx_maxtime) rx_maxtime=delay;
rx_times[rx_count%1024]=delay;
}
break;
default:
WHYF("mdpping: overlay_mdp_recv: Unexpected MDP frame type 0x%x", mdp.packetTypeAndFlags);
break;
}
}
if (mdp_poll(mdp_sockfd, poll_timeout_ms)<=0)
continue;
struct mdp_header mdp_recv_header;
uint8_t recv_payload[12];
ssize_t len = mdp_recv(mdp_sockfd, &mdp_recv_header, recv_payload, sizeof(recv_payload));
if (len<0){
WHY_perror("mdp_recv");
break;
}
if (mdp_recv_header.flags & MDP_FLAG_ERROR){
WHY("Serval daemon reported an error, please check the log for more information");
break;
}
if (mdp_recv_header.flags & MDP_FLAG_BIND){
// received port binding confirmation
mdp_header.local = mdp_recv_header.local;
mdp_header.flags &= ~MDP_FLAG_BIND;
DEBUGF("Bound to %s:%d", alloca_tohex_sid_t(mdp_header.local.sid), mdp_header.local.port);
continue;
}
if (len<sizeof(recv_payload)){
DEBUGF("Ignoring ping response as it is too short");
continue;
}
int *rxseq=(int *)&recv_payload;
time_ms_t txtime = read_uint64(&recv_payload[4]);
int hop_count = 64 - mdp_recv_header.ttl;
time_ms_t delay = gettime_ms() - txtime;
cli_put_hexvalue(context, mdp_recv_header.remote.sid.binary, SID_SIZE, ": seq=");
cli_put_long(context, (*rxseq)-firstSeq+1, " time=");
cli_put_long(context, delay, "ms hops=");
cli_put_long(context, hop_count, "");
if (mdp_recv_header.flags&MDP_FLAG_NO_CRYPT)
cli_put_string(context, "", "");
else
cli_put_string(context, " ENCRYPTED", "");
if (mdp_recv_header.flags&MDP_FLAG_NO_SIGN)
cli_put_string(context, "", "\n");
else
cli_put_string(context, " SIGNED", "\n");
cli_flush(context);
// TODO Put duplicate pong detection here so that stats work properly.
rx_count++;
ret=0;
rx_ms+=delay;
if (rx_mintime>delay||rx_mintime==-1) rx_mintime=delay;
if (delay>rx_maxtime) rx_maxtime=delay;
rx_times[rx_count%1024]=delay;
}
}
overlay_mdp_client_close(mdp_sockfd);
mdp_close(mdp_sockfd);
{
float rx_stddev=0;
@ -2264,7 +2272,7 @@ static int handle_pins(const struct cli_parsed *parsed, struct cli_context *cont
WHYF("Timeout while waiting for response");
break;
}
if (rev_header.flags & MDP_FLAG_OK){
if (rev_header.flags & MDP_FLAG_CLOSE){
ret=0;
break;
}
@ -2334,7 +2342,7 @@ int app_id_list(const struct cli_parsed *parsed, struct cli_context *context)
// TODO receive and decode other details about this identity
}
if (rev_header.flags & MDP_FLAG_OK){
if (rev_header.flags & MDP_FLAG_CLOSE){
ret=0;
break;
}

View File

@ -52,7 +52,7 @@ static void directory_send(struct subscriber *directory_service, const sid_t *si
// Used by tests
INFOF("Sending directory registration for %s*, %s, %s to %s*",
alloca_tohex_sid_t_trunc(*sidp, 14), did, name, alloca_tohex_sid_t_trunc(directory_service->sid, 14));
overlay_mdp_dispatch(&request, 0, NULL, 0);
overlay_mdp_dispatch(&request, NULL);
}
// send a registration packet for each unlocked identity

View File

@ -6,6 +6,7 @@ HDRS= fifo.h \
rhizome.h \
serval.h \
keyring.h \
socket.h \
cli.h \
str.h \
rotbuf.h \

View File

@ -1764,7 +1764,7 @@ static int keyring_respond_sas(keyring_file *k, overlay_mdp_frame *req)
alloca_tohex_sid_t(req->out.src.sid), req->out.src.port,
alloca_tohex_sid_t(req->out.dst.sid), req->out.dst.port
);
return overlay_mdp_dispatch(req,0,NULL,0);
return overlay_mdp_dispatch(req, NULL);
}
// someone else is claiming to be me on this network
@ -1790,7 +1790,7 @@ int keyring_send_unlock(struct subscriber *subscriber)
if (crypto_sign_message(subscriber, mdp.out.payload, sizeof(mdp.out.payload), &len))
return -1;
mdp.out.payload_length=len;
return overlay_mdp_dispatch(&mdp, 0 /* system generated */, NULL, 0);
return overlay_mdp_dispatch(&mdp, NULL);
}
static int keyring_send_challenge(struct subscriber *source, struct subscriber *dest)
@ -1815,7 +1815,7 @@ static int keyring_send_challenge(struct subscriber *source, struct subscriber *
bcopy(source->identity->challenge, &mdp.out.payload[1], sizeof(source->identity->challenge));
mdp.out.payload_length+=sizeof(source->identity->challenge);
return overlay_mdp_dispatch(&mdp, 0 /* system generated */, NULL, 0);
return overlay_mdp_dispatch(&mdp, NULL);
}
static int keyring_respond_challenge(struct subscriber *subscriber, overlay_mdp_frame *req)
@ -1839,7 +1839,7 @@ static int keyring_respond_challenge(struct subscriber *subscriber, overlay_mdp_
if (crypto_sign_message(subscriber, mdp.out.payload, sizeof(mdp.out.payload), &len))
return -1;
mdp.out.payload_length=len;
return overlay_mdp_dispatch(&mdp, 0 /* system generated */, NULL, 0);
return overlay_mdp_dispatch(&mdp, NULL);
}
static int keyring_process_challenge(keyring_file *k, struct subscriber *subscriber, overlay_mdp_frame *req)
@ -1925,7 +1925,7 @@ int keyring_send_sas_request(struct subscriber *subscriber){
mdp.out.payload_length=1;
mdp.out.payload[0]=KEYTYPE_CRYPTOSIGN;
if (overlay_mdp_dispatch(&mdp, 0 /* system generated */, NULL, 0))
if (overlay_mdp_dispatch(&mdp, NULL))
return WHY("Failed to send SAS resolution request");
if (config.debug.keyring)
DEBUGF("Dispatched SAS resolution request");

View File

@ -27,6 +27,7 @@
#include "overlay_address.h"
#include "overlay_packet.h"
#include "mdp_client.h"
#include "socket.h"
int mdp_socket(void)
{
@ -34,49 +35,70 @@ int mdp_socket(void)
return overlay_mdp_client_socket();
}
int mdp_close(int socket)
static void mdp_unlink(int mdp_sock)
{
// use the same process for closing sockets, though this will need to change once bind is implemented
return overlay_mdp_client_close(socket);
// get the socket name and unlink it from the filesystem if not abstract
struct socket_address addr;
addr.addrlen = sizeof addr.store;
if (getsockname(mdp_sock, &addr.addr, &addr.addrlen))
WHYF_perror("getsockname(%d)", mdp_sock);
else if (addr.addr.sa_family==AF_UNIX
&& addr.addrlen > sizeof addr.addr_un.sun_family
&& addr.addrlen <= sizeof addr.addr_un && addr.addr_un.sun_path[0] != '\0') {
if (unlink(addr.addr_un.sun_path) == -1)
WARNF_perror("unlink(%s)", alloca_str_toprint(addr.addr_un.sun_path));
}
close(mdp_sock);
}
int mdp_send(int socket, const struct mdp_header *header, const unsigned char *payload, ssize_t len)
int mdp_close(int socket)
{
struct sockaddr_un addr;
socklen_t addrlen;
if (make_local_sockaddr(&addr, &addrlen, "mdp.2.socket") == -1)
// tell the daemon to drop all bindings
struct mdp_header header={
.flags = MDP_FLAG_CLOSE,
.local.port = 0,
};
mdp_send(socket, &header, NULL, 0);
// remove socket
mdp_unlink(socket);
return 0;
}
int mdp_send(int socket, const struct mdp_header *header, const uint8_t *payload, size_t len)
{
struct socket_address addr;
if (make_local_sockaddr(&addr, "mdp.2.socket") == -1)
return -1;
struct iovec iov[]={
{
.iov_base = (void *)header,
.iov_len = sizeof(struct mdp_header)
},
{
.iov_base = (void *)payload,
.iov_len = len
struct fragmented_data data={
.fragment_count=2,
.iov={
{
.iov_base = (void*)header,
.iov_len = sizeof(struct mdp_header)
},
{
.iov_base = (void*)payload,
.iov_len = len
}
}
};
struct msghdr hdr={
.msg_name=&addr,
.msg_namelen=addrlen,
.msg_iov=iov,
.msg_iovlen=2,
};
return sendmsg(socket, &hdr, 0);
return send_message(socket, &addr, &data);
}
ssize_t mdp_recv(int socket, struct mdp_header *header, unsigned char *payload, ssize_t max_len)
ssize_t mdp_recv(int socket, struct mdp_header *header, uint8_t *payload, ssize_t max_len)
{
/* Construct name of socket to receive from. */
struct sockaddr_un mdp_addr;
socklen_t mdp_addrlen;
if (make_local_sockaddr(&mdp_addr, &mdp_addrlen, "mdp.2.socket") == -1)
return -1;
errno=0;
struct socket_address mdp_addr;
if (make_local_sockaddr(&mdp_addr, "mdp.2.socket") == -1)
return WHY("Failed to build socket address");
struct sockaddr_un addr;
struct socket_address addr;
struct iovec iov[]={
{
.iov_base = (void *)header,
@ -89,25 +111,26 @@ ssize_t mdp_recv(int socket, struct mdp_header *header, unsigned char *payload,
};
struct msghdr hdr={
.msg_name=&addr,
.msg_namelen=sizeof(struct sockaddr_un),
.msg_name=&addr.addr,
.msg_namelen=sizeof(addr.store),
.msg_iov=iov,
.msg_iovlen=2,
};
ssize_t len = recvmsg(socket, &hdr, 0);
if (len<sizeof(struct mdp_header))
return -1;
return WHYF("Received message is too short (%d)", (int)len);
addr.addrlen=hdr.msg_namelen;
// double check that the incoming address matches the servald daemon
if (cmp_sockaddr((struct sockaddr *)&addr, hdr.msg_namelen, (struct sockaddr *)&mdp_addr, mdp_addrlen) != 0
&& ( addr.sun_family != AF_UNIX
|| real_sockaddr(&addr, hdr.msg_namelen, &addr, &hdr.msg_namelen) <= 0
|| cmp_sockaddr((struct sockaddr *)&addr, hdr.msg_namelen, (struct sockaddr *)&mdp_addr, mdp_addrlen) != 0
if (cmp_sockaddr(&addr, &mdp_addr) != 0
&& ( addr.addr_un.sun_family != AF_UNIX
|| real_sockaddr(&addr, &addr) <= 0
|| cmp_sockaddr(&addr, &mdp_addr) != 0
)
)
return -1;
return WHYF("Received message came from %s instead of %s?",
alloca_socket_address(&addr),
alloca_socket_address(&mdp_addr));
return len - sizeof(struct mdp_header);
}
@ -125,19 +148,18 @@ int overlay_mdp_send(int mdp_sockfd, overlay_mdp_frame *mdp, int flags, int time
if (len == -1)
return WHY("MDP frame invalid (could not compute length)");
/* Construct name of socket to send to. */
struct sockaddr_un addr;
socklen_t addrlen;
if (make_local_sockaddr(&addr, &addrlen, "mdp.socket") == -1)
struct socket_address addr;
if (make_local_sockaddr(&addr, "mdp.socket") == -1)
return -1;
// Send to that socket
set_nonblock(mdp_sockfd);
ssize_t result = sendto(mdp_sockfd, mdp, (size_t)len, 0, (struct sockaddr *)&addr, addrlen);
ssize_t result = sendto(mdp_sockfd, mdp, (size_t)len, 0, &addr.addr, addr.addrlen);
set_block(mdp_sockfd);
if ((size_t)result != (size_t)len) {
if (result == -1)
WHYF_perror("sendto(fd=%d,len=%zu,addr=%s)", mdp_sockfd, (size_t)len, alloca_sockaddr(&addr, addrlen));
WHYF_perror("sendto(fd=%d,len=%zu,addr=%s)", mdp_sockfd, (size_t)len, alloca_socket_address(&addr));
else
WHYF("sendto() sent %zu bytes of MDP reply (%zu) to socket=%d", (size_t)result, (size_t)len, mdp_sockfd);
WHYF("sendto() sent %zu bytes of MDP reply (%zu) to %s", (size_t)result, (size_t)len, alloca_socket_address(&addr));
mdp->packetTypeAndFlags=MDP_ERROR;
mdp->error.error=1;
snprintf(mdp->error.message,128,"Error sending frame to MDP server.");
@ -181,16 +203,15 @@ int overlay_mdp_client_socket(void)
{
/* Create local per-client socket to MDP server (connection is always local) */
int mdp_sockfd;
struct sockaddr_un addr;
socklen_t addrlen;
struct socket_address addr;
uint32_t random_value;
if (urandombytes((unsigned char *)&random_value, sizeof random_value) == -1)
return WHY("urandombytes() failed");
if (make_local_sockaddr(&addr, &addrlen, "mdp.client.%u.%08lx.socket", getpid(), (unsigned long)random_value) == -1)
if (make_local_sockaddr(&addr, "mdp.client.%u.%08lx.socket", getpid(), (unsigned long)random_value) == -1)
return -1;
if ((mdp_sockfd = esocket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
return -1;
if (socket_bind(mdp_sockfd, (struct sockaddr *)&addr, addrlen) == -1) {
if (socket_bind(mdp_sockfd, &addr.addr, addr.addrlen) == -1) {
close(mdp_sockfd);
return -1;
}
@ -204,16 +225,8 @@ int overlay_mdp_client_close(int mdp_sockfd)
overlay_mdp_frame mdp;
mdp.packetTypeAndFlags = MDP_GOODBYE;
overlay_mdp_send(mdp_sockfd, &mdp, 0, 0);
// get the socket name and unlink it from the filesystem if not abstract
struct sockaddr_un addr;
socklen_t addrlen = sizeof addr;
if (getsockname(mdp_sockfd, (struct sockaddr *)&addr, &addrlen))
WHYF_perror("getsockname(%d)", mdp_sockfd);
else if (addrlen > sizeof addr.sun_family && addrlen <= sizeof addr && addr.sun_path[0] != '\0') {
if (unlink(addr.sun_path) == -1)
WARNF_perror("unlink(%s)", alloca_str_toprint(addr.sun_path));
}
close(mdp_sockfd);
mdp_unlink(mdp_sockfd);
return 0;
}
@ -236,36 +249,35 @@ int overlay_mdp_client_poll(int mdp_sockfd, time_ms_t timeout_ms)
int overlay_mdp_recv(int mdp_sockfd, overlay_mdp_frame *mdp, mdp_port_t port, int *ttl)
{
/* Construct name of socket to receive from. */
struct sockaddr_un mdp_addr;
socklen_t mdp_addrlen;
if (make_local_sockaddr(&mdp_addr, &mdp_addrlen, "mdp.socket") == -1)
struct socket_address mdp_addr;
if (make_local_sockaddr(&mdp_addr, "mdp.socket") == -1)
return -1;
/* Check if reply available */
struct sockaddr_un recvaddr;
socklen_t recvaddrlen = sizeof recvaddr;
struct socket_address recvaddr;
recvaddr.addrlen = sizeof recvaddr.store;
ssize_t len;
mdp->packetTypeAndFlags = 0;
set_nonblock(mdp_sockfd);
len = recvwithttl(mdp_sockfd, (unsigned char *)mdp, sizeof(overlay_mdp_frame), ttl, (struct sockaddr *)&recvaddr, &recvaddrlen);
len = recvwithttl(mdp_sockfd, (unsigned char *)mdp, sizeof(overlay_mdp_frame), ttl, &recvaddr.addr, &recvaddr.addrlen);
set_block(mdp_sockfd);
if (len <= 0)
return -1; // no packet received
// If the received address overflowed the buffer, then it cannot have come from the server, whose
// address must always fit within a struct sockaddr_un.
if (recvaddrlen > sizeof recvaddr)
if (recvaddr.addrlen > sizeof recvaddr.store)
return WHY("reply did not come from server: address overrun");
// Compare the address of the sender with the address of our server, to ensure they are the same.
// If the comparison fails, then try using realpath(3) on the sender address and compare again.
if ( cmp_sockaddr((struct sockaddr *)&recvaddr, recvaddrlen, (struct sockaddr *)&mdp_addr, mdp_addrlen) != 0
&& ( recvaddr.sun_family != AF_UNIX
|| real_sockaddr(&recvaddr, recvaddrlen, &recvaddr, &recvaddrlen) <= 0
|| cmp_sockaddr((struct sockaddr *)&recvaddr, recvaddrlen, (struct sockaddr *)&mdp_addr, mdp_addrlen) != 0
if ( cmp_sockaddr(&recvaddr, &mdp_addr) != 0
&& ( recvaddr.addr_un.sun_family != AF_UNIX
|| real_sockaddr(&recvaddr, &recvaddr) <= 0
|| cmp_sockaddr(&recvaddr, &mdp_addr) != 0
)
)
return WHYF("reply did not come from server: %s", alloca_sockaddr(&recvaddr, recvaddrlen));
return WHYF("reply did not come from server: %s", alloca_socket_address(&recvaddr));
// silently drop incoming packets for the wrong port number
if (port>0 && port != mdp->in.dst.port){

View File

@ -31,8 +31,9 @@ struct mdp_sockaddr {
#define MDP_FLAG_NO_CRYPT (1<<0)
#define MDP_FLAG_NO_SIGN (1<<1)
#define MDP_FLAG_BIND_ALL (1<<2)
#define MDP_FLAG_OK (1<<3)
#define MDP_FLAG_BIND (1<<2)
#define MDP_FLAG_CLOSE (1<<3)
#define MDP_FLAG_ERROR (1<<4)
struct mdp_header {
@ -43,6 +44,9 @@ struct mdp_header {
uint8_t ttl;
};
#define BIND_PRIMARY SID_ANY
#define BIND_ALL SID_BROADCAST
#define TYPE_SID 1
#define TYPE_PIN 2
#define ACTION_LOCK 1
@ -50,6 +54,7 @@ struct mdp_header {
/* Port numbers for commands sent to the local daemon*/
#define MDP_LISTEN 0
/* lock and unlock identities from the local keyring
* Requests start with an mdp_identity_request structure followed by a list of pins or SIDs
*/
@ -82,13 +87,15 @@ struct overlay_mdp_scan{
struct in_addr addr;
};
/* V2 interface */
/* low level V2 mdp interface */
int mdp_socket(void);
int mdp_close(int socket);
int mdp_send(int socket, const struct mdp_header *header, const unsigned char *payload, ssize_t len);
ssize_t mdp_recv(int socket, struct mdp_header *header, unsigned char *payload, ssize_t max_len);
int mdp_send(int socket, const struct mdp_header *header, const uint8_t *payload, size_t len);
ssize_t mdp_recv(int socket, struct mdp_header *header, uint8_t *payload, ssize_t max_len);
int mdp_poll(int socket, time_ms_t timeout_ms);
/* Client-side MDP function */
int overlay_mdp_client_socket(void);
int overlay_mdp_client_close(int mdp_sockfd);

View File

@ -36,15 +36,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#endif
#include <sys/un.h>
#include <fcntl.h>
#include <ctype.h>
#include "constants.h"
#include "conf.h"
#include "log.h"
#include "str.h"
#include "strbuf_helpers.h"
#include "socket.h"
#include "monitor-client.h"
#include <ctype.h>
#define STATE_INIT 0
#define STATE_DATA 1
@ -72,12 +72,11 @@ int monitor_client_open(struct monitor_state **res)
int fd;
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
return WHYF_perror("socket(AF_UNIX, SOCK_STREAM, 0)");
struct sockaddr_un addr;
socklen_t addrlen;
if (make_local_sockaddr(&addr, &addrlen, "monitor.socket") == -1)
struct socket_address addr;
if (make_local_sockaddr(&addr, "monitor.socket") == -1)
return -1;
INFOF("Attempting to connect to %s", alloca_sockaddr(&addr, addrlen));
if (socket_connect(fd, (struct sockaddr*)&addr, addrlen) == -1) {
INFOF("Attempting to connect to %s", alloca_socket_address(&addr));
if (socket_connect(fd, &addr.addr, addr.addrlen) == -1) {
close(fd);
return -1;
}

View File

@ -32,6 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "strbuf_helpers.h"
#include "overlay_address.h"
#include "monitor-client.h"
#include "socket.h"
#ifdef HAVE_UCRED_H
#include <ucred.h>
@ -80,11 +81,10 @@ int monitor_setup_sockets()
int sock = -1;
if ((sock = esocket(AF_UNIX, SOCK_STREAM, 0)) == -1)
goto error;
struct sockaddr_un addr;
socklen_t addrlen;
if (make_local_sockaddr(&addr, &addrlen, "monitor.socket") == -1)
struct socket_address addr;
if (make_local_sockaddr(&addr, "monitor.socket") == -1)
goto error;
if (socket_bind(sock, (struct sockaddr*)&addr, addrlen) == -1)
if (socket_bind(sock, &addr.addr, addr.addrlen) == -1)
goto error;
if (socket_listen(sock, MAX_MONITOR_SOCKETS) == -1)
goto error;
@ -97,7 +97,7 @@ int monitor_setup_sockets()
named_socket.poll.fd=sock;
named_socket.poll.events=POLLIN;
watch(&named_socket);
INFOF("Monitor socket: fd=%d %s", sock, alloca_sockaddr(&addr, addrlen));
INFOF("Monitor socket: fd=%d %s", sock, alloca_socket_address(&addr));
return 0;
error:

View File

@ -313,7 +313,7 @@ int overlay_mdp_service_stun_req(overlay_mdp_frame *mdp)
if (reply.out.payload_length){
if (config.debug.overlayrouting)
DEBUGF("Sending reply");
overlay_mdp_dispatch(&reply,0 /* system generated */, NULL,0);
overlay_mdp_dispatch(&reply, NULL);
}
ob_free(replypayload);
ob_free(payload);
@ -387,7 +387,7 @@ int overlay_send_stun_request(struct subscriber *server, struct subscriber *requ
mdp.out.payload_length=ob_position(payload);
if (config.debug.overlayrouting)
DEBUGF("Sending STUN request to %s", alloca_tohex_sid_t(server->sid));
overlay_mdp_dispatch(&mdp, 0 /* system generated */, NULL,0);
overlay_mdp_dispatch(&mdp, NULL);
}
ob_free(payload);
return 0;

File diff suppressed because it is too large Load Diff

View File

@ -99,7 +99,7 @@ int rhizome_mdp_send_block(struct subscriber *dest, const rhizome_bid_t *bid, ui
reply.out.payload[0]='T';
// send packet
if (overlay_mdp_dispatch(&reply,0 /* system generated */, NULL,0))
if (overlay_mdp_dispatch(&reply, NULL))
break;
}
@ -252,8 +252,7 @@ int overlay_mdp_service_echo(overlay_mdp_frame *mdp)
mdp->packetTypeAndFlags&=~(MDP_NOCRYPT|MDP_NOSIGN);
/* queue frame for delivery */
overlay_mdp_dispatch(mdp,0 /* system generated */,
NULL,0);
overlay_mdp_dispatch(mdp, NULL);
mdp->packetTypeAndFlags=preserved;
/* and switch addresses back around in case the caller was planning on
@ -342,20 +341,20 @@ static int overlay_mdp_service_trace(overlay_mdp_frame *mdp){
mdp->out.payload_length = ob_position(b);
mdp->out.src.sid = my_subscriber->sid;
mdp->out.dst.sid = next->sid;
ret = overlay_mdp_dispatch(mdp, 0, NULL, 0);
ret = overlay_mdp_dispatch(mdp, NULL);
end:
ob_free(b);
RETURN(ret);
}
static int overlay_mdp_service_manifest_requests(struct overlay_frame *frame, overlay_mdp_frame *mdp)
static int overlay_mdp_service_manifest_requests(struct overlay_frame *frame, const uint8_t *payload, size_t len)
{
int offset=0;
while (offset<mdp->out.payload_length) {
while (offset<len) {
rhizome_manifest *m = rhizome_new_manifest();
if (!m)
return WHY("Unable to allocate manifest");
unsigned char *bar = &mdp->out.payload[offset];
const unsigned char *bar = &payload[offset];
if (!rhizome_retrieve_manifest_by_prefix(&bar[RHIZOME_BAR_PREFIX_OFFSET], RHIZOME_BAR_PREFIX_BYTES, m)){
rhizome_advertise_manifest(frame->source, m);
// pre-emptively send the payload if it will fit in a single packet
@ -368,7 +367,7 @@ static int overlay_mdp_service_manifest_requests(struct overlay_frame *frame, ov
return 0;
}
int overlay_mdp_try_interal_services(struct overlay_frame *frame, overlay_mdp_frame *mdp)
int overlay_mdp_try_internal_services(struct overlay_frame *frame, overlay_mdp_frame *mdp)
{
IN();
switch(mdp->out.dst.port) {
@ -383,7 +382,7 @@ int overlay_mdp_try_interal_services(struct overlay_frame *frame, overlay_mdp_fr
case MDP_PORT_STUN: RETURN(overlay_mdp_service_stun(mdp));
case MDP_PORT_RHIZOME_REQUEST: RETURN(overlay_mdp_service_rhizomerequest(frame, mdp));
case MDP_PORT_RHIZOME_RESPONSE: RETURN(overlay_mdp_service_rhizomeresponse(mdp));
case MDP_PORT_RHIZOME_MANIFEST_REQUEST: RETURN(overlay_mdp_service_manifest_requests(frame, mdp));
case MDP_PORT_RHIZOME_MANIFEST_REQUEST: RETURN(overlay_mdp_service_manifest_requests(frame, mdp->out.payload, mdp->out.payload_length));
case MDP_PORT_RHIZOME_SYNC: RETURN(overlay_mdp_service_rhizome_sync(frame, mdp));
}

View File

@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "str.h"
#include "strbuf_helpers.h"
#include "overlay_address.h"
#include "socket.h"
/* Represents a queued fetch of a bundle payload, for which the manifest is already known.
*/
@ -1122,7 +1123,7 @@ static int rhizome_fetch_mdp_requestblocks(struct rhizome_fetch_slot *slot)
slot->write_state.file_offset,
slot->bidVersion);
overlay_mdp_dispatch(&mdp,0 /* system generated */,NULL,0);
overlay_mdp_dispatch(&mdp, NULL);
// remember when we sent the request so that we can adjust the inter-request
// interval based on how fast the packets arrive.

View File

@ -482,7 +482,7 @@ next:
lookup_time = (end_time - start_time);
if (mdp.out.payload_length>0)
overlay_mdp_dispatch(&mdp,0 /* system generated */,NULL,0);
overlay_mdp_dispatch(&mdp, NULL);
end:
sqlite_set_tracefunc(oldfunc);

View File

@ -93,7 +93,7 @@ static void rhizome_sync_request(struct subscriber *subscriber, uint64_t token,
mdp.out.payload_length = ob_position(b);
if (config.debug.rhizome)
DEBUGF("Sending request to %s for BARs from %"PRIu64" %s", alloca_tohex_sid_t(subscriber->sid), token, forwards?"forwards":"backwards");
overlay_mdp_dispatch(&mdp,0,NULL,0);
overlay_mdp_dispatch(&mdp, NULL);
ob_free(b);
}
@ -147,7 +147,7 @@ static void rhizome_sync_send_requests(struct subscriber *subscriber, struct rhi
break;
}
if (mdp.out.payload_length!=0)
overlay_mdp_dispatch(&mdp,0,NULL,0);
overlay_mdp_dispatch(&mdp, NULL);
// send request for more bars if we have room to cache them
if (state->bar_count >= CACHE_BARS)
@ -440,7 +440,7 @@ static void sync_send_response(struct subscriber *dest, int forwards, uint64_t t
mdp.out.payload_length = ob_position(b);
if (config.debug.rhizome_ads)
DEBUGF("Sending %d BARs from %"PRIu64" to %"PRIu64, count, token, last);
overlay_mdp_dispatch(&mdp,0,NULL,0);
overlay_mdp_dispatch(&mdp, NULL);
}
ob_free(b);
OUT();

View File

@ -195,28 +195,6 @@ int formf_serval_instance_path(struct __sourceloc, char *buf, size_t bufsiz, con
int vformf_serval_instance_path(struct __sourceloc, char *buf, size_t bufsiz, const char *fmt, va_list);
void serval_setinstancepath(const char *instancepath);
/* Basic socket operations.
*/
int _make_local_sockaddr(struct __sourceloc, struct sockaddr_un *sockname, socklen_t *addrlen, const char *fmt, ...)
__attribute__((format(printf, 4, 5)));
int _esocket(struct __sourceloc, int domain, int type, int protocol);
int _socket_bind(struct __sourceloc, int sock, const struct sockaddr *addr, socklen_t addrlen);
int _socket_connect(struct __sourceloc, int sock, const struct sockaddr *addr, socklen_t addrlen);
int _socket_listen(struct __sourceloc, int sock, int backlog);
int _socket_set_reuseaddr(struct __sourceloc, int sock, int reuseP);
int _socket_set_rcvbufsize(struct __sourceloc, int sock, unsigned buffer_size);
#define make_local_sockaddr(sockname, addrlenp, fmt,...) _make_local_sockaddr(__WHENCE__, (sockname), (addrlenp), (fmt), ##__VA_ARGS__)
#define esocket(domain, type, protocol) _esocket(__WHENCE__, (domain), (type), (protocol))
#define socket_bind(sock, addr, addrlen) _socket_bind(__WHENCE__, (sock), (addr), (addrlen))
#define socket_connect(sock, addr, addrlen) _socket_connect(__WHENCE__, (sock), (addr), (addrlen))
#define socket_listen(sock, backlog) _socket_listen(__WHENCE__, (sock), (backlog))
#define socket_set_reuseaddr(sock, reuseP) _socket_set_reuseaddr(__WHENCE__, (sock), (reuseP))
#define socket_set_rcvbufsize(sock, buffer_size) _socket_set_rcvbufsize(__WHENCE__, (sock), (buffer_size))
int real_sockaddr(const struct sockaddr_un *src_addr, socklen_t src_addrlen, struct sockaddr_un *dst_addr, socklen_t *dst_addrlen);
int cmp_sockaddr(const struct sockaddr *, socklen_t, const struct sockaddr *, socklen_t);
#define SERVER_CONFIG_RELOAD_INTERVAL_MS 1000
struct cli_parsed;
@ -508,9 +486,6 @@ int rhizome_opendb();
int parseCommandLine(struct cli_context *context, const char *argv0, int argc, const char *const *argv);
int overlay_mdp_get_fds(struct pollfd *fds,int *fdcount,int fdmax);
int overlay_mdp_reply_error(int sock,
struct sockaddr_un *recvaddr, socklen_t recvaddrlen,
int error_number,char *message);
typedef uint32_t mdp_port_t;
#define PRImdp_port_t "#08" PRIx32
@ -572,10 +547,8 @@ typedef struct overlay_mdp_frame {
/* Server-side MDP functions */
int overlay_mdp_swap_src_dst(overlay_mdp_frame *mdp);
int overlay_mdp_reply(int sock,struct sockaddr_un *recvaddr, socklen_t recvaddrlen,
overlay_mdp_frame *mdpreply);
int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
struct sockaddr_un *recvaddr, socklen_t recvaddrlen);
struct socket_address;
int overlay_mdp_dispatch(overlay_mdp_frame *mdp, struct socket_address *client);
void overlay_mdp_encode_ports(struct overlay_buffer *plaintext, mdp_port_t dst_port, mdp_port_t src_port);
int overlay_mdp_dnalookup_reply(const sockaddr_mdp *dstaddr, const sid_t *resolved_sidp, const char *uri, const char *did, const char *name);
@ -688,7 +661,7 @@ int overlay_packetradio_tx_packet(struct overlay_frame *frame);
void overlay_dummy_poll(struct sched_ent *alarm);
void server_config_reload(struct sched_ent *alarm);
void server_shutdown_check(struct sched_ent *alarm);
int overlay_mdp_try_interal_services(struct overlay_frame *frame, overlay_mdp_frame *mdp);
int overlay_mdp_try_internal_services(struct overlay_frame *frame, overlay_mdp_frame *mdp);
int overlay_send_probe(struct subscriber *peer, struct network_destination *destination, int queue);
int overlay_send_stun_request(struct subscriber *server, struct subscriber *request);
void fd_periodicstats(struct sched_ent *alarm);

118
socket.c
View File

@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "conf.h"
#include "log.h"
#include "strbuf_helpers.h"
#include "socket.h"
/* Form the name of an AF_UNIX (local) socket in the instance directory as an absolute path.
* Under Linux, this will create a socket name in the abstract namespace. This permits us to use
@ -40,25 +41,28 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* @author Andrew Bettison <andrew@servalproject.com>
* @author Daniel O'Connor <daniel@servalproject.com>
*/
int _make_local_sockaddr(struct __sourceloc __whence, struct sockaddr_un *addr, socklen_t *addrlen, const char *fmt, ...)
int _make_local_sockaddr(struct __sourceloc __whence, struct socket_address *addr, const char *fmt, ...)
{
bzero(addr, sizeof(*addr));
addr->addr_un.sun_family = AF_UNIX;
va_list ap;
va_start(ap, fmt);
int r = vformf_serval_instance_path(__WHENCE__, addr->sun_path, sizeof addr->sun_path, fmt, ap);
int r = vformf_serval_instance_path(__WHENCE__, addr->addr_un.sun_path, sizeof addr->addr_un.sun_path, fmt, ap);
va_end(ap);
if (!r)
return WHY("socket name overflow");
if (real_sockaddr(addr, sizeof addr->sun_family + strlen(addr->sun_path) + 1, addr, addrlen) == -1)
return -1;
addr->addrlen=sizeof addr->addr_un.sun_family + strlen(addr->addr_un.sun_path) + 1;
// TODO perform real path transformation in making the serval instance path
// if (real_sockaddr(addr, addr) == -1)
// return -1;
#ifdef USE_ABSTRACT_NAMESPACE
// For the abstract name we use the absolute path name with the initial '/' replaced by the
// leading nul. This ensures that different instances of the Serval daemon have different socket
// names.
addr->sun_path[0] = '\0'; // mark as Linux abstract socket
--*addrlen; // do not count trailing nul in abstract socket name
addr->addr_un.sun_path[0] = '\0'; // mark as Linux abstract socket
--addr->addrlen; // do not count trailing nul in abstract socket name
#endif // USE_ABSTRACT_NAMESPACE
addr->sun_family = AF_UNIX;
return 0;
}
@ -74,31 +78,33 @@ int _make_local_sockaddr(struct __sourceloc __whence, struct sockaddr_un *addr,
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
int real_sockaddr(const struct sockaddr_un *src_addr, socklen_t src_addrlen, struct sockaddr_un *dst_addr, socklen_t *dst_addrlen)
int real_sockaddr(const struct socket_address *src_addr, struct socket_address *dst_addr)
{
int src_path_len = src_addrlen - sizeof src_addr->sun_family;
if ( src_addrlen >= sizeof src_addr->sun_family + 1
&& src_addr->sun_family == AF_UNIX
&& src_addr->sun_path[0] != '\0'
&& src_addr->sun_path[src_path_len - 1] == '\0'
int src_path_len = src_addr->addrlen - sizeof src_addr->addr_un.sun_family;
if ( src_addr->addrlen >= sizeof src_addr->addr_un.sun_family + 1
&& src_addr->addr_un.sun_family == AF_UNIX
&& src_addr->addr_un.sun_path[0] != '\0'
&& src_addr->addr_un.sun_path[src_path_len - 1] == '\0'
) {
char real_path[PATH_MAX];
size_t real_path_len;
if (realpath(src_addr->sun_path, real_path) == NULL)
return WHYF_perror("realpath(%s)", alloca_str_toprint(src_addr->sun_path));
else if ((real_path_len = strlen(real_path) + 1) > sizeof dst_addr->sun_path)
return WHYF("sockaddr overrun: realpath(%s) returned %s", alloca_str_toprint(src_addr->sun_path), alloca_str_toprint(real_path));
if (realpath(src_addr->addr_un.sun_path, real_path) == NULL)
return WHYF_perror("realpath(%s)", alloca_str_toprint(src_addr->addr_un.sun_path));
else if ((real_path_len = strlen(real_path) + 1) > sizeof dst_addr->addr_un.sun_path)
return WHYF("sockaddr overrun: realpath(%s) returned %s",
alloca_str_toprint(src_addr->addr_un.sun_path), alloca_str_toprint(real_path));
else if ( real_path_len != src_path_len
|| memcmp(real_path, src_addr->sun_path, src_path_len) != 0
|| memcmp(real_path, src_addr->addr_un.sun_path, src_path_len) != 0
) {
memcpy(dst_addr->sun_path, real_path, real_path_len);
*dst_addrlen = real_path_len + sizeof dst_addr->sun_family;
memcpy(dst_addr->addr_un.sun_path, real_path, real_path_len);
dst_addr->addrlen = real_path_len + sizeof dst_addr->addr_un.sun_family;
return 1;
}
}
if (dst_addr != src_addr)
memcpy(dst_addr, src_addr, src_addrlen);
*dst_addrlen = src_addrlen;
if (dst_addr != src_addr){
memcpy(&dst_addr->addr, &src_addr->addr, src_addr->addrlen);
dst_addr->addrlen = src_addr->addrlen;
}
return 0;
}
@ -107,43 +113,43 @@ int real_sockaddr(const struct sockaddr_un *src_addr, socklen_t src_addrlen, str
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
int cmp_sockaddr(const struct sockaddr *addrA, socklen_t addrlenA, const struct sockaddr *addrB, socklen_t addrlenB)
int cmp_sockaddr(const struct socket_address *addrA, const struct socket_address *addrB)
{
// Two zero-length sockaddrs are equal.
if (addrlenA == 0 && addrlenB == 0)
if (addrA->addrlen == 0 && addrB->addrlen == 0)
return 0;
// If either sockaddr is truncated, then we compare the bytes we have.
if (addrlenA < sizeof addrA->sa_family || addrlenB < sizeof addrB->sa_family) {
int c = memcmp(addrA, addrB, addrlenA < addrlenB ? addrlenA : addrlenB);
if (addrA->addrlen < sizeof addrA->addr.sa_family || addrB->addrlen < sizeof addrB->addr.sa_family) {
int c = memcmp(addrA, addrB, addrA->addrlen < addrB->addrlen ? addrA->addrlen : addrB->addrlen);
if (c == 0)
c = addrlenA < addrlenB ? -1 : addrlenA > addrlenB ? 1 : 0;
c = addrA->addrlen < addrB->addrlen ? -1 : addrA->addrlen > addrB->addrlen ? 1 : 0;
return c;
}
// Order first by address family.
if (addrA->sa_family < addrB->sa_family)
if (addrA->addr.sa_family < addrB->addr.sa_family)
return -1;
if (addrA->sa_family > addrB->sa_family)
if (addrA->addr.sa_family > addrB->addr.sa_family)
return 1;
// Both addresses are in the same family...
switch (addrA->sa_family) {
switch (addrA->addr.sa_family) {
case AF_UNIX: {
unsigned pathlenA = addrlenA - sizeof ((const struct sockaddr_un *)addrA)->sun_family;
unsigned pathlenB = addrlenB - sizeof ((const struct sockaddr_un *)addrB)->sun_family;
unsigned pathlenA = addrA->addrlen - sizeof (addrA->addr_un.sun_family);
unsigned pathlenB = addrB->addrlen - sizeof (addrB->addr_un.sun_family);
int c;
if ( pathlenA > 1 && pathlenB > 1
&& ((const struct sockaddr_un *)addrA)->sun_path[0] == '\0'
&& ((const struct sockaddr_un *)addrB)->sun_path[0] == '\0'
&& addrA->addr_un.sun_path[0] == '\0'
&& addrB->addr_un.sun_path[0] == '\0'
) {
// Both abstract sockets - just compare names, nul bytes are not terminators.
c = memcmp(&((const struct sockaddr_un *)addrA)->sun_path[1],
&((const struct sockaddr_un *)addrB)->sun_path[1],
c = memcmp(&addrA->addr_un.sun_path[1],
&addrB->addr_un.sun_path[1],
(pathlenA < pathlenB ? pathlenA : pathlenB) - 1);
} else {
// Either or both are named local file sockets. If the file names are identical up to the
// first nul, then the addresses are equal. This collates abstract socket names, whose first
// character is a nul, ahead of all non-empty file socket names.
c = strncmp(((const struct sockaddr_un *)addrA)->sun_path,
((const struct sockaddr_un *)addrB)->sun_path,
c = strncmp(addrA->addr_un.sun_path,
addrB->addr_un.sun_path,
(pathlenA < pathlenB ? pathlenA : pathlenB));
}
if (c == 0)
@ -153,9 +159,10 @@ int cmp_sockaddr(const struct sockaddr *addrA, socklen_t addrlenA, const struct
break;
}
// Fall back to comparing raw data bytes.
int c = memcmp(addrA->sa_data, addrB->sa_data, (addrlenA < addrlenB ? addrlenA : addrlenB) - sizeof addrA->sa_family);
int c = memcmp(addrA->addr.sa_data, addrB->addr.sa_data,
(addrA->addrlen < addrB->addrlen ? addrA->addrlen : addrB->addrlen) - sizeof addrA->addr.sa_family);
if (c == 0)
c = addrlenA < addrlenB ? -1 : addrlenA > addrlenB ? 1 : 0;
c = addrA->addrlen < addrB->addrlen ? -1 : addrA->addrlen > addrB->addrlen ? 1 : 0;
return c;
}
@ -225,3 +232,32 @@ int _socket_set_rcvbufsize(struct __sourceloc __whence, int sock, unsigned buffe
DEBUGF("setsockopt(%d, SOL_SOCKET, SO_RCVBUF, &%u, %u)", sock, buffer_size, (unsigned)sizeof buffer_size);
return 0;
}
ssize_t _send_message(struct __sourceloc __whence, int fd, const struct socket_address *address, const struct fragmented_data *data)
{
struct msghdr hdr={
.msg_name=(void *)&address->addr,
.msg_namelen=address->addrlen,
.msg_iov=(struct iovec*)data->iov,
.msg_iovlen=data->fragment_count,
};
ssize_t ret = sendmsg(fd, &hdr, 0);
if (ret==-1)
WHYF_perror("sendmsg(%d,%s,%lu)", fd, alloca_socket_address(address), (unsigned long)address->addrlen);
return ret;
}
ssize_t _recv_message(struct __sourceloc __whence, int fd, struct socket_address *address, struct fragmented_data *data)
{
struct msghdr hdr={
.msg_name=(void *)&address->addr,
.msg_namelen=address->addrlen,
.msg_iov=data->iov,
.msg_iovlen=data->fragment_count,
};
ssize_t ret = recvmsg(fd, &hdr, 0);
if (ret==-1)
WHYF_perror("recvmsg(%d,%s,%lu)", fd, alloca_socket_address(address), (unsigned long)address->addrlen);
return ret;
}

56
socket.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef __SERVALD_SOCKET_H
#define __SERVALD_SOCKET_H
#ifndef WIN32
#include <sys/un.h>
#endif
struct socket_address{
socklen_t addrlen;
union{
struct sockaddr addr;
struct sockaddr_un addr_un;
struct sockaddr_storage store;
};
};
/* Basic socket operations.
*/
int _make_local_sockaddr(struct __sourceloc, struct socket_address *addr, const char *fmt, ...)
__attribute__((format(printf, 3, 4)));
int _esocket(struct __sourceloc, int domain, int type, int protocol);
int _socket_bind(struct __sourceloc, int sock, const struct sockaddr *addr, socklen_t addrlen);
int _socket_connect(struct __sourceloc, int sock, const struct sockaddr *addr, socklen_t addrlen);
int _socket_listen(struct __sourceloc, int sock, int backlog);
int _socket_set_reuseaddr(struct __sourceloc, int sock, int reuseP);
int _socket_set_rcvbufsize(struct __sourceloc, int sock, unsigned buffer_size);
#define make_local_sockaddr(sockname, fmt,...) _make_local_sockaddr(__WHENCE__, (sockname), (fmt), ##__VA_ARGS__)
#define esocket(domain, type, protocol) _esocket(__WHENCE__, (domain), (type), (protocol))
#define socket_bind(sock, addr, addrlen) _socket_bind(__WHENCE__, (sock), (addr), (addrlen))
#define socket_connect(sock, addr, addrlen) _socket_connect(__WHENCE__, (sock), (addr), (addrlen))
#define socket_listen(sock, backlog) _socket_listen(__WHENCE__, (sock), (backlog))
#define socket_set_reuseaddr(sock, reuseP) _socket_set_reuseaddr(__WHENCE__, (sock), (reuseP))
#define socket_set_rcvbufsize(sock, buffer_size) _socket_set_rcvbufsize(__WHENCE__, (sock), (buffer_size))
int real_sockaddr(const struct socket_address *src_addr, struct socket_address *dst_addr);
int cmp_sockaddr(const struct socket_address *addrA, const struct socket_address *addrB);
// helper functions for manipulating fragmented packet data
#define MAX_FRAGMENTS 8
struct fragmented_data{
int fragment_count;
struct iovec iov[MAX_FRAGMENTS];
};
int prepend_fragment(struct fragmented_data *data, const uint8_t *payload, size_t len);
int append_fragment(struct fragmented_data *data, const uint8_t *payload, size_t len);
size_t copy_fragment(struct fragmented_data *src, uint8_t *dest, size_t length);
ssize_t _send_message(struct __sourceloc, int fd, const struct socket_address *address, const struct fragmented_data *data);
ssize_t _recv_message(struct __sourceloc, int fd, struct socket_address *address, struct fragmented_data *data);
#define send_message(fd, address, data) _send_message(__WHENCE__, (fd), (address), (data))
#define recv_message(fd, address, data) _recv_message(__WHENCE__, (fd), (address), (data))
#endif

View File

@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "http_server.h"
#include "strbuf_helpers.h"
#include "str.h"
#include "socket.h"
static inline strbuf _toprint(strbuf sb, char c)
{
@ -374,6 +375,11 @@ strbuf strbuf_append_sockaddr(strbuf sb, const struct sockaddr *addr, socklen_t
return sb;
}
strbuf strbuf_append_socket_address(strbuf sb, const struct socket_address *addr)
{
return strbuf_append_sockaddr(sb, &addr->addr, addr->addrlen);
}
strbuf strbuf_append_strftime(strbuf sb, const char *format, const struct tm *tm)
{
// First, try calling strftime(3) directly on the buffer in the strbuf, if there is one and it

View File

@ -139,6 +139,10 @@ struct sockaddr;
strbuf strbuf_append_sockaddr(strbuf sb, const struct sockaddr *addr, socklen_t addrlen);
#define alloca_sockaddr(addr, addrlen) strbuf_str(strbuf_append_sockaddr(strbuf_alloca(200), (const struct sockaddr *)(addr), (addrlen)))
struct socket_address;
strbuf strbuf_append_socket_address(strbuf sb, const struct socket_address *addr);
#define alloca_socket_address(addr) strbuf_str(strbuf_append_socket_address(strbuf_alloca(200), (addr)))
/* Append a strftime(3) string.
* @author Andrew Bettison <andrew@servalproject.com>
*/

4
vomp.c
View File

@ -523,7 +523,7 @@ static int vomp_send_status_remote(struct vomp_call_state *call)
call->local.sequence++;
overlay_mdp_dispatch(&mdp,0,NULL,0);
overlay_mdp_dispatch(&mdp, NULL);
return 0;
}
@ -561,7 +561,7 @@ int vomp_received_audio(struct vomp_call_state *call, int audio_codec, int time,
mdp.out.queue=OQ_ISOCHRONOUS_VOICE;
overlay_mdp_dispatch(&mdp,0,NULL,0);
overlay_mdp_dispatch(&mdp, NULL);
return 0;
}