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;
}
static int ebb_connection_push_header(ebb_connection *conn, const char *msg)
{
    ebb_connection_info *conninfo = (ebb_connection_info *)(conn->data);
    uint8_t *block;
    size_t msglen;

    msglen = strlen(msg);

    block = (uint8_t *)malloc(sizeof(size_t) + msglen);

LOG_DEBUG("pushhdr, block = %p", block);

    LOG_DEBUG("********* ebb_connection_push_header str=%p", block);
    if (block == NULL)
    {
        LOG_ERROR("strdup failed, silently closing conn");
        ebb_connection_schedule_close(conn);
        return 1;
    }
    else
    {
        memcpy(block, &msglen, sizeof(size_t));
        memcpy(block + sizeof(size_t), msg, msglen);

        LOG_DEBUG("Pushed hdr %s", msg);
        tailq_push_head(conninfo->rsp_q, block);
        conninfo->push_len += msglen;
        connection_flush_write(conn);
        return 0;
    }
}
static int ebb_connection_pushbin(ebb_connection *conn, const uint8_t *msg, size_t len, bool flush)
{
    ebb_connection_info *conninfo = (ebb_connection_info *)(conn->data);
    uint8_t *block;

    block = (uint8_t *)malloc(sizeof(size_t) + len);

    LOG_DEBUG("********* ebb_connection_pushbin str=%p", msg);
    if (block == NULL)
    {
        LOG_ERROR("strdup failed, silently closing conn");
        ebb_connection_schedule_close(conn);
        return 1;
    }
    else
    {
        memcpy(block, &len, sizeof(size_t));
        memcpy(block + sizeof(size_t), msg, len);

        //LOG_INFO("Pushed block %u (+%u) bytes", len, sizeof(size_t));
        //dump(block, len + sizeof(size_t));
        tailq_push_tail(conninfo->rsp_q, block);    // FIXME, error check
        conninfo->push_len += len;
        if (flush)
            connection_flush_write(conn);
        return 0;
    }
}
Exemple #4
0
void continue_responding(ebb_connection *connection) {
  AsyncConnection *connection_data = (AsyncConnection *)connection->data;
  if (connection_data->keep_alive_flag == false) {
    ebb_connection_schedule_close(connection);
  }
  else {
    // clear connection for next request
    connection_data->reset();
  }
}
Exemple #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;
  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);
}
Exemple #6
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);
}
Exemple #7
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);
}
Exemple #8
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);
}
static void connection_flush_write(ebb_connection *conn)
{
    ebb_connection_info *conninfo = (ebb_connection_info *)(conn->data);
    if (!conninfo->writing)
    {
        uint8_t *blockp;
        uint8_t *data;
        size_t len = 0;

        blockp = tailq_pop_head(conninfo->rsp_q);
/*
LOG_INFO("flush %p", blockp);
if (NULL != blockp)
dump(blockp, 16);
*/
        if (NULL != blockp)
        {
            len = *((size_t *)blockp);
            data = blockp + sizeof(size_t);

            conninfo->writing = true;
            LOG_DEBUG("conn_write");
            if (len > sizeof(conninfo->writebuf))
                LOG_CRITICAL("block too big %u of %u", len, sizeof(conninfo->writebuf));
            memcpy(conninfo->writebuf, data, len);
            conninfo->push_len -= len;
            free(blockp);
            if (len)
                ebb_connection_write(conn, conninfo->writebuf, len, on_write_complete);
        }
        else
        {   // reached end of q
            LOG_DEBUG("End of write q");
            if (conninfo->finished)
            {
                if (!conninfo->keepalive)
                    ebb_connection_schedule_close(conn);
            }
        }
    }
}
Exemple #10
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);
}
Exemple #11
0
void continue_responding(ebb_connection *connection) {
    delete(AsyncConnection *) connection->data;
    connection->data = nullptr;
    ebb_connection_schedule_close(connection);
}
Exemple #12
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);
}