Created
July 25, 2012 00:37
-
-
Save minitech/3173635 to your computer and use it in GitHub Desktop.
My prototype webserver-thing
This file contains hidden or 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 "xeric-utils.h" | |
/* The main method. */ | |
int main(int argc, char * argv[]) { | |
int i; | |
int port = 80; | |
struct in_addr address = {0}; | |
/* Parse the arguments: */ | |
for(i = 1; i < argc; i++) { | |
if(strcmp(argv[i], "--port") == 0) { | |
i++; | |
if(i == argc) { | |
warn("Expected port number after --port option. Continuing with port 80."); | |
break; | |
} | |
port = strtoport(argv[i]); | |
if(!port) { | |
warn("Invalid port number specified. Continuing with port 80."); | |
port = 80; | |
} | |
} else if(strcmp(argv[i], "--address") == 0) { | |
i++; | |
if(i == argc) { | |
warn("Expected address after --address option. Continuing with address 0.0.0.0."); | |
break; | |
} | |
if(inet_pton(AF_INET, argv[i], &address) != 1) { | |
warn("Invalid address specified. Continuing with address 0.0.0.0."); | |
} | |
} else { | |
printf("Unrecognized option %s.\n", argv[i]); | |
} | |
} | |
int client; | |
socklen_t clilen = sizeof(struct sockaddr_in); | |
char buffer[1024]; | |
char str_address[16]; | |
struct sockaddr_in serv_addr, cli_addr; | |
int n; | |
/* Create the socket: */ | |
s = socket(AF_INET, SOCK_STREAM, 0); | |
if(s < 0) { | |
warn("Error opening socket."); | |
return 1; | |
} | |
/* Listen on the socket: */ | |
serv_addr.sin_family = AF_INET; | |
serv_addr.sin_port = htons(port); | |
serv_addr.sin_addr = address; | |
errno = 0; | |
if(bind(s, (struct sockaddr *) &serv_addr, sizeof serv_addr) < 0) { | |
if(errno == EADDRINUSE) | |
warn("Could not bind to port; already in use."); | |
else | |
warn("Could not bind to port due to an unknown error."); | |
return 1; | |
} | |
listen(s, 5); | |
success("Xeric 0.1.0 has started!"); | |
inet_ntop(AF_INET, &serv_addr.sin_addr, str_address, 15); | |
printf("Listening at %s:%d.\n", str_address, port); | |
/* Enable the Ctrl+C SIGINT handler so that the socket can be closed */ | |
signal(SIGINT, interrupted); | |
while(keepRunning) { | |
/* Accept a client: */ | |
client = accept(s, (struct sockaddr *)&cli_addr, &clilen); | |
if(client < 0) { | |
warn("Error on accept."); | |
return 1; | |
} | |
ip4_t r_addr = {cli_addr.sin_addr.s_addr}; | |
printf("Got client from %d.%d.%d.%d.\n", r_addr.components.p1, r_addr.components.p2, r_addr.components.p3, r_addr.components.p4); | |
/* Read data from the client: */ | |
bzero(buffer, 1024); | |
n = read(client, buffer, 1023); | |
if(n < 0) { | |
warn("Error reading from socket; breaking connection."); | |
goto close; | |
} | |
puts(buffer); | |
/* Write data to the client: */ | |
const char * output = "HTTP/1.1 200 OK\nContent-Type: text/html\n\n<h1>It works!</h1> <p>Welcome to Xeric, the tiny server.</p>"; | |
n = write(client, output, strlen(output)); | |
if(n < 0) { | |
warn("Error writing to socket; breaking connection."); | |
goto close; | |
} | |
close: | |
/* Close the connection: */ | |
close(client); | |
} | |
if(s >= 0) { | |
close(s); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment