mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-03-11 15:03:56 +00:00
More progress on dnahelper
This commit is contained in:
parent
5aac5a3854
commit
3b44bb6e58
341
dna_helper.c
341
dna_helper.c
@ -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
81
log.c
@ -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
12
net.c
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
42
serval.h
42
serval.h
@ -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);
|
||||
|
7
server.c
7
server.c
@ -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");
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user