#include #include #include #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; CertificateAutority *ca = malloc( sizeof( CertificateAutority ) ); ca->cert = NULL; ca->pkey = NULL; ca->certs = NULL; 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; } } ca->pkey = read_private_key( config->keyfile ); if (!path_exists( config->certfile ) ){ printf("Creating cert\n"); if ( !create_and_save_cert(config->certfile, read_private_key( config->keyfile) ) ){ return 1; } } ca->cert = read_cert( config->certfile ); 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, ca); } close(client); freeRequest( request ); } return 0; }