Created
February 4, 2024 01:18
-
-
Save AdriDevelopsThings/efbf890256f6e7f51f07c53bfd39ee29 to your computer and use it in GitHub Desktop.
A http server written in c that responds to any request with a infinitely large file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <asm-generic/errno-base.h> | |
#include <asm-generic/errno.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <unistd.h> | |
#include <stdlib.h> | |
#include <errno.h> | |
#define RANDOM_BYTE_CHUNK_SIZE 256 | |
// get random bytes and return a pointer to the random bytes of the length RANDOM_BYTE_CHUNK_SIZE | |
char* get_random_bytes() { | |
// allocate space for random bytes | |
char* random_bytes = malloc(RANDOM_BYTE_CHUNK_SIZE * sizeof(char)); | |
if (random_bytes == NULL) { | |
perror("error while allocating space"); | |
return NULL; | |
} | |
// open /dev/urandom as a file | |
FILE *file = fopen("/dev/urandom", "r"); | |
// read RANDOM_BYTE_CHUNK_SIZE bytes into random_bytes | |
fgets(random_bytes, RANDOM_BYTE_CHUNK_SIZE, file); | |
fclose(file); | |
return random_bytes; | |
} | |
int main(int argc, char *argv[]) { | |
if (argc == 2 && strcmp(argv[1], "--help") == 0) { | |
printf("Usage: unlimited-download [port] [listen address]"); | |
return 0; | |
} | |
// parse port | |
char *s_port = "8000"; | |
if (argc > 1) { | |
s_port = argv[1]; | |
} | |
int port = atoi(s_port); | |
// parse server address | |
char* server_address = "127.0.0.1"; | |
if (argc == 3) { | |
server_address = argv[2]; | |
} | |
// create socket | |
int server_fd = socket(AF_INET, SOCK_STREAM, 0); | |
if (server_fd < 0) { | |
perror("error while creating socket"); | |
return -1; | |
} | |
// set reuseaddr as socket option | |
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0) { | |
perror("error while setting socket option"); | |
return -1; | |
} | |
// build socket address | |
struct sockaddr_in address; | |
address.sin_family = AF_INET; | |
address.sin_port = htons(port); | |
if (inet_aton(server_address, &address.sin_addr) == 0) { | |
fprintf(stderr, "The server address %s seems to be invalid.\n", server_address); | |
return -1; | |
} | |
// bind socket to socket address | |
if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) { | |
perror("error while binding socket"); | |
return -1; | |
} | |
// listen socket | |
if (listen(server_fd, 3) < 0) { | |
perror("error while listening"); | |
return -1; | |
} | |
printf("Server listening on %s port %d\n", server_address, port); | |
// accept clients | |
while (1) { | |
// accept client | |
struct sockaddr_in client_address; | |
socklen_t client_size = sizeof(client_address); | |
int client_fd = accept(server_fd, (struct sockaddr*)&client_address, &client_size); | |
if (client_fd < 0) { | |
perror("error while accepting client"); | |
continue; | |
} | |
// receive request from client (without parsing) | |
char client_buf[256]; | |
if (recv(client_fd, client_buf, sizeof(client_buf), 0) < 0) { | |
perror("error while receiving from client"); | |
close(client_fd); | |
continue; | |
} | |
// respond with http header | |
char* header = "HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\nContent-Disposition: attachment\r\n\r\n"; | |
if (send(client_fd, header, strlen(header), 0) < 0) { | |
perror("error while sending http header"); | |
close(client_fd); | |
continue; | |
} | |
// start responding with random bytes | |
while (1) { | |
// receive from client to check if the client closed the socket | |
char buffer[16]; | |
int r = recv(client_fd, buffer, 16, MSG_DONTWAIT); // no blocking | |
if (r == 0 || (r < 0 && errno != EAGAIN && errno != EWOULDBLOCK)) { // error while receiving or client closed socket | |
break; | |
} | |
// generate random bytes | |
char* random_bytes = get_random_bytes(); | |
if (random_bytes == NULL) { | |
break; | |
} | |
// send random bytes to client | |
if (send(client_fd, random_bytes, RANDOM_BYTE_CHUNK_SIZE, 0) < 0) { | |
free(random_bytes); | |
break; | |
} | |
free(random_bytes); | |
} | |
close(client_fd); | |
} | |
close(server_fd); // this close statement is obsolete because the loop will never break | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment