Implementing socket creation

This commit is contained in:
Max 2024-01-07 18:04:39 +01:00
parent 71326e34b2
commit 42bfd9dc14
18 changed files with 114 additions and 221 deletions

View File

@ -2,8 +2,7 @@
add_library(netex SHARED
"configuration.c"
"netex.c"
"storage.c")
"netex.c")
find_package(OpenSSL REQUIRED)
target_link_libraries(netex OpenSSL::SSL)

View File

@ -5,5 +5,4 @@ target_sources(netex PUBLIC
"net.h"
"netex.h"
"sockets.h"
"storage.h"
"strutil.h")

View File

@ -10,5 +10,6 @@
void netex_init(void);
void netex_shutdown(void);
int setup_socket(int port, const char* hostname);
#endif //NETEX_H

View File

@ -1,19 +0,0 @@
//
// Created by max on 25-12-23.
//
#ifndef STORAGE_H
#define STORAGE_H
#include "netex.h"
struct netex_configuration
{
char* server_name;
size_t port;
char* certificate_path;
};
int save_config(void);
int load_config_storage(void);
#endif //STORAGE_H

View File

@ -1,20 +1,17 @@
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>
#include "netex.h"
#include "storage.h"
#include "config.h"
void netex_init(void)
{
// Config
const int config_loaded = load_config_storage();
if (config_loaded != 0)
{
ERROR("Failed to load config! Shutting down...");
exit(EXIT_FAILURE);
}
// OpenSSL
PRINT_LINE("Initializing OpenSSL...");
SSL_load_error_strings();
@ -23,10 +20,54 @@ void netex_init(void)
}
void netex_shutdown(void)
{
// Config
save_config();
// OpenSSL
ERR_free_strings();
EVP_cleanup();
}
int setup_socket(const int port, const char* hostname)
{
struct addrinfo *cur_addrdinfo;
struct addrinfo hints_addrinfo = {0};
int sock_fd = 0;
hints_addrinfo.ai_family = AF_UNSPEC;
hints_addrinfo.ai_socktype = SOCK_DGRAM;
hints_addrinfo.ai_flags = AI_PASSIVE;
hints_addrinfo.ai_protocol = 0;
hints_addrinfo.ai_canonname = NULL;
hints_addrinfo.ai_addr = NULL;
hints_addrinfo.ai_next = NULL;
if (getaddrinfo(NULL, hostname, &hints_addrinfo, &cur_addrdinfo) != 0)
{
ERROR("Could not get the address info of hostname: '%s'", hostname);
return 1;
}
for (const struct addrinfo* tmp_addrinfo = cur_addrdinfo; tmp_addrinfo != NULL; tmp_addrinfo = tmp_addrinfo->ai_next)
{
sock_fd = socket(tmp_addrinfo->ai_family, tmp_addrinfo->ai_socktype, tmp_addrinfo->ai_protocol);
if (sock_fd == -1)
continue;
if (bind(sock_fd, tmp_addrinfo->ai_addr, tmp_addrinfo->ai_addrlen) == 0)
break; // Succesfull bind to the hostname
close(sock_fd);
}
/*struct sockaddr_in sockaddr;
const int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
WARN("Failed to create socket!");
return 1;
}
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(port);
sockaddr.sin_addr.s_addr = INADDR_ANY;
const int bind_result = bind(sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
if (bind_result != 0)
{
const int bind_error = errno;
ERROR("Failed to bind to socket! Error: %i", bind_error);
return 1;
}*/
return sock_fd;
}

View File

@ -1,153 +0,0 @@
#include <fcntl.h>
#include <unistd.h>
#include <json-c/json.h>
#include <errno.h>
#include <sys/stat.h>
#include <string.h>
#include "storage.h"
#define CONFIG_FILE_NAME "config.json"
#define PROP_SRV_NAME "server_name"
#define PROP_PORT "port"
#define PROP_CERT "certificate_path"
const char* config_to_json(const struct netex_configuration* net_config);
struct netex_configuration* create_config(const char* server_name, const size_t port);
void set_config(struct netex_configuration* config);
struct netex_configuration* json_to_config(const char* json);
struct netex_configuration* loaded_configuration;
int save_config(void)
{
if (loaded_configuration == NULL)
return 0; // Nothing to save
FILE* config_file = fopen(CONFIG_FILE_NAME, "w");
if (config_file == NULL)
{
const int error = errno;
ERROR("Failed to open file '%s', code %i", CONFIG_FILE_NAME, error);
return -1;
}
const char* json = config_to_json(loaded_configuration);
const size_t json_len = strlen(json);
const int write_result = fwrite(json, 1, json_len, config_file);
fclose(config_file);
if (write_result <= 0)
{
const int write_error = errno;
ERROR("Failed to write config file to disk! Error: %i", write_error);
return -1;
}
return 0;
}
int load_config_storage(void)
{
struct stat config_stat;
if (lstat(CONFIG_FILE_NAME, &config_stat) == -1)
{
const int error = errno;
if (error == ENOENT)// No config file found -> create new config with defaults & save to disk.
{
set_config(NULL);
return save_config();
}
WARN("Failed to get stat on file '%s', error: %i ", CONFIG_FILE_NAME, error);
return error;
}
const long int file_size = config_stat.st_size;
if (file_size <= 0)
{
WARN("Config file exists but is empty, fallback to default config...");
set_config(NULL);
return save_config();
}
FILE *config_fd = fopen(CONFIG_FILE_NAME, "r");
if (config_fd == NULL)
{
const int error = errno;
WARN("Failed to open file: '%s' with error code: %i", CONFIG_FILE_NAME, error);
return error;
}
void* file_mem = malloc(file_size);
if (file_mem == NULL)
{
const int error = errno;
WARN("Failed to allocate memory!");
return error;
}
const size_t total_read = fread(file_mem, file_size, file_size, config_fd);
fclose(config_fd);
if (total_read != 1)
{
free(file_mem);
return -1;
}
loaded_configuration = json_to_config(file_mem);
free(file_mem);
return 0;
}
struct netex_configuration* get_configuration()
{
if (loaded_configuration == NULL)
{
const int load_result = load_config_storage();
if (load_result != 0)
WARN("Failed to get configuration!");
}
return loaded_configuration;
}
struct netex_configuration* create_config(const char* server_name, const size_t port)
{
struct netex_configuration* nx_config = malloc(sizeof(struct netex_configuration));
if (nx_config == NULL)
{
WARN("Failed to allocate memory for configuration object!");
return nx_config;
}
nx_config->server_name = strdup(server_name);
nx_config->port = port;
return nx_config;
}
void set_config(struct netex_configuration* config)
{
if (loaded_configuration != NULL)
{
if (loaded_configuration->server_name != NULL)
free(loaded_configuration->server_name);
free(loaded_configuration);
}
if (config == NULL) // Fallback to default values
config = create_config("Linux netex server", 6920);
loaded_configuration = config;
}
struct netex_configuration* json_to_config(const char* json)
{
const json_object* json_obj = json_tokener_parse(json);
json_object* json_prop_srv_name;
const char* srv_name = "";
if (json_object_object_get_ex(json_obj, PROP_SRV_NAME, &json_prop_srv_name))
srv_name = json_object_get_string(json_prop_srv_name);
json_object* json_prop_port;
size_t srv_port = 0;
if (json_object_object_get_ex(json_obj, PROP_PORT, &json_prop_port))
srv_port = json_object_get_int64(json_prop_port);
struct netex_configuration* config = create_config(srv_name, srv_port);
return config;
}
const char* config_to_json(const struct netex_configuration* net_config)
{
json_object* jobj = json_object_new_object();
json_object* srv_name_obj = json_object_new_string(net_config->server_name);
if (json_object_object_add(jobj, PROP_SRV_NAME, srv_name_obj) != 0)
WARN("Failed to add property: '%s' to JSON!", PROP_SRV_NAME);
json_object* srv_port_obj = json_object_new_int64(net_config->port);
if (json_object_object_add(jobj, PROP_PORT, srv_port_obj) != 0)
WARN("Failed to add property: '%s' to JSON!", PROP_PORT);
return json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
}

View File

@ -1,5 +1,7 @@
add_executable(netex_svr
"server.c")
"main.c"
"server.c"
server.h)
target_include_directories(netex_svr PRIVATE ${CMAKE_SOURCE_DIR}/src/net/include)
target_link_libraries(netex_svr netex)

21
src/server/main.c Normal file
View File

@ -0,0 +1,21 @@
#include <stdio.h>
#include "netex.h"
#include "server.h"
// Sources:
// http://simplestcodings.blogspot.com/2010/08/secure-server-client-using-openssl-in-c.html
// https://stackoverflow.com/questions/40812836/how-to-create-chat-server-using-openssl-in-c
// https://www.cs.cmu.edu/~srini/15-441/F02/Projects/lab01/reference/part1.pdf
int main(int argc, char *argv[])
{
const int init_result = initialize_server(argc, argv);
if (init_result)
{
WARN("Failed to initialize server, error: %i. Exiting...", init_result);
return init_result;
}
return server_execute();
}

View File

@ -1,50 +1,45 @@
#include <errno.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "netex.h"
#include "config.h"
#define CONFIG_PATH "srv_config.json"
CONFIGURATION* srv_configuration;
int server_sockfd;
struct sockaddr_in server_sockaddr;
int srv_setup(void);
int main(int argc, char *argv[])
int initialize_server(int argc, char* argv[])
{
const CONFIGURATION* srv_config = config_load_from_path(CONFIG_PATH);
int remove_result = config_remove(srv_config, "Connection.CertPath");
config_set_string(srv_config, "Connection.CertPath", "cert.pem");
config_save_to_path(srv_config, CONFIG_PATH);
config_clear(srv_config);
// Config
srv_configuration = config_load_from_path(CONFIG_PATH);
if (srv_configuration == NULL)
{
WARN("Fallback to default config!");
srv_configuration = config_create();
config_set_int(srv_configuration, "Connection.Port", 6920);
config_set_string(srv_configuration, "Connection.Crypto.CertPath", "cert.pem");
if (config_save_to_path(srv_configuration, CONFIG_PATH) != 0)
{
WARN("Failed to save configuration to disk, default config is only available in memory!");
}
}
netex_init();
PRINT_LINE("Hello, server!");
if (argc > 1)
// Socket
const int64_t portnum = config_get_int(srv_configuration, "Connection.Port");
server_sockfd = setup_socket(portnum, "localhost");
if (server_sockfd < 0)
{
//TODO: Handle args
WARN("Failed to create socket!");
return 1;
}
if (srv_setup() != 0)
{
ERROR("Failed to initialize server!");
return 0;
}
netex_shutdown();
return 0;
}
void* th_srv_listen(void)
{
for (;;)
{
//TODO: Listen to connections & give a thread to handle communication
}
}
int svr_command(void)
int server_execute(void)
{
return 0;
}
int srv_setup(void)
{
return -1;
}

7
src/server/server.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef SERVER_H
#define SERVER_H
int initialize_server(int argc, char* argv[]);
int server_execute(void);
#endif //SERVER_H