예제 #1
0
static void read_stdin(ph_job_t *job, ph_iomask_t why, void *data)
{
  char buf[128];
  int x, i;

  ph_unused_parameter(why);
  ph_unused_parameter(data);

  x = read(job->fd, buf, sizeof(buf));
  if (x <= 0) {
    if (x == -1) {
      ph_log(PH_LOG_ERR, "read(stdin): `Pe%d", errno);
    }
    ph_sched_stop();
    return;
  }

  // Writing to the other job is safe here because we have the
  // same affinity: we know that it is not executing and mutating
  // its state
  for (i = 0; i < x; i++) {
    if (buf[i] == '\n') {
      ph_stm_write(remote_sock->stream, "\r\n", 2, NULL);
    } else {
      ph_stm_write(remote_sock->stream, buf + i, 1, NULL);
    }
  }

  // Force the sock to wakeup and send the buffer.
  // FIXME: Need something nicer than this hack
  ph_sock_enable(remote_sock, false);
  ph_sock_enable(remote_sock, true);

  ph_job_set_nbio_timeout_in(job, PH_IOMASK_READ, timeout);
}
예제 #2
0
파일: stream.c 프로젝트: kunth/libphenom
int main(int argc, char **argv)
{
  ph_stream_t *stm;
  char namebuf[128];
  int fd;
  char buf[BUFSIZ];
  uint64_t amount;
  int len;

  ph_unused_parameter(argc);
  ph_unused_parameter(argv);

  ph_library_init();
  plan_tests(18);

  strcpy(namebuf, "/tmp/phenomXXXXXX");
  fd = ph_mkostemp(namebuf, 0);
  diag("opened %s -> %d", namebuf, fd);
  unlink(namebuf);

  stm = ph_stm_fd_open(fd, 0, PH_STM_BUFSIZE);
  ph_stm_write(stm, "lemon\n", 6, &amount);
  is(amount, 6);

  // Shouldn't see it yet
  is(0, pread(fd, buf, sizeof(buf), 0));

  // Should see it now
  ph_stm_flush(stm);
  is(6, pread(fd, buf, sizeof(buf), 0));

  ok(!memcmp("lemon\n", buf, 6), "right content");
  ok(ph_stm_seek(stm, 0, SEEK_SET, NULL), "seeked");
  memset(buf, 0, sizeof(buf));

  ok(ph_stm_read(stm, buf, 3, &amount), "read ok");
  ok(amount == 3, "amount is %" PRIu64, amount);
  ok(!memcmp("lem", buf, 3), "got prefix");

  ok(ph_stm_read(stm, buf, 3, &amount), "read ok");
  ok(amount == 3, "amount is %" PRIu64, amount);
  ok(!memcmp("on\n", buf, 3), "got remainder");

  ok(ph_stm_seek(stm, 0, SEEK_SET, NULL), "seeked");
  len = ph_stm_printf(stm, "testing %d %s!", 1, "two");
  ok(14 == len, "printed len %d", len);
  ok(ph_stm_seek(stm, 0, SEEK_SET, NULL), "seeked");
  memset(buf, 0, sizeof(buf));
  ok(ph_stm_read(stm, buf, 14, &amount), "read ok");
  ok(amount == 14, "len was %" PRIu64, amount);
  ok(!memcmp("testing 1 two!", buf, 14), "got formatted");

  ok(ph_stm_close(stm), "closed");

  return exit_status();
}
예제 #3
0
파일: echo.c 프로젝트: bigwhite/libphenom
// Called each time the session wakes up.
// The `why` parameter indicates why we were woken up
static void echo_processor(ph_sock_t *sock, ph_iomask_t why, void *arg)
{
  struct echo_state *state = arg;
  ph_buf_t *buf;

  // If the socket encountered an error, or if the timeout was reached
  // (there's a default timeout, even if we didn't override it), then
  // we tear down the session
  if (why & (PH_IOMASK_ERR|PH_IOMASK_TIME)) {
    ph_log(PH_LOG_ERR, "disconnecting `P{sockaddr:%p}", (void*)&sock->peername);
    ph_sock_shutdown(sock, PH_SOCK_SHUT_RDWR);
    ph_mem_free(mt_state, state);
    ph_sock_free(sock);
    return;
  }

  // We loop because echo_processor is only triggered by newly arriving
  // data or events from the kernel.  If we have data buffered and only
  // partially consume it, we won't get woken up until the next data
  // arrives, if ever.
  while (1) {
    // Try to read a line of text.
    // This returns a slice over the underlying buffer (if the line was
    // smaller than a buffer) or a freshly made contiguous buffer (if the
    // line was larger than our buffer segment size).  Either way, we
    // own a reference to the returned buffer and should treat it as
    // a read-only slice.
    buf = ph_sock_read_line(sock);
    if (!buf) {
      // Not available yet, we'll try again later
      return;
    }

    // We got a line; update our state
    state->num_lines++;

    // Send our response.  The data is buffered and automatically sent
    // to the client as it becomes writable, so we don't need to handle
    // partial writes or EAGAIN here.

    // If this was a "real" server, we would still check the return value
    // from the writes and proceed to tear down the session if things failed.

    // Note that buf includes the trailing CRLF, so our response
    // will implicitly end with CRLF too.
    ph_stm_printf(sock->stream, "You said [%d]: ", state->num_lines);
    ph_stm_write(sock->stream, ph_buf_mem(buf), ph_buf_len(buf), NULL);

    // We're done with buf, so we must release it
    ph_buf_delref(buf);
  }
}
예제 #4
0
파일: copy.c 프로젝트: 01BTC10/libphenom
bool ph_stm_copy(ph_stream_t *src, ph_stream_t *dest,
    uint64_t num_bytes, uint64_t *nreadp, uint64_t *nwrotep)
{
  uint64_t nread = 0, nwrote = 0;
  uint64_t remain = num_bytes;
  char lbuf[PH_STM_BUFSIZE];
  int err = 0;

  while (remain > 0 && err == 0) {
    uint64_t r, want = MIN(remain, sizeof(lbuf));

    if (!ph_stm_read(src, lbuf, want, &r)) {
      if (ph_stm_errno(src) == EINTR) {
        continue;
      }
      err = ph_stm_errno(src);
      break;
    }

    if (r == 0) {
      break;
    }

    nread += r;
    remain -= r;

    char *buf = lbuf;
    while (r > 0) {
      uint64_t w;
      if (!ph_stm_write(dest, buf, r, &w)) {
        if (ph_stm_errno(dest) == EINTR) {
          continue;
        }
        err = ph_stm_errno(dest);
        break;
      }

      nwrote += w;
      buf += w;
      r -= w;
    }
  }

  if (nreadp) {
    *nreadp = nread;
  }
  if (nwrotep) {
    *nwrotep = nwrote;
  }

  return err == 0;
}
예제 #5
0
static int bio_stm_write(BIO *h, const char *buf, int size)
{
  uint64_t nwrote;
  ph_stream_t *stm = h->ptr;

  if (buf == NULL || size == 0 || stm == NULL) {
    return 0;
  }

  BIO_clear_retry_flags(h);
  if (ph_stm_write(stm, buf, size, &nwrote)) {
    return (int)nwrote;
  }

  if (should_retry(stm)) {
    BIO_set_retry_write(h);
  }

  return -1;
}