Exemplo n.º 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);
  }
}
Exemplo n.º 2
0
int uei_508_read_bytes(int m_port, char *m_buf, size_t m_bytes)
{
    ph_buf_t *tmp_buf;

    if ((tmp_buf = ph_bufq_consume_bytes(SL508_read_buffer[m_port], m_bytes))) {
        memcpy(m_buf, ph_buf_mem(tmp_buf), m_bytes);
        ph_buf_delref(tmp_buf);
        return m_bytes;
    } else {
        return 0;
    }
}
Exemplo n.º 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);
  }
}
Exemplo n.º 4
0
int uei_508_read_record(int m_port, char *m_buf, size_t m_buflen, const char *m_delim, uint32_t m_delimlen)
{
    ph_buf_t *tmp_buf;

    if ((tmp_buf = ph_bufq_consume_record(SL508_read_buffer[m_port], m_delim, m_delimlen))) {
        size_t len = min((size_t)ph_buf_len(tmp_buf), m_buflen);
        if (len) memcpy(m_buf, ph_buf_mem(tmp_buf), len);
        ph_buf_delref(tmp_buf);
        return len;
    } else {
        return 0;
    }
}
Exemplo n.º 5
0
static void test_straddle_edges(void)
{
  const char *delim = "\r\n";
  int delim_len = strlen(delim);
  int default_buf_size = 8192;
  int i;
  char pad[8192];

  memset(pad, 'x', sizeof(pad));
#define PAD_IT(__n) { \
  uint64_t n = __n; \
  while (n > 0) { \
    ph_bufq_append(q, pad, MIN(n, sizeof(pad)), 0); \
    n -= MIN(n, sizeof(pad)); \
  } \
}

  // We want two buffers: [8192][8192]
  // And then to place our delimiter around the first boundary to verify
  // that the delimiter matching operates correctly
  // We define a cursor offset relative to the end of the first buffer
  // (0 means the last byte of the delimiter is in the last byte of the
  // first buffer, 1 means that the last delimiter byte is in the first
  // byte of the second buffer)

  for (i = - 2 * delim_len; i < 2 * delim_len; i++) {
    ph_bufq_t *q;

    q = ph_bufq_new(16*1024);

    // Fill up the start of the buffer
    uint64_t num_first = default_buf_size + i - delim_len;

    // first data
    PAD_IT(num_first);
    is(num_first, ph_bufq_len(q));
    // first delim
    ph_bufq_append(q, delim, delim_len, 0);

    // second data
    PAD_IT(16);
    // second delim
    ph_bufq_append(q, delim, delim_len, 0);

    ph_buf_t *first = ph_bufq_consume_record(q, delim, delim_len);
    is_int(num_first + 2, ph_buf_len(first));

    ph_buf_t *second = ph_bufq_consume_record(q, delim, delim_len);
    is_int(18, ph_buf_len(second));

    diag("for i = %d, num_first = %d.  first->len=%d second->len=%d",
        i, (int)num_first, (int)ph_buf_len(first), (int)ph_buf_len(second));

    ph_buf_delref(first);
    ph_buf_delref(second);

    ph_bufq_free(q);
  }

  // Now, test the case where we have a partial match at a boundary, but not
  // the true match until later

  ph_bufq_t *q;

  q = ph_bufq_new(24*1024);
  PAD_IT(8191);
  ph_bufq_append(q, "\r", 1, 0);
  PAD_IT(8192);
  ph_bufq_append(q, delim, delim_len, 0);

  ph_buf_t *first = ph_bufq_consume_record(q, delim, delim_len);
  is_int(16386, ph_buf_len(first));

  ph_buf_delref(first);
  ph_bufq_free(q);
}
Exemplo n.º 6
0
void *uei_508_loop(void *m_arg)
{
    struct timespec next;
    uint64_t periodns = ((double)(NSEC_PER_SEC) / 10);
    int ret;
    int channel_list_508[8] = {0, 1, 2, 3, 4, 5, 6, 7};
    uint32_t channel_cfg_508[8] = {
        CFG_485(DQ_SL501_BAUD_9600),
        CFG_485(DQ_SL501_BAUD_9600),
        CFG_485(DQ_SL501_BAUD_9600),
        CFG_485(DQ_SL501_BAUD_9600),
        CFG_485(DQ_SL501_BAUD_9600),
        CFG_485(DQ_SL501_BAUD_9600),
        CFG_485(DQ_SL501_BAUD_9600),
        CFG_485(DQ_SL501_BAUD_9600)
    };
    int channel_flags_508[8] = { 0 };

    ph_library_init();
    ph_thread_set_name("UEI508");
    blast_startup("Starting UEI 508 loop");

    // set channel configuration
    for (int i = 0; i < 8; i++) {
        if ((ret = DqAdv501SetChannelCfg(hd_508, 4, i, channel_cfg_508[i])) < 0) {
            blast_err("Error in DqAdv501SetChannelCfg()");
        }
    }
    ret = DqRtVmapAddChannel(hd_508, vmapid_508, 4, DQ_SS0IN, channel_list_508, channel_flags_508, 8);
    ret = DqRtVmapAddChannel(hd_508, vmapid_508, 4, DQ_SS0OUT, channel_list_508, channel_flags_508, 8);
    ret = DqRtVmapStart(hd_508, vmapid_508);

    clock_gettime(CLOCK_MONOTONIC, &next);

    while (!shutdown_mcp) {
        for (int i = 0; i < 8; i++) {
            size_t num_bytes;
            ph_buf_t *outbuf = NULL;
            if ((num_bytes = ph_bufq_len(SL508_write_buffer[i]))) {
                outbuf = ph_bufq_consume_bytes(SL508_write_buffer[i], num_bytes);
                DqRtVmapWriteOutput(hd_508, vmapid_508, 4, i, num_bytes, ph_buf_mem(outbuf));
                ph_buf_delref(outbuf);
            }
            DqRtVmapRequestInput(hd_508, vmapid_508, 4, i, 128);
        }
        // Write output data to each TX port FIFO and Read each RX port FIFO
        ret = DqRtVmapRefresh(hd_508, vmapid_508, 0);

        // Read data received during the last refresh
        for (int i = 0; i < 8; i++) {
            uint8_t read_buffer[128];
            int read_len;
            DqRtVmapReadInput(hd_508, vmapid_508, 4, i, sizeof(read_buffer), &read_len, read_buffer);
            if (read_len > 0) {
                ph_bufq_append(SL508_read_buffer[i], read_buffer, read_len, NULL);
            }
        }

        timespec_add_ns(&next, periodns);
        clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, NULL);
    }

    DqRtVmapStop(hd_508, vmapid_508);
    DqRtVmapClose(hd_508, vmapid_508);
    return NULL;
}