示例#1
0
void
PortLineSplitter::DataReceived(const void *_data, size_t length)
{
  assert(_data != NULL);
  assert(length > 0);

  const char *data = (const char *)_data, *end = data + length;

  do {
    /* append new data to buffer, as much as fits there */
    auto range = buffer.Write();
    if (range.IsEmpty()) {
      /* overflow: reset buffer to recover quickly */
      buffer.Clear();
      continue;
    }

    size_t nbytes = std::min(size_t(range.size), size_t(end - data));
    memcpy(range.data, data, nbytes);
    data += nbytes;
    buffer.Append(nbytes);

    while (true) {
      /* read data from the buffer, to see if there's a newline
         character */
      range = buffer.Read();
      if (range.IsEmpty())
        break;

      char *newline = (char *)memchr(range.data, '\n', range.size);
      if (newline == NULL)
        /* no newline here: wait for more data */
        break;

      /* remove trailing whitespace, such as '\r' */
      char *end = newline;
      while (end > range.data && IsWhitespaceOrNull(end[-1]))
        --end;

      *end = '\0';

      SanitiseLine(range.data, end);

      const char *line = range.data;

      /* if there are NUL bytes in the line, skip to after the last
         one, to avoid conflicts with NUL terminated C strings due to
         binary garbage */
      const void *nul;
      while ((nul = memchr(line, 0, end - line)) != NULL)
        line = (const char *)nul + 1;

      LineReceived(line);

      buffer.Consume(newline - range.data + 1);
    }
  } while (data < end);
}
示例#2
0
void EventLoop(int fd, void *handle)
{
  intf_thread_t *intf = (intf_thread_t*)handle;
  intf_sys_t *sys = intf->p_sys;

  sys->line = (char *)malloc(MAX_LINE * sizeof(char));

  while(1) {
    struct pollfd ufd = { .fd = fd, .events = POLLIN | POLLOUT, };
    
    if(poll(&ufd, 1, 1000) <= 0) /* block for 1s so we don't spin */
      continue;
    
    if(ufd.revents & POLLIN) {
      int rv = HandleRead(handle);
      if(rv != 0) {
	msg_Err(intf, "Read error: %s", strerror(rv));
	break;
      }
    } else if(ufd.revents & POLLOUT) {
      int rv = HandleWrite(handle);
      if(rv != 0) {
	msg_Err(intf, "Write error: %s", strerror(rv));
	break;
      }
    }
  }

  free(sys->line);
}

int HandleRead(void *handle) {
  intf_thread_t *intf = (intf_thread_t*)handle;
  intf_sys_t *sys = intf->p_sys;

  static char ch, pch;

  int rv = recv(sys->fd, &ch, 1, 0);
  if(rv == -1)
    return errno;
  else if(rv == 0)
    return -2;
  
  if(pch == '\r' && ch == '\n') { /* were the last two characters \r\n? */
    sys->line[sys->line_loc-1] = '\0'; /* overwrite CR with a nullbyte */
    LineReceived(handle, sys->line);
    sys->line_loc = 0;
    sys->line = (char *)malloc(MAX_LINE * sizeof(char)); /* allocate a new line, lineReceived will free the old one */
  } else {
    sys->line[sys->line_loc] = ch;
    pch = ch;
    sys->line_loc++;
  }

  return 0;
}