More progress on dnahelper

This commit is contained in:
Andrew Bettison 2012-07-19 17:59:45 +09:30
parent 5aac5a3854
commit 3b44bb6e58
8 changed files with 437 additions and 171 deletions

View File

@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include "serval.h"
#include "strbuf.h"
#include "strbuf_helpers.h"
@ -42,10 +43,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
main loop.
*/
static pid_t dna_helper_pid = -1;
static int dna_helper_stdin = -1;
static int dna_helper_stdout = -1;
int
parseDnaReply(const unsigned char *bytes, int count,
char *sidhex, char *did, char *name, char *uri)
@ -77,33 +74,95 @@ parseDnaReply(const unsigned char *bytes, int count,
return 0;
}
static struct sched_ent dna_helper_sched;
static pid_t dna_helper_pid = -1;
static int dna_helper_stdin = -1;
static int dna_helper_stdout = -1;
static int dna_helper_stderr = -1;
static int dna_helper_started = 0;
void dna_helper_monitor(struct sched_ent *alarm);
static struct sched_ent sched_requests = STRUCT_SCHED_ENT_UNUSED;
static struct sched_ent sched_replies = STRUCT_SCHED_ENT_UNUSED;
static struct sched_ent sched_harvester = STRUCT_SCHED_ENT_UNUSED;
static struct sched_ent sched_errors = STRUCT_SCHED_ENT_UNUSED;
static struct sched_ent schedrestart = STRUCT_SCHED_ENT_UNUSED;
static char request_buffer[1024];
static size_t request_length = 0;
void monitor_requests(struct sched_ent *alarm);
void monitor_replies(struct sched_ent *alarm);
void monitor_errors(struct sched_ent *alarm);
void harvester(struct sched_ent *alarm);
static void
dna_helper_close_pipes()
{
if (debug & DEBUG_DNAHELPER)
DEBUG("Closing DNA helper pipes");
if (sched_requests.poll.fd != -1) {
unwatch(&sched_requests);
sched_requests.poll.fd = -1;
}
if (dna_helper_stdin != -1) {
close(dna_helper_stdin);
dna_helper_stdin = -1;
}
if (sched_replies.poll.fd != -1) {
unwatch(&sched_replies);
sched_replies.poll.fd = -1;
}
if (dna_helper_stdout != -1) {
close(dna_helper_stdout);
dna_helper_stdout = -1;
}
if (sched_errors.poll.fd != -1) {
unwatch(&sched_errors);
sched_errors.poll.fd = -1;
}
if (dna_helper_stderr != -1) {
close(dna_helper_stderr);
dna_helper_stderr = -1;
}
}
static int
dna_helper_start(const char *command, const char *arg)
{
int stdin_fds[2], stdout_fds[2];
if (pipe(stdin_fds))
dna_helper_close_pipes();
int stdin_fds[2], stdout_fds[2], stderr_fds[2];
if (pipe(stdin_fds) == -1)
return WHY_perror("pipe");
if (pipe(stdout_fds)) {
if (pipe(stdout_fds) == -1) {
WHY_perror("pipe");
close(stdin_fds[0]);
close(stdin_fds[1]);
return WHY_perror("pipe");
return -1;
}
if (pipe(stderr_fds) == -1) {
WHY_perror("pipe");
close(stdin_fds[0]);
close(stdin_fds[1]);
close(stdout_fds[0]);
close(stdout_fds[1]);
return -1;
}
switch (dna_helper_pid = fork()) {
case 0:
/* Child, should exec() to become helper after installing file descriptors. */
if (dup2(stdin_fds[1], 0)) /* replace stdin */
exit(-1);
if (dup2(stdout_fds[0], 1)) /* replace stdout */
exit(-1);
if (dup2(stdout_fds[0], 2)) /* replace stderr */
exit(-1);
set_logging(stderr);
signal(SIGTERM, SIG_DFL);
close(stdin_fds[1]);
close(stdout_fds[0]);
close(stderr_fds[0]);
if (dup2(stderr_fds[1], 2) == -1 || dup2(stdout_fds[1], 1) == -1 || dup2(stdin_fds[0], 0) == -1) {
LOG_perror(LOG_LEVEL_FATAL, "dup2");
fflush(stderr);
_exit(-1);
}
execl(command, command, arg, NULL);
WHYF_perror("execl(%s, %s, %s, NULL)", command, command, arg ? arg : "NULL");
abort(); /* Can't get here */
LOGF_perror(LOG_LEVEL_FATAL, "execl(%s, %s, %s, NULL)", command, command, arg ? arg : "NULL");
fflush(stderr);
do { _exit(-1); } while (1);
break;
case -1:
/* fork failed */
@ -112,63 +171,221 @@ dna_helper_start(const char *command, const char *arg)
close(stdin_fds[1]);
close(stdout_fds[0]);
close(stdout_fds[1]);
close(stderr_fds[0]);
close(stderr_fds[1]);
return -1;
default:
/* Parent, should put file descriptors into place for use */
INFOF("Started DNA helper, pid=%u: %s %s", dna_helper_pid, command, arg ? arg : "");
dna_helper_stdin = stdin_fds[0];
dna_helper_stdout = stdout_fds[1];
dna_helper_sched.function = dna_helper_monitor;
dna_helper_sched.context = NULL;
dna_helper_sched.poll.fd = dna_helper_stdout;
dna_helper_sched.poll.events = POLLIN;
dna_helper_sched.alarm = overlay_gettime_ms() + 1000;
dna_helper_sched.stats = NULL;
watch(&dna_helper_sched);
schedule(&dna_helper_sched);
close(stdin_fds[0]);
close(stdout_fds[1]);
close(stderr_fds[1]);
dna_helper_started = 0;
dna_helper_stdin = stdin_fds[1];
dna_helper_stdout = stdout_fds[0];
dna_helper_stderr = stderr_fds[0];
INFOF("STARTED DNA HELPER pid=%u stdin=%d stdout=%d stderr=%d executable=%s arg=%s",
dna_helper_pid,
dna_helper_stdin,
dna_helper_stdout,
dna_helper_stderr,
command,
arg ? arg : "NULL"
);
sched_requests.function = monitor_requests;
sched_requests.context = NULL;
sched_requests.poll.fd = dna_helper_stdin;
sched_requests.poll.events = POLLOUT;
sched_requests.stats = NULL;
sched_replies.function = monitor_replies;
sched_replies.context = NULL;
sched_replies.poll.fd = dna_helper_stdout;
sched_replies.poll.events = POLLIN;
sched_replies.stats = NULL;
sched_errors.function = monitor_errors;
sched_errors.context = NULL;
sched_errors.poll.fd = dna_helper_stderr;
sched_errors.poll.events = POLLIN;
sched_errors.stats = NULL;
sched_harvester.function = harvester;
sched_harvester.stats = NULL;
sched_harvester.alarm = overlay_gettime_ms() + 1000;
watch(&sched_replies);
watch(&sched_errors);
schedule(&sched_harvester);
return 0;
}
return -1;
}
static int
dna_helper_harvest()
dna_helper_stop()
{
D;
if (dna_helper_pid > 0) {
if (debug & DEBUG_DNAHELPER)
DEBUGF("Sending SIGTERM to DNA helper pid=%d", dna_helper_pid);
if (kill(dna_helper_pid, SIGTERM) == -1)
WHYF_perror("kill(%d, SIGTERM)", dna_helper_pid);
// The process is wait()ed for in dna_helper_monitor() so that we do not block here.
return 1;
}
return 0;
}
static int
dna_helper_harvest(int blocking)
{
if (dna_helper_pid > 0) {
if (blocking && (debug & DEBUG_DNAHELPER))
DEBUGF("Waiting for DNA helper pid=%d to die", dna_helper_pid);
int status;
pid_t pid = waitpid(dna_helper_pid, &status, WNOHANG);
pid_t pid = waitpid(dna_helper_pid, &status, blocking ? 0 : WNOHANG);
if (pid == dna_helper_pid) {
strbuf b = strbuf_alloca(80);
INFOF("DNA helper pid=%u %s", pid, strbuf_str(strbuf_append_exit_status(b, status)));
unschedule(&dna_helper_sched);
unwatch(&dna_helper_sched);
unschedule(&sched_harvester);
dna_helper_pid = -1;
return 1;
} else if (pid == -1) {
return WHYF_perror("waitpid(%d, WNOHANG)", dna_helper_pid);
return WHYF_perror("waitpid(%d, %s)", dna_helper_pid, blocking ? "0" : "WNOHANG");
} else if (pid) {
return WHYF("waitpid(%d, WNOHANG) returned %d", dna_helper_pid, pid);
return WHYF("waitpid(%d, %s) returned %d", dna_helper_pid, blocking ? "0" : "WNOHANG", pid);
}
}
return 0;
}
void dna_helper_monitor(struct sched_ent *alarm)
int dna_helper_shutdown()
{
if (alarm != &dna_helper_sched) {
WHY("Alarm not for me");
return;
if (debug & DEBUG_DNAHELPER)
DEBUG("Shutting down DNA helper");
dna_helper_close_pipes();
switch (dna_helper_stop()) {
case -1:
return -1;
case 0:
return 0;
default:
return dna_helper_harvest(1);
}
if (dna_helper_sched.poll.revents & POLLIN) {
}
void dna_helper_restart(struct sched_ent *alarm)
{
if (debug & DEBUG_DNAHELPER)
DEBUG("Re-enable DNA helper restart");
if (dna_helper_pid == 0)
dna_helper_pid = -1;
}
void monitor_requests(struct sched_ent *alarm)
{
if (debug & DEBUG_DNAHELPER) {
DEBUGF("sched_requests.poll.revents=%s",
strbuf_str(strbuf_append_poll_events(strbuf_alloca(40), sched_requests.poll.revents))
);
}
if (sched_requests.poll.revents & (POLLHUP | POLLERR)) {
WARN("DNA helper stdin closed -- stopping DNA helper");
close(dna_helper_stdin);
dna_helper_stdin = -1;
unwatch(&sched_requests);
sched_requests.poll.fd = -1;
dna_helper_stop();
}
else if (sched_requests.poll.revents & POLLOUT) {
unwatch(&sched_requests);
sched_requests.poll.fd = -1;
if (request_length) {
sigPipeFlag = 0;
if (write_all(dna_helper_stdin, request_buffer, request_length) == request_length) {
// Request sent successfully. Start watching for reply.
request_length = 0;
} else if (sigPipeFlag) {
/* Broken pipe is probably due to a dead helper, but make sure the helper is dead, just to be
sure. It will be harvested at the next harvester() timeout, and restarted on the first
request that arrives after a suitable pause has elapsed. Losing the current request is not
a big problem, because DNA preemptively retries.
*/
WARN("Got SIGPIPE from DNA helper -- stopping DNA helper");
dna_helper_stop();
}
}
}
}
void monitor_replies(struct sched_ent *alarm)
{
if (debug & DEBUG_DNAHELPER) {
DEBUGF("sched_replies.poll.revents=%s",
strbuf_str(strbuf_append_poll_events(strbuf_alloca(40), sched_replies.poll.revents))
);
}
if (sched_replies.poll.revents & POLLIN) {
if (dna_helper_started) {
unsigned char buffer[1024];
if (read_nonblock(dna_helper_sched.poll.fd, buffer, sizeof buffer) != -1) {
DEBUGF("Got DNA helper reply %s", alloca_toprint(160, buffer, sizeof buffer));
ssize_t nread = read_nonblock(sched_replies.poll.fd, buffer, sizeof buffer);
if (nread > 0) {
if (debug & DEBUG_DNAHELPER)
DEBUGF("DNA helper reply %s", alloca_toprint(-1, buffer, nread));
// TODO parse and send DNA reply
}
} else {
unsigned char buffer[8];
ssize_t nread = read_nonblock(sched_replies.poll.fd, buffer, sizeof buffer);
if (nread > 0) {
if (nread == sizeof buffer && strncmp((const char *)buffer, "STARTED\n", sizeof buffer) == 0)
dna_helper_started = 1;
else {
WHYF("Unexpected DNA helper ACK %s", alloca_toprint(-1, buffer, nread));
dna_helper_stop();
}
}
if (dna_helper_harvest() <= 0) {
dna_helper_sched.alarm = overlay_gettime_ms() + 1000;
schedule(alarm);
}
}
if (sched_replies.poll.revents & (POLLHUP | POLLERR)) {
close(dna_helper_stdout);
dna_helper_stdout = -1;
unwatch(&sched_replies);
sched_replies.poll.fd = -1;
}
}
void monitor_errors(struct sched_ent *alarm)
{
if (debug & DEBUG_DNAHELPER) {
DEBUGF("sched_errors.poll.revents=%s",
strbuf_str(strbuf_append_poll_events(strbuf_alloca(40), sched_errors.poll.revents))
);
}
if (sched_errors.poll.revents & POLLIN) {
unsigned char buffer[1024];
ssize_t nread = read_nonblock(sched_errors.poll.fd, buffer, sizeof buffer);
if (nread > 0 && (debug & DEBUG_DNAHELPER))
DEBUGF("DNA helper stderr %s", alloca_toprint(-1, buffer, nread));
}
if (sched_errors.poll.revents & (POLLHUP | POLLERR)) {
close(dna_helper_stdout);
dna_helper_stdout = -1;
unwatch(&sched_errors);
sched_errors.poll.fd = -1;
}
}
void harvester(struct sched_ent *alarm)
{
// While the helper process appears to still be running, keep calling this function.
// Otherwise, wait a while before re-starting the helper.
if (dna_helper_harvest(0) <= 0) {
sched_harvester.alarm = overlay_gettime_ms() + 1000;
schedule(&sched_harvester);
} else {
const int delay_ms = 2000;
if (debug & DEBUG_DNAHELPER)
DEBUGF("DNA helper has died, pausing %d ms before restart", delay_ms);
dna_helper_pid = 0;
schedrestart.function = dna_helper_restart;
schedrestart.alarm = overlay_gettime_ms() + delay_ms;
schedule(&schedrestart);
}
}
@ -190,7 +407,7 @@ dna_helper_enqueue(char *did, unsigned char *requestorSid)
}
if (dna_helper_start(dna_helper_executable, dna_helper_arg1) < 0) {
/* Something broke, bail out */
DEBUG("Failed to start dna helper");
WHY("Failed to start DNA helper");
return -1;
}
}
@ -200,29 +417,17 @@ dna_helper_enqueue(char *did, unsigned char *requestorSid)
any state, as all we have to do is wait for responses from the helper,
which will include the requestor's SID.
*/
char buffer[1024];
strbuf b = strbuf_local(buffer, sizeof buffer);
if (request_length) {
WARN("DNA helper request already pending -- dropping new request");
} else {
strbuf b = strbuf_local(request_buffer, sizeof request_buffer);
strbuf_sprintf(b, "%s|%s|\n", alloca_tohex_sid(requestorSid), did);
if (strbuf_overrun(b))
return WHY("DNA helper buffer overrun");
sigPipeFlag = 0;
write_all(dna_helper_stdin, strbuf_str(b), strbuf_len(b));
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.
*/
WARN("Got SIGPIPE from DNA helper");
close(dna_helper_stdin);
close(dna_helper_stdout);
dna_helper_stdin = -1;
dna_helper_stdout = -1;
dna_helper_harvest();
return -1;
return WHY("DNA helper request buffer overrun -- request not sent");
else {
request_length = strbuf_len(b);
watch(&sched_requests);
}
}
return 0;
}

81
log.c
View File

@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "serval.h"
#include "strbuf.h"
#include <stdio.h>
#include <ctype.h>
#include <sys/time.h>
#include <time.h>
@ -38,6 +39,17 @@ static struct strbuf logbuf = STRUCT_STRBUF_EMPTY;
#include <android/log.h>
#endif
void set_logging(FILE *f)
{
logfile = f;
if (f == stdout)
INFO("Logging to stdout");
else if (f == stderr)
INFO("Logging to stderr");
else if (f != NULL)
INFOF("Logging to stream with fd=%d", fileno(f));
}
FILE *open_logging()
{
if (!logfile) {
@ -227,7 +239,7 @@ unsigned int debugFlagMask(const char *flagname) {
else if (!strcasecmp(flagname,"verbio")) return DEBUG_VERBOSE_IO;
else if (!strcasecmp(flagname,"peers")) return DEBUG_PEERS;
else if (!strcasecmp(flagname,"dnaresponses")) return DEBUG_DNARESPONSES;
else if (!strcasecmp(flagname,"dnarequests")) return DEBUG_DNAREQUESTS;
else if (!strcasecmp(flagname,"dnahelper")) return DEBUG_DNAHELPER;
else if (!strcasecmp(flagname,"simulation")) return DEBUG_SIMULATION;
else if (!strcasecmp(flagname,"packetformats")) return DEBUG_PACKETFORMATS;
else if (!strcasecmp(flagname,"packetconstruction")) return DEBUG_PACKETCONSTRUCTION;
@ -249,34 +261,49 @@ unsigned int debugFlagMask(const char *flagname) {
return 0;
}
static strbuf _toprint(strbuf sb, const unsigned char *srcBuf, size_t srcBytes)
{
strbuf_putc(sb, '"');
for (; srcBytes && !strbuf_overrun(sb); ++srcBuf, --srcBytes) {
if (*srcBuf == '\0')
strbuf_puts(sb, "\\0");
else if (*srcBuf == '\n')
strbuf_puts(sb, "\\n");
else if (*srcBuf == '\r')
strbuf_puts(sb, "\\r");
else if (*srcBuf == '\t')
strbuf_puts(sb, "\\t");
else if (*srcBuf == '\\')
strbuf_puts(sb, "\\\\");
else if (*srcBuf >= ' ' && *srcBuf <= '~')
strbuf_putc(sb, *srcBuf);
else
strbuf_sprintf(sb, "\\x%02x", *srcBuf);
}
strbuf_putc(sb, '"');
if (strbuf_overrun(sb)) {
strbuf_trunc(sb, -4);
strbuf_puts(sb, "\"...");
}
return sb;
}
/* Format a buffer of data as a printable representation, eg: "Abc\x0b\n\0", for display
in log messages.
in log messages. If dstStrLen == -1 then assumes the dstStr buffer is large enough to
hold the representation of the entire srcBuf.
@author Andrew Bettison <andrew@servalproject.com>
*/
char *toprint(char *dstStr, size_t dstChars, const unsigned char *srcBuf, size_t srcBytes)
char *toprint(char *dstStr, ssize_t dstStrLen, const unsigned char *srcBuf, size_t srcBytes)
{
strbuf b = strbuf_local(dstStr, dstChars);
strbuf_putc(b, '"');
for (; srcBytes && !strbuf_overrun(b); ++srcBuf, --srcBytes) {
if (*srcBuf == '\0')
strbuf_puts(b, "\\0");
else if (*srcBuf == '\n')
strbuf_puts(b, "\\n");
else if (*srcBuf == '\r')
strbuf_puts(b, "\\r");
else if (*srcBuf == '\t')
strbuf_puts(b, "\\t");
else if (*srcBuf == '\\')
strbuf_puts(b, "\\\\");
else if (*srcBuf >= ' ' && *srcBuf <= '~')
strbuf_putc(b, *srcBuf);
else
strbuf_sprintf(b, "\\x%02x", *srcBuf);
}
strbuf_putc(b, '"');
if (strbuf_overrun(b)) {
strbuf_trunc(b, -4);
strbuf_puts(b, "\"...");
}
return dstStr;
return strbuf_str(_toprint(strbuf_local(dstStr, (dstStrLen == -1 ? 2 + srcBytes * 4 : dstStrLen) + 1), srcBuf, srcBytes));
}
/* Compute the length of the printable string produced by toprint(). If dstStrLen == -1 then
returns the exact number of characters in the printable representation, otherwise returns
dstStrLen.
@author Andrew Bettison <andrew@servalproject.com>
*/
size_t toprint_strlen(ssize_t dstStrLen, const unsigned char *srcBuf, size_t srcBytes)
{
return dstStrLen == -1 ? strbuf_count(_toprint(strbuf_local(NULL, 0), srcBuf, srcBytes)) : dstStrLen;
}

12
net.c
View File

@ -47,7 +47,7 @@ int _set_block(int fd, const char *file, unsigned int line, const char *function
return 0;
}
int _read_nonblock(int fd, void *buf, size_t len, const char *file, unsigned int line, const char *function)
ssize_t _read_nonblock(int fd, void *buf, size_t len, const char *file, unsigned int line, const char *function)
{
ssize_t nread = read(fd, buf, len);
if (nread == -1) {
@ -66,7 +66,7 @@ int _read_nonblock(int fd, void *buf, size_t len, const char *file, unsigned int
return nread;
}
int _write_all(int fd, const void *buf, size_t len, const char *file, unsigned int line, const char *function)
ssize_t _write_all(int fd, const void *buf, size_t len, const char *file, unsigned int line, const char *function)
{
ssize_t written = write(fd, buf, len);
if (written == -1) {
@ -82,7 +82,7 @@ int _write_all(int fd, const void *buf, size_t len, const char *file, unsigned i
return written;
}
int _write_nonblock(int fd, const void *buf, size_t len, const char *file, unsigned int line, const char *function)
ssize_t _write_nonblock(int fd, const void *buf, size_t len, const char *file, unsigned int line, const char *function)
{
ssize_t written = write(fd, buf, len);
if (written == -1) {
@ -101,7 +101,7 @@ int _write_nonblock(int fd, const void *buf, size_t len, const char *file, unsig
return written;
}
int _write_all_nonblock(int fd, const void *buf, size_t len, const char *file, unsigned int line, const char *function)
ssize_t _write_all_nonblock(int fd, const void *buf, size_t len, const char *file, unsigned int line, const char *function)
{
ssize_t written = _write_nonblock(fd, buf, len, file, line, function);
if (written != -1 && written != len) {
@ -112,12 +112,12 @@ int _write_all_nonblock(int fd, const void *buf, size_t len, const char *file, u
return written;
}
int _write_str(int fd, const char *str, const char *file, unsigned int line, const char *function)
ssize_t _write_str(int fd, const char *str, const char *file, unsigned int line, const char *function)
{
return _write_all(fd, str, strlen(str), file, line, function);
}
int _write_str_nonblock(int fd, const char *str, const char *file, unsigned int line, const char *function)
ssize_t _write_str_nonblock(int fd, const char *str, const char *file, unsigned int line, const char *function)
{
return _write_all_nonblock(fd, str, strlen(str), file, line, function);
}

View File

@ -296,7 +296,7 @@ int extractRequest(unsigned char *packet,int *packet_ofs,int packet_len,
*bytes|=packet[(*packet_ofs)++];
*flags=packet[(*packet_ofs)++];
if (debug&DEBUG_DNAREQUESTS) printf("Write flags = 0x%02x\n",*flags);
if (debug&DEBUG_PACKETFORMATS) printf("Write flags = 0x%02x\n",*flags);
if (*packet_ofs<0||(*packet_ofs)+(*bytes)>=packet_len)
{

View File

@ -503,6 +503,7 @@ struct sched_ent{
int _poll_index;
};
#define STRUCT_SCHED_ENT_UNUSED ((struct sched_ent){NULL, NULL, NULL, NULL, {-1, 0, 0}, 0LL, NULL, -1})
extern int overlayMode;
#define OVERLAY_INTERFACE_UNKNOWN 0
@ -782,6 +783,7 @@ int overlay_frame_resolve_addresses(overlay_frame *f);
#define LOG_LEVEL_FATAL (4)
extern unsigned int debug;
void set_logging(FILE *f);
FILE *open_logging();
void close_logging();
void logMessage(int level, const char *file, unsigned int line, const char *function, const char *fmt, ...);
@ -789,40 +791,46 @@ void vlogMessage(int level, const char *file, unsigned int line, const char *fun
unsigned int debugFlagMask(const char *flagname);
char *catv(const char *data, char *buf, size_t len);
int dump(char *name, unsigned char *addr, size_t len);
char *toprint(char *dstStr, size_t dstChars, const unsigned char *srcBuf, size_t srcBytes);
char *toprint(char *dstStr, ssize_t dstStrLen, const unsigned char *srcBuf, size_t srcBytes);
size_t toprint_strlen(ssize_t dstStrLen, const unsigned char *srcBuf, size_t srcBytes);
#define alloca_toprint(dstlen,buf,len) toprint((char *)alloca((dstlen) + 1), (dstlen) + 1, (buf), (len))
#define alloca_toprint(dstlen,buf,len) toprint((char *)alloca(toprint_strlen((dstlen), (buf), (len)) + 1), (dstlen), (buf), (len))
#define alloca_tohex(buf,len) tohex((char *)alloca((len)*2+1), (buf), (len))
#define alloca_tohex_sid(sid) alloca_tohex((sid), SID_SIZE)
const char *trimbuildpath(const char *s);
#define LOGF(L,F,...) (logMessage(L, __FILE__, __LINE__, __FUNCTION__, F, ##__VA_ARGS__))
#define logMessage_perror(L,file,line,func,F,...) \
(logMessage(L, file, line, func, F ": %s [errno=%d]", ##__VA_ARGS__, strerror(errno), errno))
#define LOGF(L,F,...) logMessage(L, __FILE__, __LINE__, __FUNCTION__, F, ##__VA_ARGS__)
#define LOGF_perror(L,F,...) logMessage_perror(L, __FILE__, __LINE__, __FUNCTION__, F, ##__VA_ARGS__)
#define LOG_perror(L,X) LOGF_perror(L, "%s", (X))
#define FATALF(F,...) do { LOGF(LOG_LEVEL_FATAL, F, ##__VA_ARGS__); exit(-1); } while (1)
#define FATAL(X) FATALF("%s", (X))
#define FATAL_perror(X) FATALF("%s: %s [errno=%d]", (X), strerror(errno), errno)
#define FATALF_perror(F,...) do { LOGF_perror(LOG_LEVEL_FATAL, F, ##__VA_ARGS__); exit(-1); } while (1)
#define FATAL_perror(X) FATALF_perror("%s", (X))
#define WHYF(F,...) (LOGF(LOG_LEVEL_ERROR, F, ##__VA_ARGS__), -1)
#define WHY(X) WHYF("%s", (X))
#define WHYNULL(X) (LOGF(LOG_LEVEL_ERROR, "%s", X), NULL)
#define WHYF_perror(F,...) WHYF(F ": %s [errno=%d]", ##__VA_ARGS__, strerror(errno), errno)
#define WHY_perror(X) WHYF("%s: %s [errno=%d]", (X), strerror(errno), errno)
#define WHYF_perror(F,...) (LOGF_perror(LOG_LEVEL_ERROR, F, ##__VA_ARGS__), -1)
#define WHY_perror(X) WHYF_perror("%s", (X))
#define WARNF(F,...) LOGF(LOG_LEVEL_WARN, F, ##__VA_ARGS__)
#define WARN(X) WARNF("%s", (X))
#define WARN_perror(X) WARNF("%s: %s [errno=%d]", (X), strerror(errno), errno)
#define WARNF_perror(F,...) LOGF_perror(LOG_LEVEL_WARN, F, ##__VA_ARGS__)
#define WARN_perror(X) WARNF_perror("%s", (X))
#define INFOF(F,...) LOGF(LOG_LEVEL_INFO, F, ##__VA_ARGS__)
#define INFO(X) INFOF("%s", (X))
#define DEBUGF(F,...) LOGF(LOG_LEVEL_DEBUG, F, ##__VA_ARGS__)
#define DEBUG(X) DEBUGF("%s", (X))
#define DEBUGF_perror(F,...) DEBUGF(F ": %s [errno=%d]", ##__VA_ARGS__, strerror(errno), errno)
#define DEBUG_perror(X) DEBUGF("%s: %s [errno=%d]", (X), strerror(errno), errno)
#define DEBUGF_perror(F,...) LOGF_perror(LOG_LEVEL_DEBUG, F, ##__VA_ARGS__)
#define DEBUG_perror(X) DEBUGF_perror("%s", (X))
#define D DEBUG("D")
overlay_buffer *ob_new(int size);
@ -1087,7 +1095,7 @@ int overlay_saw_mdp_containing_frame(overlay_frame *f,long long now);
#define DEBUG_VERBOSE_IO (1 << 3)
#define DEBUG_PEERS (1 << 4)
#define DEBUG_DNARESPONSES (1 << 5)
#define DEBUG_DNAREQUESTS (1 << 6)
#define DEBUG_DNAHELPER (1 << 6)
#define DEBUG_SIMULATION (1 << 7)
#define DEBUG_RHIZOME_RX (1 << 8)
#define DEBUG_PACKETFORMATS (1 << 9)
@ -1574,12 +1582,12 @@ void sigIoHandler(int signal);
int _set_nonblock(int fd, const char *file, unsigned int line, const char *function);
int _set_block(int fd, const char *file, unsigned int line, const char *function);
int _read_nonblock(int fd, void *buf, size_t len, const char *file, unsigned int line, const char *function);
int _write_all(int fd, const void *buf, size_t len, const char *file, unsigned int line, const char *function);
int _write_nonblock(int fd, const void *buf, size_t len, const char *file, unsigned int line, const char *function);
int _write_all_nonblock(int fd, const void *buf, size_t len, const char *file, unsigned int line, const char *function);
int _write_str(int fd, const char *str, const char *file, unsigned int line, const char *function);
int _write_str_nonblock(int fd, const char *str, const char *file, unsigned int line, const char *function);
ssize_t _read_nonblock(int fd, void *buf, size_t len, const char *file, unsigned int line, const char *function);
ssize_t _write_all(int fd, const void *buf, size_t len, const char *file, unsigned int line, const char *function);
ssize_t _write_nonblock(int fd, const void *buf, size_t len, const char *file, unsigned int line, const char *function);
ssize_t _write_all_nonblock(int fd, const void *buf, size_t len, const char *file, unsigned int line, const char *function);
ssize_t _write_str(int fd, const char *str, const char *file, unsigned int line, const char *function);
ssize_t _write_str_nonblock(int fd, const char *str, const char *file, unsigned int line, const char *function);
int rhizome_http_server_start();
int overlay_mdp_setup_sockets();
@ -1600,6 +1608,8 @@ void overlay_mdp_poll(struct sched_ent *alarm);
void fd_periodicstats(struct sched_ent *alarm);
void rhizome_check_connections(struct sched_ent *alarm);
int dna_helper_shutdown();
void monitor_client_poll(struct sched_ent *alarm);
void monitor_poll(struct sched_ent *alarm);
void overlay_interface_poll(struct sched_ent *alarm);

View File

@ -302,6 +302,7 @@ void serverCleanUp()
} else {
overlay_mdp_client_done();
}
dna_helper_shutdown();
}
static void signame(char *buf, size_t len, int signal)
@ -473,7 +474,7 @@ int processRequest(unsigned char *packet,int len,
while(pofs<len)
{
if (debug&DEBUG_DNAREQUESTS) DEBUGF(" processRequest: len=%d, pofs=%d, pofs_prev=%d",len,pofs,prev_pofs);
if (debug&DEBUG_DNARESPONSES) DEBUGF(" processRequest: len=%d, pofs=%d, pofs_prev=%d",len,pofs,prev_pofs);
/* Avoid infinite loops */
if (pofs<=prev_pofs) break;
prev_pofs=pofs;
@ -504,7 +505,7 @@ int processRequest(unsigned char *packet,int len,
}
else
{
if (debug&DEBUG_DNAREQUESTS) DEBUGF("Looking at action code 0x%02x @ packet offset 0x%x",
if (debug&DEBUG_DNARESPONSES) DEBUGF("Looking at action code 0x%02x @ packet offset 0x%x",
packet[pofs],pofs);
switch(packet[pofs])
{
@ -559,7 +560,7 @@ int processRequest(unsigned char *packet,int len,
pofs+=2;
if (debug&DEBUG_DNAREQUESTS) DEBUGF("Processing ACTION_GET (var_id=%02x, instance=%02x, pofs=0x%x, len=%d)",var_id,instance,pofs,len);
if (debug&DEBUG_DNARESPONSES) DEBUGF("Processing ACTION_GET (var_id=%02x, instance=%02x, pofs=0x%x, len=%d)",var_id,instance,pofs,len);
if (debug&DEBUG_HLR) DEBUGF("Looking for identities with sid='%s' / did='%s'",(sid&&sid[0])?sid:"null",did?did:"null");

View File

@ -76,7 +76,9 @@ strbuf strbuf_append_exit_status(strbuf sb, int status)
#endif
} else if (WIFSTOPPED(status))
strbuf_sprintf(sb, "stopped by signal %u (%s)", WSTOPSIG(status), strsignal(WSTOPSIG(status)));
#ifdef WIFCONTINUED
else if (WIFCONTINUED(status))
strbuf_sprintf(sb, "continued by signal %u (SIGCONT)", SIGCONT);
#endif
return sb;
}

View File

@ -37,7 +37,8 @@ teardown() {
configure_servald_server() {
executeOk_servald config set log.show_pid on
executeOk_servald config set log.show_time on
executeOk_servald config set dna.helper.executable "$TFWTMP/dnahelper"
executeOk_servald config set debug.dnahelper on
executeOk_servald config set dna.helper.executable "$dnahelper"
}
setup_dnahelper() {
@ -48,7 +49,9 @@ setup_dnahelper() {
import sys
def main():
print "STARTED"
sys.stdout.flush()
while True:
sys.stderr.write("wah\n")
line = sys.stdin.readline().strip()
if line == "":
# EOF detection is broken :(
@ -62,35 +65,53 @@ def main():
# Multiple results (SID/VoMP results)
print "%s|sid:%s|%s|%s|" % (token, token, number, "Agent A. Smith")
print "%s|sid:%s|%s|%s|" % (token, token, number, "Agent B. Smith")
if number == "5551234":
elif number == "5551234":
# Single result, SIP URI
print "%s|sip://5551234@10.1.2.3|%s|%s|" % (token, number, "Will Smith")
if number == "5551001":
elif number == "5551001":
# Empty URI field
print "%s||%s|%s|" % (token, number, "Empty URI")
if number == "5551002":
elif number == "5551002":
# Empty DID field
print "%s|sip://123@1.2.3.4||%s|" % (token, "Empty DID")
if number == "5551003":
elif number == "5551003":
# Empty CALLERID field
print "%s|sip://empty-callerid@1.2.3.4|%s||" % (token, number)
if number == "5551004":
elif number == "5551004":
# Excessively long callerid
print "%s|sip://long-callerid@1.2.3.4|%s|%s|" % (token, 'x' * 200, number)
if number == "5551005":
elif number == "5551005":
# Excessively long DID
print "%s|sip://long-did@1.2.3.4|%s|%s|" % (token, 'x' * 200, "Agent Smith")
if number == "5551006":
elif number == "5551006":
# Excessively long URI
print "%s|sip://%s|%s|%s|" % (token, 'x' * 1000, number, "Agent Smith")
if number == "5551007":
elif number == "5551007":
# Incorrect token
print "cheeseburger|sip://incorrect-token@1.2.3.4|%s||" % (token, number)
elif number == "11111":
print "%s|A|%s|B|" % (token, number)
print "DONE"
sys.stdout.flush()
if __name__ == "__main__":
main()
EOF
chmod 0755 "$dnahelper"
executeOk "$dnahelper" <<EOF
ToKeN|11111|
EOF
assertStdoutIs -e "STARTED\nToKeN|A|11111|B|\nDONE\n"
}
doc_ExecError="Non-existent DNA helper executable"
setup_ExecError() {
setup
dnahelper=/non/existent
assert [ ! -e "$dnahelper" ]
start_servald_instances +A
}
test_ExecError() {
executeOk_servald dna lookup 12345
}
doc_Simple="Simple DNA helper test"