Hi All! I’m confused about Stage #EJ5.
I was able to complete the stage and get all my tests passing without using threads. I’m a bit baffled by this because I assumed threads were required. I feel like I’m getting false positives. If someone could clarify why my tests are passing and if my implementation is actually okay, I would really appreciate it!
All I did was wrap my connection logic in a while loop to continuously accept connections. Below is all my code.
void handle_connection(int client_fd)
{
char request[1024];
char response[1024];
read(client_fd, request, sizeof(request));
// passing null starts from strtok static pointer to previous token
char *request_target = strtok(request, " ");
request_target = strtok(NULL, " ");
if (strcmp(request_target, "/") == 0)
{
send(client_fd, "HTTP/1.1 200 OK\r\n\r\n", 23, 0);
}
else if (strncmp(request_target, "/echo", 5) == 0)
{
int content_length = strlen(request_target + 6);
sprintf(
response,
"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %d\r\n\r\n%s",
content_length,
request_target + 6);
send(client_fd, response, strlen(response), 0);
}
else if (strncmp(request_target, "/user-agent", 11) == 0)
{
char *token = strtok(NULL, "\r\n");
while (strncmp(token, "User-Agent", 10) != 0)
{
token = strtok(NULL, "\r\n");
}
char *user_agent = strchr(token, ':') + 2;
int content_length = strlen(user_agent);
sprintf(
response,
"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %d\r\n\r\n%s",
content_length,
user_agent);
send(client_fd, response, strlen(response), 0);
}
else
{
send(client_fd, "HTTP/1.1 404 Not Found\r\n\r\n", 30, 0);
}
}
int main()
{
// Disable output buffering
setbuf(stdout, NULL);
setbuf(stderr, NULL);
// You can use print statements as follows for debugging, they'll be visible when running tests.
printf("Logs from your program will appear here!\n");
int server_fd, client_addr_len;
struct sockaddr_in client_addr;
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1)
{
printf("Socket creation failed: %s...\n", strerror(errno));
return 1;
}
// Since the tester restarts your program quite often, setting SO_REUSEADDR
// ensures that we don't run into 'Address already in use' errors
int reuse = 1;
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
printf("SO_REUSEADDR failed: %s \n", strerror(errno));
return 1;
}
struct sockaddr_in serv_addr = {
.sin_family = AF_INET,
.sin_port = htons(4221),
.sin_addr = {htonl(INADDR_ANY)},
};
if (bind(server_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0)
{
printf("Bind failed: %s \n", strerror(errno));
return 1;
}
int connection_backlog = 5;
if (listen(server_fd, connection_backlog) != 0)
{
printf("Listen failed: %s \n", strerror(errno));
return 1;
}
client_addr_len = sizeof(client_addr);
for (;;)
{
printf("Waiting for a client to connect...\n");
int client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len);
printf("Client connected\n");
handle_connection(client_fd);
//pthread_t t;
}
close(server_fd);
return 0;
}
Thanks so much!