95 lines
2.2 KiB
C
95 lines
2.2 KiB
C
#define XS_IMPLEMENTATION
|
|
|
|
#include "../xs.h"
|
|
#include "../xs_io.h"
|
|
#include "../xs_socket.h"
|
|
#include "../xs_url.h"
|
|
#include "../xs_httpd.h"
|
|
|
|
#include <sys/socket.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
static int normal_client(void)
|
|
{
|
|
int sockets[2];
|
|
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1)
|
|
return 10;
|
|
|
|
pid_t child = fork();
|
|
if (child == -1)
|
|
return 11;
|
|
|
|
if (child == 0) {
|
|
char buffer[8192];
|
|
ssize_t bytes;
|
|
size_t total = 0;
|
|
|
|
close(sockets[0]);
|
|
while ((bytes = read(sockets[1], buffer, sizeof(buffer))) > 0)
|
|
total += bytes;
|
|
|
|
close(sockets[1]);
|
|
_exit(total > 1024 * 1024 ? 0 : 12);
|
|
}
|
|
|
|
close(sockets[1]);
|
|
FILE *response = fdopen(sockets[0], "w");
|
|
if (response == NULL)
|
|
return 13;
|
|
|
|
xs *headers = xs_dict_new();
|
|
headers = xs_dict_append(headers, "content-type", "application/octet-stream");
|
|
int body_size = 1024 * 1024;
|
|
xs *body = xs_realloc(NULL, body_size);
|
|
memset(body, 'n', body_size);
|
|
|
|
int result = xs_httpd_response(response, 200, "OK", headers, body, body_size);
|
|
fclose(response);
|
|
|
|
int status;
|
|
if (waitpid(child, &status, 0) == -1)
|
|
return 14;
|
|
|
|
return result == 0 && WIFEXITED(status) && WEXITSTATUS(status) == 0 ? 0 : 15;
|
|
}
|
|
|
|
static int slow_client(void)
|
|
{
|
|
int sockets[2];
|
|
int send_buffer = 4096;
|
|
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1)
|
|
return 2;
|
|
|
|
if (setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF,
|
|
&send_buffer, sizeof(send_buffer)) == -1)
|
|
return 3;
|
|
|
|
FILE *response = fdopen(sockets[0], "w");
|
|
if (response == NULL)
|
|
return 4;
|
|
|
|
xs *headers = xs_dict_new();
|
|
headers = xs_dict_append(headers, "content-type", "application/octet-stream");
|
|
|
|
int body_size = 8 * 1024 * 1024;
|
|
xs *body = xs_realloc(NULL, body_size);
|
|
memset(body, 'x', body_size);
|
|
|
|
int result = xs_httpd_response(response, 200, "OK", headers, body, body_size);
|
|
|
|
fclose(response);
|
|
close(sockets[1]);
|
|
|
|
return result == -1 ? 0 : 1;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
int result = normal_client();
|
|
|
|
return result == 0 ? slow_client() : result;
|
|
}
|