Beispiel #1
0
static void read_remote(ph_sock_t *sock, ph_iomask_t why, void *data)
{
  ph_buf_t *buf;

  ph_unused_parameter(data);

  if (why & (PH_IOMASK_TIME|PH_IOMASK_ERR)) {
    ph_log(PH_LOG_ERR, "disconnecting `P{sockaddr:%p}",
        (void*)&sock->peername);
    ph_sock_shutdown(sock, PH_SOCK_SHUT_RDWR);
    ph_sock_free(sock);
    remote_sock = NULL;
    ph_sched_stop();
    return;
  }

  while (1) {
    buf = ph_sock_read_line(sock);
    if (!buf) {
      // Not available yet, we'll try again later
      return;
    }

    ph_ignore_result(write(STDOUT_FILENO, ph_buf_mem(buf), ph_buf_len(buf)));
    ph_buf_delref(buf);
  }
}
Beispiel #2
0
static void debug_con_processor(ph_sock_t *sock, ph_iomask_t why, void *arg)
{
  if (why & (PH_IOMASK_ERR|PH_IOMASK_TIME)) {
done:
    ph_sock_shutdown(sock, PH_SOCK_SHUT_RDWR);
    ph_sock_free(sock);
    return;
  }
  if (arg && (why & PH_IOMASK_WRITE) && ph_bufq_len(sock->wbuf) == 0) {
    goto done;
  }

  if (arg == NULL && (why & PH_IOMASK_READ)) {
    ph_buf_t *buf;
    char *cmd;
    int len;
    uint32_t i;

    buf = ph_sock_read_line(sock);
    if (!buf) {
      return;
    }

    sock->job.data = buf;
    ph_sock_shutdown(sock, PH_SOCK_SHUT_RD);

    cmd = (char*)ph_buf_mem(buf);
    len = ph_buf_len(buf);
    /* replace CRLF with NUL termination */
    cmd[len - 2] = '\0';

    for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) {
      if (strcmp(funcs[i].name, cmd)) {
        continue;
      }

      funcs[i].func(sock);
      break;
    }
  }
}
Beispiel #3
0
// 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);
  }
}