You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
3.8 KiB
162 lines
3.8 KiB
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
|
|
#include "database.h" |
|
#include "proxy.h" |
|
#include "config.h" |
|
#include "request.h" |
|
#include "response.h" |
|
#include "ssl.h" |
|
|
|
#define PACKAGE_NAME "WICTP" |
|
#define DEFAULT_DATABASE "data.sqlite" |
|
#define DEFAULT_CONFIG "config.json" |
|
#define DEFAULT_PORT 8080 |
|
|
|
unsigned int validatePortNumber(unsigned int portNumber){ |
|
// Given that we are dealing with unsined ints, we don't need to worry about |
|
// checking for values less than 0 |
|
if ( portNumber > 65535 ){ |
|
printf( "Port %i is invalid, using default of %i", portNumber, DEFAULT_PORT ); |
|
return DEFAULT_PORT; |
|
} |
|
return portNumber; |
|
} |
|
|
|
void printHelp(){ |
|
printf("Usage: %s [options]\n", PACKAGE_NAME); |
|
printf( "Options are:\n" ); |
|
printf( "\t --config OPTION VALUE Sets config option OPTION to VALUE\n" ); |
|
printf( "\t --print-config Prints current config\n" ); |
|
} |
|
|
|
int startListener(unsigned int port){ |
|
//we need to act as an http server |
|
int server_fd; |
|
struct sockaddr_in address; |
|
memset( &address, 0, sizeof(address) ); |
|
int addrlen = sizeof(address); |
|
Response *response; |
|
char *responseStr; |
|
|
|
// Creating socket file descriptor |
|
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { |
|
perror("socket failed"); |
|
return -1; |
|
} |
|
|
|
address.sin_family = AF_INET; |
|
address.sin_addr.s_addr = INADDR_ANY; |
|
address.sin_port = htons( port ); |
|
|
|
// Forcefully attaching socket to the port 8080 |
|
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) != 0) { |
|
perror("bind failed"); |
|
return -1; |
|
} |
|
|
|
if (listen(server_fd, 3) != 0) { |
|
perror("listen"); |
|
return -1; |
|
} |
|
|
|
return server_fd; |
|
} |
|
|
|
|
|
int main(int argc, char**argv){ |
|
Config *config = configDefaults(); |
|
int listener; |
|
|
|
|
|
for ( unsigned int i = 1; i < argc; i++ ){ |
|
if ( strcmp( argv[i], "--config" ) == 0 ){ |
|
if ( i + 2 < argc ){ |
|
setConfig( config, argv[i + 1], argv[i + 2] ); |
|
i += 2; |
|
} else { |
|
printf("--config requires 2 positional arguments\n"); |
|
} |
|
} else if ( strcmp( argv[i], "--print-config" ) == 0 ){ |
|
printConfig(config); |
|
return 0; |
|
} else if ( strcmp( argv[i], "--help" ) == 0 ){ |
|
printHelp(); |
|
return 0; |
|
} else { |
|
printf("Unknown option %s\n", argv[i]); |
|
} |
|
} |
|
|
|
if (path_exists( config->userConfig ) ){ |
|
printf("User config file exists but still needs to be parsed\n"); |
|
} |
|
|
|
if (path_exists( config->localConfig ) ){ |
|
printf("Local config file exists but still needs to be parsed\n"); |
|
} |
|
|
|
if ( !db_file_exists(config->database) ){ |
|
printf("Creating DB"); |
|
db_create(config->database); |
|
} |
|
|
|
maybeMakeDir( getConfigDir() ); |
|
|
|
|
|
if (!path_exists( config->keyfile ) ){ |
|
printf("Creating keyfile\n"); |
|
if ( !create_and_save_key(config->keyfile) ){ |
|
return 1; |
|
} |
|
} |
|
|
|
if (!path_exists( config->certfile ) ){ |
|
printf("Creating cert\n"); |
|
if ( !create_and_save_cert(config->certfile, read_private_key( config->keyfile) ) ){ |
|
return 1; |
|
} |
|
} |
|
|
|
listener = startListener(config->port); |
|
|
|
if ( listener < 0 ){ |
|
return 1; |
|
} |
|
|
|
while ( true ){ |
|
struct sockaddr_in addr; |
|
socklen_t addrlen = sizeof(addr); |
|
int client = 0; |
|
Request *request = NULL; |
|
printf("Listening on port %i\n", config->port); |
|
|
|
if ((client = accept(listener, (struct sockaddr *)&addr, |
|
&addrlen))<0) { |
|
perror("accept"); |
|
return 0; |
|
} |
|
|
|
//I think eventually I'd like a different thread here for each request |
|
//Not sure how to do that yet though so I'll keep everything on the main |
|
//thread |
|
|
|
request = newRequestFromSocket(client); |
|
|
|
if ( strcmp( request->host, "" ) == 0 ){ |
|
// If the host is not defined, then it is not a proxy request |
|
// Note that the host here is where the request should be sent, not |
|
// necesarily the hosts header |
|
webserverRequest(request, client); |
|
} else { |
|
proxyRequest(request, client); |
|
} |
|
|
|
close(client); |
|
freeRequest( request ); |
|
|
|
} |
|
|
|
return 0; |
|
}
|
|
|