parent
cb26514ad3
commit
faacc5c785
@ -1,7 +1,80 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
void client_socket_close(int client_socket, struct sockaddr *client_address);
|
#include "debuglog.h"
|
||||||
|
#include "http.h"
|
||||||
|
#include "http_total.h"
|
||||||
|
#include "panic.h"
|
||||||
|
#include "likely.h"
|
||||||
|
|
||||||
int client_socket_send(int client_socket, int status_code);
|
|
||||||
|
static inline void
|
||||||
|
client_socket_close(int client_socket, struct sockaddr *client_address)
|
||||||
|
{
|
||||||
|
/* Should never close 0, 1, or 2 */
|
||||||
|
assert(client_socket != STDIN_FILENO);
|
||||||
|
assert(client_socket != STDOUT_FILENO);
|
||||||
|
assert(client_socket != STDERR_FILENO);
|
||||||
|
|
||||||
|
if (unlikely(close(client_socket) < 0)) {
|
||||||
|
char client_address_text[INET6_ADDRSTRLEN] = {};
|
||||||
|
if (unlikely(inet_ntop(AF_INET, &client_address, client_address_text, INET6_ADDRSTRLEN) == NULL)) {
|
||||||
|
debuglog("Failed to log client_address: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
debuglog("Error closing client socket %d associated with %s - %s", client_socket, client_address_text,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rejects request due to admission control or error
|
||||||
|
* @param client_socket - the client we are rejecting
|
||||||
|
* @param status_code - either 503 or 400
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
client_socket_send(int client_socket, int status_code)
|
||||||
|
{
|
||||||
|
const char *response;
|
||||||
|
int rc;
|
||||||
|
switch (status_code) {
|
||||||
|
case 503:
|
||||||
|
response = HTTP_RESPONSE_503_SERVICE_UNAVAILABLE;
|
||||||
|
http_total_increment_5XX();
|
||||||
|
break;
|
||||||
|
case 400:
|
||||||
|
response = HTTP_RESPONSE_400_BAD_REQUEST;
|
||||||
|
http_total_increment_4XX();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
panic("%d is not a valid status code\n", status_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sent = 0;
|
||||||
|
int to_send = strlen(response);
|
||||||
|
|
||||||
|
while (sent < to_send) {
|
||||||
|
rc = write(client_socket, &response[sent], to_send - sent);
|
||||||
|
if (rc < 0) {
|
||||||
|
if (errno == EAGAIN) { debuglog("Unexpectedly blocking on write of %s\n", response); }
|
||||||
|
|
||||||
|
debuglog("Error with %s\n", strerror(errno));
|
||||||
|
|
||||||
|
goto send_err;
|
||||||
|
}
|
||||||
|
sent += rc;
|
||||||
|
};
|
||||||
|
|
||||||
|
rc = 0;
|
||||||
|
done:
|
||||||
|
return rc;
|
||||||
|
send_err:
|
||||||
|
debuglog("Error sending to client: %s", strerror(errno));
|
||||||
|
rc = -1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <http_parser.h>
|
|
||||||
#include <sys/uio.h>
|
|
||||||
|
|
||||||
#include "http.h"
|
|
||||||
|
|
||||||
#define HTTP_RESPONSE_200_OK "HTTP/1.1 200 OK\r\n"
|
|
||||||
#define HTTP_RESPONSE_503_SERVICE_UNAVAILABLE "HTTP/1.1 503 Service Unavailable\r\n\r\n"
|
|
||||||
#define HTTP_RESPONSE_400_BAD_REQUEST "HTTP/1.1 400 Bad Request\r\n\r\n"
|
|
||||||
#define HTTP_RESPONSE_CONTENT_LENGTH "Content-Length: "
|
|
||||||
#define HTTP_RESPONSE_CONTENT_LENGTH_TERMINATOR "\r\n\r\n" /* content body follows this */
|
|
||||||
#define HTTP_RESPONSE_CONTENT_TYPE "Content-Type: "
|
|
||||||
#define HTTP_RESPONSE_CONTENT_TYPE_PLAIN "text/plain"
|
|
||||||
#define HTTP_RESPONSE_CONTENT_TYPE_TERMINATOR " \r\n"
|
|
||||||
|
|
||||||
struct http_response_header {
|
|
||||||
char *header;
|
|
||||||
int length;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct http_response {
|
|
||||||
struct http_response_header headers[HTTP_MAX_HEADER_COUNT];
|
|
||||||
int header_count;
|
|
||||||
char * body;
|
|
||||||
int body_length;
|
|
||||||
char * status;
|
|
||||||
int status_length;
|
|
||||||
struct iovec bufs[HTTP_MAX_HEADER_COUNT * 2 + 3];
|
|
||||||
};
|
|
||||||
|
|
||||||
/***************************************************
|
|
||||||
* General HTTP Response Functions *
|
|
||||||
**************************************************/
|
|
||||||
int http_response_encode_as_vector(struct http_response *http_response);
|
|
||||||
int http_response_set_body(struct http_response *http_response, char *body, int length);
|
|
||||||
int http_response_set_header(struct http_response *http_response, char *h, int length);
|
|
||||||
int http_response_set_status(struct http_response *http_response, char *status, int length);
|
|
@ -1,78 +0,0 @@
|
|||||||
#include <arpa/inet.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "client_socket.h"
|
|
||||||
#include "debuglog.h"
|
|
||||||
#include "http_response.h"
|
|
||||||
#include "http_total.h"
|
|
||||||
#include "likely.h"
|
|
||||||
#include "panic.h"
|
|
||||||
|
|
||||||
void
|
|
||||||
client_socket_close(int client_socket, struct sockaddr *client_address)
|
|
||||||
{
|
|
||||||
/* Should never close 0, 1, or 2 */
|
|
||||||
assert(client_socket != STDIN_FILENO);
|
|
||||||
assert(client_socket != STDOUT_FILENO);
|
|
||||||
assert(client_socket != STDERR_FILENO);
|
|
||||||
|
|
||||||
if (unlikely(close(client_socket) < 0)) {
|
|
||||||
char client_address_text[INET6_ADDRSTRLEN] = {};
|
|
||||||
if (unlikely(inet_ntop(AF_INET, &client_address, client_address_text, INET6_ADDRSTRLEN) == NULL)) {
|
|
||||||
debuglog("Failed to log client_address: %s", strerror(errno));
|
|
||||||
}
|
|
||||||
debuglog("Error closing client socket %d associated with %s - %s", client_socket, client_address_text,
|
|
||||||
strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rejects request due to admission control or error
|
|
||||||
* @param client_socket - the client we are rejecting
|
|
||||||
* @param status_code - either 503 or 400
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
client_socket_send(int client_socket, int status_code)
|
|
||||||
{
|
|
||||||
const char *response;
|
|
||||||
int rc;
|
|
||||||
switch (status_code) {
|
|
||||||
case 503:
|
|
||||||
response = HTTP_RESPONSE_503_SERVICE_UNAVAILABLE;
|
|
||||||
http_total_increment_5XX();
|
|
||||||
break;
|
|
||||||
case 400:
|
|
||||||
response = HTTP_RESPONSE_400_BAD_REQUEST;
|
|
||||||
http_total_increment_4XX();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
panic("%d is not a valid status code\n", status_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
int sent = 0;
|
|
||||||
int to_send = strlen(response);
|
|
||||||
|
|
||||||
while (sent < to_send) {
|
|
||||||
rc = write(client_socket, &response[sent], to_send - sent);
|
|
||||||
if (rc < 0) {
|
|
||||||
if (errno == EAGAIN) { debuglog("Unexpectedly blocking on write of %s\n", response); }
|
|
||||||
|
|
||||||
debuglog("Error with %s\n", strerror(errno));
|
|
||||||
|
|
||||||
goto send_err;
|
|
||||||
}
|
|
||||||
sent += rc;
|
|
||||||
};
|
|
||||||
|
|
||||||
rc = 0;
|
|
||||||
done:
|
|
||||||
return rc;
|
|
||||||
send_err:
|
|
||||||
debuglog("Error sending to client: %s", strerror(errno));
|
|
||||||
rc = -1;
|
|
||||||
goto done;
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "http_response.h"
|
|
||||||
|
|
||||||
/***************************************************
|
|
||||||
* General HTTP Response Functions *
|
|
||||||
**************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encodes a sandbox's HTTP Response as an array of buffers
|
|
||||||
* @param sandbox the sandbox containing the HTTP response we want to encode as buffers
|
|
||||||
* @returns the number of buffers used to store the HTTP Response
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
http_response_encode_as_vector(struct http_response *http_response)
|
|
||||||
{
|
|
||||||
int buffer_count = 0;
|
|
||||||
|
|
||||||
http_response->bufs[buffer_count].iov_base = http_response->status;
|
|
||||||
http_response->bufs[buffer_count].iov_len = http_response->status_length;
|
|
||||||
buffer_count++;
|
|
||||||
|
|
||||||
for (int i = 0; i < http_response->header_count; i++) {
|
|
||||||
http_response->bufs[buffer_count].iov_base = http_response->headers[i].header;
|
|
||||||
http_response->bufs[buffer_count].iov_len = http_response->headers[i].length;
|
|
||||||
buffer_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (http_response->body) {
|
|
||||||
http_response->bufs[buffer_count].iov_base = http_response->body;
|
|
||||||
http_response->bufs[buffer_count].iov_len = http_response->body_length;
|
|
||||||
buffer_count++;
|
|
||||||
|
|
||||||
http_response->bufs[buffer_count].iov_base = http_response->status + http_response->status_length - 2;
|
|
||||||
http_response->bufs[buffer_count].iov_len = 2;
|
|
||||||
buffer_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set an HTTP Response Body on a Sandbox
|
|
||||||
* @param sandbox the sandbox we want to set the request header on
|
|
||||||
* @param body string of the body that we want to set
|
|
||||||
* @param length the length of the header string
|
|
||||||
* @returns 0 (abends program in case of error)
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
http_response_set_body(struct http_response *http_response, char *body, int length)
|
|
||||||
{
|
|
||||||
// assert(length <= sandbox->module->max_response_size);
|
|
||||||
http_response->body = body;
|
|
||||||
http_response->body_length = length;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a header to the HTTP Response of a Sandbox
|
|
||||||
* @param sandbox the sandbox we want to set the request header on
|
|
||||||
* @param header string containing the header that we want to append
|
|
||||||
* @param length the length of the header string
|
|
||||||
* @returns 0 (abends program in case of error)
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
http_response_set_header(struct http_response *http_response, char *header, int length)
|
|
||||||
{
|
|
||||||
assert(http_response->header_count < HTTP_MAX_HEADER_COUNT);
|
|
||||||
http_response->header_count++;
|
|
||||||
http_response->headers[http_response->header_count - 1].header = header;
|
|
||||||
http_response->headers[http_response->header_count - 1].length = length;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set an HTTP Response Status on a Sandbox
|
|
||||||
* @param sandbox the sandbox we want to set the request status on
|
|
||||||
* @param status string of the status we want to set
|
|
||||||
* @param length the length of the status
|
|
||||||
* @returns 0 (abends program in case of error)
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
http_response_set_status(struct http_response *http_response, char *status, int length)
|
|
||||||
{
|
|
||||||
http_response->status = status;
|
|
||||||
http_response->status_length = length;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Reference in new issue