BarryServer : Git

All the code for all my projects
// BarryServer : Git / IRCWebHooks / blob / 3f04e2245ef9565e8e9853cac3f2114fbfdd566d / src / webserver.c

// Related

IRCWebHooks

Barry Adding files 3f04e22 (3 years, 3 months ago)
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#include "config.h"
#include "list.h"
#include "irc.h"

int
create_socket(int port)
{
	int s;
	struct sockaddr_in addr;

	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);

	s = socket(AF_INET, SOCK_STREAM, 0);
	if (s < 0) {
		perror("Unable to create socket");
		exit(EXIT_FAILURE);
	}

	if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
		perror("Unable to bind");
		exit(EXIT_FAILURE);
	}

	if (listen(s, 1) < 0) {
		perror("Unable to listen");
		exit(EXIT_FAILURE);
	}

	return s;
}

void
init_openssl(void)
{
	SSL_load_error_strings();
	OpenSSL_add_ssl_algorithms();
}

void
cleanup_openssl(void)
{
	EVP_cleanup();
}

SSL_CTX *
create_context(void)
{
	const SSL_METHOD *method;
	SSL_CTX *ctx;

	method = SSLv23_server_method();

	ctx = SSL_CTX_new(method);
	if (!ctx) {
	perror("Unable to create SSL context");
		ERR_print_errors_fp(stderr);
		exit(EXIT_FAILURE);
	}

	return ctx;
}

void
configure_context(SSL_CTX *ctx)
{
	SSL_CTX_set_ecdh_auto(ctx, 1);

	/* Set the key and cert */
	if (SSL_CTX_use_certificate_file(ctx, "cert.pem", SSL_FILETYPE_PEM) <= 0) {
		ERR_print_errors_fp(stderr);
		exit(EXIT_FAILURE);
	}

	if (SSL_CTX_use_PrivateKey_file(ctx, "cert.pem", SSL_FILETYPE_PEM) <= 0 ) {
		ERR_print_errors_fp(stderr);
		exit(EXIT_FAILURE);
	}
}

int
srv(int argc, char **argv)
{
	printf("Spinning up webserver...\n");

	int sock;
#ifdef SSL_SERVER
	SSL_CTX *ctx;
	init_openssl();
	ctx = create_context();
	configure_context(ctx);
#endif

	sock = create_socket(WEB_PORT);

	/* Handle connections */
	while(1) {
		struct sockaddr_in addr;
		uint len = sizeof(addr);
#ifdef SSL_SERVER
		SSL *ssl;
#endif
		const char reply[] = "test\r\n";

		int client = accept(sock, (struct sockaddr*)&addr, &len);
		if (client < 0) {
			perror("Unable to accept");
			exit(EXIT_FAILURE);
		}

#ifdef SSL_SERVER
		ssl = SSL_new(ctx);
		SSL_set_fd(ssl, client);
		SSL_accept(ssl);
#endif

		char buf[1025];
		char *p, *uri, *cont;
		int conlen;
		char key[64];

#ifdef SSL_SERVER
		SSL_read(ssl, &buf, 1024);
#else
		read(client, &buf, 1024);
#endif

		if (!strncmp(buf, "POST /", 6)) {
			p = buf + 5;
			while (*p++) if (*p == '\n' || *p == '\r' || *p == ' ') *p = '\0';
			uri = buf + 6;
			cont = uri + strlen(uri) + 1;
			if ((p = strstr(cont, "Content-Length: ")) != NULL) {
				sscanf(p+16, "%i", &conlen);
			}
			if ((p = strstr(cont, "content=")) != NULL) {
				p[conlen] = '\0';
				p += 8;

				if (*(uri) == '\0') {
					for (current = head; current != NULL; current = current->next) {
						raw("PRIVMSG %s :%s\r\n", current->data, p);
					}
				} else
				if (*(uri) == '@') {
					raw("PRIVMSG %s :%s\r\n", buf+7, p);
				} else {
					raw("PRIVMSG #%s :%s\r\n", buf+6, p);
				}
			}
			memset(&buf, 0, 1024);
		}

#ifdef SSL_SERVER
		SSL_write(ssl, "HTTP/1.1 200 OK\r\n", 17);
		SSL_shutdown(ssl);
		SSL_free(ssl);
#else
		write(client, "HTTP/1.1 200 OK\r\n", 17);
#endif
		close(client);
	}

	close(sock);
#ifdef SSL_SERVER
	SSL_CTX_free(ctx);
	cleanup_openssl();
#endif
}