Пример #1
0
static ebb_request *ebb_request_create(ebb_connection *conn)
{
    ebb_request *request;
    ebb_request_info *request_info;

    if (NULL == (request = calloc(1, sizeof(ebb_request))))
        goto fail;

    if (NULL == (request_info = calloc(1, sizeof(ebb_request_info))))
        goto fail;

    ebb_request_init(request);
    request->data = (void *)request_info;
    request->on_complete = on_request_complete;
    request->on_uri = on_uri_complete;
    request->on_body = on_body_complete;
    request->on_path = on_path_complete;
    request->on_header_field = on_header_field;
    request->on_header_value = on_header_value;

    request_info->conn = conn;

    ebb_connection_reset_timeout(conn);

    return request;
fail:
    ebb_request_destroy(request);
    ebb_connection_schedule_close(conn);
    return NULL;
}
Пример #2
0
/* Internal callback 
 * called by connection->read_watcher
 */
static void 
on_readable(struct ev_loop *loop, ev_io *watcher, int revents)
{
  ebb_connection *connection = watcher->data;
  char recv_buffer[4096];
  ssize_t recved;

  //printf("on_readable\n");
  // TODO -- why is this broken?
  //assert(ev_is_active(&connection->timeout_watcher));
  assert(watcher == &connection->read_watcher);

  if(EV_ERROR & revents) {
    error("on_readable() got error event, closing connection.");
    goto error;
  }

#ifdef HAVE_GNUTLS
  assert(!ev_is_active(&connection->handshake_watcher));

  if(connection->server->secure) {
    recved = gnutls_record_recv( connection->session
                               , recv_buffer
                               , TCP_MAXWIN
                               );
    if(recved <= 0) {
      if(gnutls_error_is_fatal(recved)) goto error;
      if( (recved == GNUTLS_E_INTERRUPTED || recved == GNUTLS_E_AGAIN)
       && GNUTLS_NEED_WRITE
        ) ev_io_start(loop, &connection->write_watcher);
      return; 
    } 
  } else {
#endif /* HAVE_GNUTLS */

    recved = recv(connection->fd, recv_buffer, 4096, 0);
    if(recved <= 0) goto error;

#ifdef HAVE_GNUTLS
  }
#endif /* HAVE_GNUTLS */

  ebb_connection_reset_timeout(connection);

  ebb_request_parser_execute(&connection->parser, recv_buffer, recved);

  /* parse error? just drop the client. screw the 400 response */
  if(ebb_request_parser_has_error(&connection->parser)) goto error;
  return;
error:
  ebb_connection_schedule_close(connection);
}
Пример #3
0
/* Internal callback 
 * called by connection->read_watcher
 */
static void 
on_readable(EV_P_ ev_io *watcher, int revents)
{
  ebb_connection *connection = watcher->data;
  char base[TCP_MAXWIN];
  char *recv_buffer = base;
  size_t recv_buffer_size = TCP_MAXWIN;
  ssize_t recved;

  //printf("on_readable\n");

  // TODO -- why is this broken?
  //assert(ev_is_active(&connection->timeout_watcher));
  assert(watcher == &connection->read_watcher);

  if(EV_ERROR & revents) {
    error("on_readable() got error event, closing connection.");
    goto error;
  }

  ebb_buf *buf = NULL;
  if(connection->new_buf) {
    buf = connection->new_buf(connection);
    if(buf == NULL) return; 
    recv_buffer = buf->base;
    recv_buffer_size = buf->len;
  }


  recved = recv(connection->fd, recv_buffer, recv_buffer_size, 0);
  if(recved < 0) goto error;
  if(recved == 0) return;


  ebb_connection_reset_timeout(connection);

  ebb_request_parser_execute(&connection->parser, recv_buffer, recved);

  /* parse error? just drop the client. screw the 400 response */
  if(ebb_request_parser_has_error(&connection->parser)) goto error;

  if(buf && buf->on_release)
    buf->on_release(buf);

  return;
error:
  ebb_connection_schedule_close(connection);
}
Пример #4
0
/* Internal callback 
 * called by connection->write_watcher
 */
static void 
on_writable(struct ev_loop *loop, ev_io *watcher, int revents)
{
  ebb_connection *connection = watcher->data;
  ssize_t sent;
  
  //printf("on_writable\n");

  assert(CONNECTION_HAS_SOMETHING_TO_WRITE);
  assert(connection->written <= connection->to_write_len);
  // TODO -- why is this broken?
  //assert(ev_is_active(&connection->timeout_watcher));
  assert(watcher == &connection->write_watcher);

  if(connection->to_write == 0)
    goto stop_writing;

    sent = nosigpipe_push( (void*)(long)connection->fd
                         , connection->to_write + connection->written
                         , connection->to_write_len - connection->written
                         );
    if(sent < 0) goto error;
    if(sent == 0) return;

  ebb_connection_reset_timeout(connection);

  connection->written += sent;

  if(connection->written == connection->to_write_len) {
    goto stop_writing;
  }
  return;
stop_writing:
  ev_io_stop(loop, watcher);
  connection->to_write = NULL;

  if(connection->after_write_cb)
    connection->after_write_cb(connection);
  return;
error:
  error("close connection on write.");
  ebb_connection_schedule_close(connection);
}
Пример #5
0
/* Internal callback 
 * called by connection->read_watcher
 */
static void 
on_readable(struct ev_loop *loop, ev_io *watcher, int revents)
{
  ebb_connection *connection = watcher->data;
  size_t offset = connection->buffered_data;
  int left = EBB_READ_BUFFER - offset;
  char* recv_buffer = connection->read_buffer + offset;
  ssize_t recved;

  //printf("on_readable\n");
  // TODO -- why is this broken?
  //assert(ev_is_active(&connection->timeout_watcher));
  assert(watcher == &connection->read_watcher);

  // No more buffer space.
  if(left == 0) goto error;

  if(EV_ERROR & revents) {
    error("on_readable() got error event, closing connection.");
    goto error;
  }

  recved = recv(connection->fd, recv_buffer, left, 0);
  if(recved <= 0) goto error;
  connection->buffered_data += recved;

  ebb_connection_reset_timeout(connection);

  ebb_request_parser_execute(&connection->parser, connection->read_buffer,
                                recved, offset);

  if(ebb_request_parser_is_finished(&connection->parser)) {
    connection->buffered_data = 0;
  }

  /* parse error? just drop the client. screw the 400 response */
  if(ebb_request_parser_has_error(&connection->parser)) goto error;
  return;
error:
  ebb_connection_schedule_close(connection);
}
Пример #6
0
/* Internal callback 
 * called by connection->timeout_watcher
 */
static void 
on_timeout(EV_P_ ev_timer *watcher, int revents)
{
  ebb_connection *connection = watcher->data;

  assert(watcher == &connection->timeout_watcher);

  //printf("on_timeout\n");

  /* if on_timeout returns true, we don't time out */
  if(connection->on_timeout) {
    int r = connection->on_timeout(connection);

    if(r == EBB_AGAIN) {
      ebb_connection_reset_timeout(connection);
      return;
    }
  }

  ebb_connection_schedule_close(connection);
}
Пример #7
0
static void 
on_handshake(struct ev_loop *loop ,ev_io *watcher, int revents)
{
  ebb_connection *connection = watcher->data;

  //printf("on_handshake\n");

  assert(ev_is_active(&connection->timeout_watcher));
  assert(!ev_is_active(&connection->read_watcher));
  assert(!ev_is_active(&connection->write_watcher));

  if(EV_ERROR & revents) {
    error("on_handshake() got error event, closing connection.n");
    goto error;
  }

  int r = gnutls_handshake(connection->session);
  if(r < 0) {
    if(gnutls_error_is_fatal(r)) goto error;
    if(r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN)
      ev_io_set( watcher
               , connection->fd
               , (GNUTLS_NEED_WRITE ? EV_WRITE : EV_READ)
               );
    return;
  }

  ebb_connection_reset_timeout(connection);
  ev_io_stop(loop, watcher);

  ev_io_start(loop, &connection->read_watcher);
  if(CONNECTION_HAS_SOMETHING_TO_WRITE)
    ev_io_start(loop, &connection->write_watcher);

  return;
error:
  close_connection(connection);
}
Пример #8
0
/* Internal callback 
 * called by connection->write_watcher
 */
static void 
on_writable(struct ev_loop *loop, ev_io *watcher, int revents)
{
  ebb_connection *connection = watcher->data;
  ssize_t sent;
  
  //printf("on_writable\n");

  assert(CONNECTION_HAS_SOMETHING_TO_WRITE);
  assert(connection->written <= connection->to_write_len);
  // TODO -- why is this broken?
  //assert(ev_is_active(&connection->timeout_watcher));
  assert(watcher == &connection->write_watcher);

  if(connection->to_write == 0)
    goto stop_writing;

#ifdef HAVE_GNUTLS
  assert(!ev_is_active(&connection->handshake_watcher));

  if(connection->server->secure) {
    sent = gnutls_record_send( connection->session
                             , connection->to_write + connection->written
                             , connection->to_write_len - connection->written
                             ); 
    if(sent < 0) {
      if(gnutls_error_is_fatal(sent)) goto error;
      if( (sent == GNUTLS_E_INTERRUPTED || sent == GNUTLS_E_AGAIN)
       && GNUTLS_NEED_READ
        ) ev_io_stop(loop, watcher);
      return; 
    }
  } else {
#endif /* HAVE_GNUTLS */

    sent = nosigpipe_push( (void*)connection->fd
                         , connection->to_write + connection->written
                         , connection->to_write_len - connection->written
                         );
    if(sent < 0) goto error;
    if(sent == 0) return;

#ifdef HAVE_GNUTLS
  }
#endif /* HAVE_GNUTLS */

  ebb_connection_reset_timeout(connection);

  connection->written += sent;

  if(connection->written == connection->to_write_len) {
    goto stop_writing;
  }
  return;
stop_writing:
  ev_io_stop(loop, watcher);
  connection->to_write = NULL;

  if(connection->after_write_cb)
    connection->after_write_cb(connection);
  return;
error:
  error("close connection on write.");
  ebb_connection_schedule_close(connection);
}