void write_cb(struct ev_loop *loop, struct ev_async *w, int revents) { AsyncConnection *conn = (AsyncConnection *) w->data; char *method = (char *) ""; switch (conn->request->method) { case EBB_GET: method = (char *)"GET"; break; case EBB_POST: method = (char *)"POST"; break; default: break; } struct timeval endtime; gettimeofday(&endtime, nullptr); float duration = endtime.tv_sec + endtime.tv_usec / 1000000.0 - conn->starttime.tv_sec - conn->starttime.tv_usec / 1000000.0; time_t rawtime; struct tm *timeinfo; char timestr[80]; time(&rawtime); timeinfo = localtime(&rawtime); strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S %z", timeinfo); if (conn->connection != nullptr) { conn->write_buffer = (char *)malloc(max_header_length + conn->response_length); conn->write_buffer_len = 0; // Copy the http status code conn->code = conn->code == 0 ? 200 : conn->code; conn->contentType = conn->contentType.size() == 0 ? "application/json" : conn->contentType; conn->write_buffer_len += snprintf((char *)conn->write_buffer, max_header_length, "HTTP/1.1 %lu OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\nConnection: close\r\n\r\n", conn->code, conn->contentType.c_str(), conn->response_length); // Append the response memcpy(conn->write_buffer + conn->write_buffer_len, conn->response, conn->response_length); conn->write_buffer_len += conn->response_length; ebb_connection_write(conn->connection, conn->write_buffer, conn->write_buffer_len, continue_responding); // We need to wait for `continue_responding` to fire to be sure the client has been sent all the data printf("%s [%s] %s %s (%f s)\n", inet_ntoa(conn->addr.sin_addr), timestr, method, conn->path, duration); } else { printf("%s [%s] %s %s (%f s) not sent\n", inet_ntoa(conn->addr.sin_addr), timestr, method, conn->path, duration); } ev_async_stop(conn->ev_loop, &conn->ev_write); // When connection is nullptr, `continue_responding` won't fire since we never sent data to the client, // thus, we'll need to clean up manually here, while connection has already been cleaned up in on `on_response` if (conn->connection == nullptr) delete conn; }
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); } } } }
void write_cb(struct ev_loop *loop, struct ev_async *w, int revents) { AsyncConnection *conn = (AsyncConnection *) w->data; char *method = (char *) ""; switch (conn->request->method) { case EBB_GET: method = (char *)"GET"; break; case EBB_POST: method = (char *)"POST"; break; default: break; } struct timeval endtime; gettimeofday(&endtime, nullptr); float duration = endtime.tv_sec + endtime.tv_usec / 1000000.0 - conn->starttime.tv_sec - conn->starttime.tv_usec / 1000000.0; time_t rawtime; struct tm *timeinfo; char timestr[80]; time(&rawtime); timeinfo = localtime(&rawtime); strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S %z", timeinfo); // Handle the actual writing if (conn->connection != nullptr) { ebb_connection_write(conn->connection, conn->write_buffer, conn->write_buffer_len, continue_responding); printf("%s [%s] %s %s (%f s)\n", inet_ntoa(conn->addr.sin_addr), timestr, method, conn->path, duration); } else { printf("%s [%s] %s %s (%f s) not sent\n", inet_ntoa(conn->addr.sin_addr), timestr, method, conn->path, duration); } ev_async_stop(conn->ev_loop, &conn->ev_write); conn->waiting_for_response = false; // When connection is nullptr, `continue_responding` won't fire since we never sent data to the client, // thus, we'll need to clean up manually here, while connection has already been cleaned up in on `on_close` if (conn->connection == nullptr) delete conn; }