コード例 #1
0
static void monitor_requests(struct sched_ent *alarm)
{
  if (config.debug.dnahelper) {
    DEBUGF("sched_requests.poll.fd=%d .revents=%s",
	sched_requests.poll.fd,
	strbuf_str(strbuf_append_poll_events(strbuf_alloca(40), sched_requests.poll.revents))
      );
  }
  assert(alarm == &sched_requests);
  // On Linux, poll(2) returns ERR when the remote reader dies.  On Mac OS X, poll(2) returns NVAL,
  // which is documented to mean the file descriptor is not open, but testing revealed that in this
  // case it is still open.  See issue #5.
  if (sched_requests.poll.revents & (POLLHUP | POLLERR | POLLNVAL)) {
    if (config.debug.dnahelper)
      DEBUGF("DNAHELPER closing stdin fd=%d", dna_helper_stdin);
    close(dna_helper_stdin);
    dna_helper_stdin = -1;
    unwatch(&sched_requests);
    sched_requests.poll.fd = -1;
    dna_helper_kill();
  }
  else if (sched_requests.poll.revents & POLLOUT) {
    if (request_bufptr) {
      if (request_bufptr < request_bufend) {
	size_t remaining = request_bufend - request_bufptr;
	sigPipeFlag = 0;
	ssize_t written = write_nonblock(dna_helper_stdin, request_bufptr, remaining);
	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.
	  */
	  INFO("DNAHELPER got SIGPIPE on write -- stopping process");
	  dna_helper_kill();
	} else if (written > 0) {
	  if (config.debug.dnahelper)
	    DEBUGF("DNAHELPER wrote request %s", alloca_toprint(-1, request_bufptr, written));
	  request_bufptr += written;
	}
      }
      if (request_bufptr >= request_bufend) {
	// Request sent successfully.  Start watching for reply.
	request_bufptr = request_bufend = NULL;
	awaiting_reply = 1;
	sched_timeout.alarm = gettime_ms() + 1500;
	sched_timeout.deadline = sched_timeout.alarm + 3000;
	schedule(&sched_timeout);
      }
    }
    // If no request to send, stop monitoring the helper's stdin pipe.
    if (!request_bufptr) {
      unwatch(&sched_requests);
      sched_requests.poll.fd = -1;
    }
  }
}
コード例 #2
0
ファイル: dna_helper.c プロジェクト: klkblake/serval-dna
static void reply_timeout(struct sched_ent *alarm)
{
  if (awaiting_reply) {
    WHY("DNAHELPER reply timeout");
    dna_helper_kill();
  }
}
コード例 #3
0
void handle_reply_line(const char *bufp, size_t len)
{
  if (!dna_helper_started) {
    if (len == 8 && strncmp(bufp, "STARTED\n", 8) == 0) {
      if (config.debug.dnahelper)
	DEBUGF("DNAHELPER got STARTED ACK");
      dna_helper_started = 1;
      // Start sending request if there is one pending.
      if (request_bufptr) {
	sched_requests.poll.fd = dna_helper_stdin;
	watch(&sched_requests);
      }
    } else {
      WHYF("DNAHELPER malformed start ACK %s", alloca_toprint(-1, bufp, len));
      dna_helper_kill();
    }
  } else if (awaiting_reply) {
    if (len == 5 && strncmp(bufp, "DONE\n", 5) == 0) {
      if (config.debug.dnahelper)
	DEBUG("DNAHELPER reply DONE");
      unschedule(&sched_timeout);
      awaiting_reply = 0;
    } else {
      char sidhex[SID_STRLEN + 1];
      char did[DID_MAXSIZE + 1];
      char name[64];
      char uri[512];
      const char *replyend = NULL;
      if (!parseDnaReply(bufp, len, sidhex, did, name, uri, &replyend))
	WHYF("DNAHELPER reply %s invalid -- ignored", alloca_toprint(-1, bufp, len));
      else if (uri[0] == '\0')
	WHYF("DNAHELPER reply %s contains empty URI -- ignored", alloca_toprint(-1, bufp, len));
      else if (!str_is_uri(uri))
	WHYF("DNAHELPER reply %s contains invalid URI -- ignored", alloca_toprint(-1, bufp, len));
      else if (sidhex[0] == '\0')
	WHYF("DNAHELPER reply %s contains empty token -- ignored", alloca_toprint(-1, bufp, len));
      else if (!str_is_subscriber_id(sidhex))
	WHYF("DNAHELPER reply %s contains invalid token -- ignored", alloca_toprint(-1, bufp, len));
      else if (strncmp(sidhex, request_buffer, SID_STRLEN) != 0)
	WHYF("DNAHELPER reply %s contains mismatched token -- ignored", alloca_toprint(-1, bufp, len));
      else if (did[0] == '\0')
	WHYF("DNAHELPER reply %s contains empty DID -- ignored", alloca_toprint(-1, bufp, len));
      else if (!str_is_did(did))
	WHYF("DNAHELPER reply %s contains invalid DID -- ignored", alloca_toprint(-1, bufp, len));
      else if (strcmp(did, request_did) != 0)
	WHYF("DNAHELPER reply %s contains mismatched DID -- ignored", alloca_toprint(-1, bufp, len));
      else if (*replyend != '\n')
	WHYF("DNAHELPER reply %s contains spurious trailing chars -- ignored", alloca_toprint(-1, bufp, len));
      else {
	if (config.debug.dnahelper)
	  DEBUGF("DNAHELPER reply %s", alloca_toprint(-1, bufp, len));
	overlay_mdp_dnalookup_reply(request_source, request_port, my_subscriber, uri, did, name);
      }
    }
  } else {
    WARNF("DNAHELPER spurious output %s -- ignored", alloca_toprint(-1, bufp, len));
  }
}
コード例 #4
0
static void monitor_replies(struct sched_ent *alarm)
{
  if (config.debug.dnahelper) {
    DEBUGF("sched_replies.poll.fd=%d .revents=%s",
	sched_replies.poll.fd,
	strbuf_str(strbuf_append_poll_events(strbuf_alloca(40), sched_replies.poll.revents))
      );
  }
  assert(alarm == &sched_replies);
  if (sched_replies.poll.revents & POLLIN) {
    size_t remaining = reply_buffer + sizeof reply_buffer - reply_bufend;
    ssize_t nread = read_nonblock(sched_replies.poll.fd, reply_bufend, remaining);
    if (nread > 0) {
      char *bufp = reply_buffer;
      char *readp = reply_bufend;
      reply_bufend += nread;
      char *nl;
      while (nread > 0 && (nl = srv_strnstr(readp, nread, "\n"))) {
	size_t len = nl - bufp + 1;
	if (discarding_until_nl) {
	  if (config.debug.dnahelper)
	    DEBUGF("Discarding %s", alloca_toprint(-1, bufp, len));
	  discarding_until_nl = 0;
	} else {
	  handle_reply_line(bufp, len);
	}
	readp = bufp = nl + 1;
	nread = reply_bufend - readp;
      }
      if (bufp != reply_buffer) {
	size_t len = reply_bufend - bufp;
	memmove(reply_buffer, bufp, len);
	reply_bufend = reply_buffer + len;
      } else if (reply_bufend >= reply_buffer + sizeof reply_buffer) {
	WHY("DNAHELPER reply buffer overrun");
	if (config.debug.dnahelper)
	  DEBUGF("Discarding %s", alloca_toprint(-1, reply_buffer, sizeof reply_buffer));
	reply_bufend = reply_buffer;
	discarding_until_nl = 1;
      }
    }
  }
  if (sched_replies.poll.revents & (POLLHUP | POLLERR | POLLNVAL)) {
    if (config.debug.dnahelper)
      DEBUGF("DNAHELPER closing stdout fd=%d", dna_helper_stdout);
    close(dna_helper_stdout);
    dna_helper_stdout = -1;
    unwatch(&sched_replies);
    sched_replies.poll.fd = -1;
    dna_helper_kill();
  }
}
コード例 #5
0
int dna_helper_shutdown()
{
  if (config.debug.dnahelper)
    DEBUG("DNAHELPER shutting down");
  dna_helper_close_pipes();
  switch (dna_helper_kill()) {
  case -1:
    return -1;
  case 0:
    return 0;
  default:
    return dna_helper_harvest(1);
  }
}