Added argument parser and set all logs to STDERR
This commit is contained in:
@@ -23,7 +23,7 @@ static struct epoll_event _evs[MAX_EPOLL_EVENTS];
|
|||||||
bool loop_init(loop_cb_t callback) {
|
bool loop_init(loop_cb_t callback) {
|
||||||
_efd = epoll_create1(0);
|
_efd = epoll_create1(0);
|
||||||
if (_efd == -1) {
|
if (_efd == -1) {
|
||||||
printf("[!] epoll_create1 failed: %d\n", errno);
|
fprintf(stderr, "[!] epoll_create1 failed: %d\n", errno);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_cb = callback;
|
_cb = callback;
|
||||||
@@ -36,7 +36,7 @@ void loop_deinit() {
|
|||||||
|
|
||||||
bool loop_ctl(int op, int fd, struct epoll_event *event) {
|
bool loop_ctl(int op, int fd, struct epoll_event *event) {
|
||||||
if (epoll_ctl(_efd, op, fd, event) == -1) {
|
if (epoll_ctl(_efd, op, fd, event) == -1) {
|
||||||
printf("[!] epoll_ctl failed: %d\n", errno);
|
fprintf(stderr, "[!] epoll_ctl failed: %d\n", errno);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -50,7 +50,7 @@ bool loop_wait() {
|
|||||||
-1
|
-1
|
||||||
);
|
);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
printf("[!] epoll_wait failed: %d\n", errno);
|
fprintf(stderr, "[!] epoll_wait failed: %d\n", errno);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
|||||||
73
main.c
73
main.c
@@ -1,6 +1,8 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@@ -9,6 +11,7 @@
|
|||||||
|
|
||||||
#include "event_loop.h"
|
#include "event_loop.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data
|
* Data
|
||||||
@@ -20,6 +23,54 @@ static int _server_fd = -1;
|
|||||||
/*
|
/*
|
||||||
* Private API
|
* Private API
|
||||||
*/
|
*/
|
||||||
|
// Parse command line arguments and check if mandatory ones are present.
|
||||||
|
// Parameters:
|
||||||
|
// - argc
|
||||||
|
// - argv
|
||||||
|
// Returns:
|
||||||
|
// - true on success
|
||||||
|
// - false on failure
|
||||||
|
bool parse_cli_args(int argc, char** argv) {
|
||||||
|
if (argc < 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int key_length, value_length;
|
||||||
|
int i = 1;
|
||||||
|
char first_sym;
|
||||||
|
while (i < argc) {
|
||||||
|
key_length = strlen(argv[i] + 1);
|
||||||
|
first_sym = argv[i][0];
|
||||||
|
if (key_length != 1 || (first_sym != '+' && first_sym != '-')) {
|
||||||
|
fprintf(stderr, "[!] Argument '%s' is discarded\n", argv[i]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// flag
|
||||||
|
if (first_sym == '+') {
|
||||||
|
cli_arg_set(argv[i] + 1, argv[i] + 1);
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// argument
|
||||||
|
if (i + 1 >= argc) {
|
||||||
|
fprintf(stderr, "[!] Argument '%s' misses a value\n", argv[i]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
value_length = strlen(argv[i + 1]);
|
||||||
|
if (value_length < 1) {
|
||||||
|
fprintf(stderr, "[!] Argument '%s' has empty value\n", argv[i]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cli_arg_set(argv[i] + 1, argv[i + 1]);
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
bool required_args_present = true;
|
||||||
|
required_args_present &= cli_arg_get("M") ? true : false;
|
||||||
|
required_args_present &= cli_arg_get("A") ? true : false;
|
||||||
|
required_args_present &= cli_arg_get("P") ? true : false;
|
||||||
|
required_args_present &= cli_arg_get("E") ? true : false;
|
||||||
|
return required_args_present;
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize signals.
|
// Initialize signals.
|
||||||
// Returns:
|
// Returns:
|
||||||
// - true on success
|
// - true on success
|
||||||
@@ -32,7 +83,7 @@ static bool signals_init() {
|
|||||||
sigaddset(&mask, SIGINT);
|
sigaddset(&mask, SIGINT);
|
||||||
sigaddset(&mask, SIGQUIT);
|
sigaddset(&mask, SIGQUIT);
|
||||||
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
|
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
|
||||||
printf("[!] sigprocmask failed: %d\n", errno);
|
fprintf(stderr, "[!] sigprocmask failed: %d\n", errno);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_sig_fd = signalfd(
|
_sig_fd = signalfd(
|
||||||
@@ -41,7 +92,7 @@ static bool signals_init() {
|
|||||||
SFD_NONBLOCK
|
SFD_NONBLOCK
|
||||||
);
|
);
|
||||||
if (_sig_fd == -1) {
|
if (_sig_fd == -1) {
|
||||||
printf("[!] signalfd failed: %d\n", errno);
|
fprintf(stderr, "[!] signalfd failed: %d\n", errno);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
struct epoll_event ev;
|
struct epoll_event ev;
|
||||||
@@ -54,7 +105,7 @@ static bool signals_init() {
|
|||||||
);
|
);
|
||||||
if (!loop_res) {
|
if (!loop_res) {
|
||||||
close(_sig_fd);
|
close(_sig_fd);
|
||||||
printf("[!] loop_ctl failed\n");
|
fprintf(stderr, "[!] loop_ctl failed\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -69,7 +120,7 @@ static void signals_deinit() {
|
|||||||
// Returns:
|
// Returns:
|
||||||
// - true on success
|
// - true on success
|
||||||
static bool server_init() {
|
static bool server_init() {
|
||||||
_server_fd = server_open("0.0.0.0", 20070);
|
_server_fd = server_open(cli_arg_get("A"), atoi(cli_arg_get("P")));
|
||||||
if (_server_fd == -1) {
|
if (_server_fd == -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -83,7 +134,7 @@ static bool server_init() {
|
|||||||
);
|
);
|
||||||
if (!loop_res) {
|
if (!loop_res) {
|
||||||
server_close();
|
server_close();
|
||||||
printf("[!] loop_ctl failed\n");
|
fprintf(stderr, "[!] loop_ctl failed\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -106,16 +157,20 @@ static void on_fd_event(int fd, uint32_t events) {
|
|||||||
// Server event
|
// Server event
|
||||||
else if (fd == _server_fd) {
|
else if (fd == _server_fd) {
|
||||||
if (!server_event(_server_fd)) {
|
if (!server_event(_server_fd)) {
|
||||||
printf("[!] server_event failed\n");
|
fprintf(stderr, "[!] server_event failed\n");
|
||||||
_to_work = false;
|
_to_work = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("[!] Event has happened on an unknown file descriptor\n");
|
fprintf(stderr, "[!] Event has happened on an unknown file descriptor\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
if (!parse_cli_args(argc, argv)) {
|
||||||
|
print_usage_text();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
if (!loop_init(on_fd_event)) {
|
if (!loop_init(on_fd_event)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -131,10 +186,10 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
while (_to_work) {
|
while (_to_work) {
|
||||||
if (!loop_wait()) {
|
if (!loop_wait()) {
|
||||||
printf("[!] loop_wait returns false, stopping...\n");
|
fprintf(stderr, "[!] loop_wait returns false, stopping...\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("--- loop ---\n");
|
fprintf(stderr, "--- loop ---\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
server_close();
|
server_close();
|
||||||
|
|||||||
10
server.c
10
server.c
@@ -34,7 +34,7 @@ bool _accept() {
|
|||||||
int server_open(const char* host, int port) {
|
int server_open(const char* host, int port) {
|
||||||
struct hostent *he = gethostbyname(host);
|
struct hostent *he = gethostbyname(host);
|
||||||
if (!he) {
|
if (!he) {
|
||||||
printf("[!] gethostbyname failed: %d (h_errno)\n", h_errno);
|
fprintf(stderr, "[!] gethostbyname failed: %d (h_errno)\n", h_errno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
_fd = socket(
|
_fd = socket(
|
||||||
@@ -43,13 +43,13 @@ int server_open(const char* host, int port) {
|
|||||||
IPPROTO_TCP
|
IPPROTO_TCP
|
||||||
);
|
);
|
||||||
if (_fd == -1) {
|
if (_fd == -1) {
|
||||||
printf("[!] socket failed: %d\n", errno);
|
fprintf(stderr, "[!] socket failed: %d\n", errno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
const int opt = 1;
|
const int opt = 1;
|
||||||
if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
|
if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
|
||||||
close(_fd);
|
close(_fd);
|
||||||
printf("[!] setsockopt failed: %d\n", errno);
|
fprintf(stderr, "[!] setsockopt failed: %d\n", errno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
@@ -58,12 +58,12 @@ int server_open(const char* host, int port) {
|
|||||||
memcpy(&addr.sin_addr, he->h_addr, he->h_length);
|
memcpy(&addr.sin_addr, he->h_addr, he->h_length);
|
||||||
if (bind(_fd, (const void *)&addr, sizeof(addr)) == -1) {
|
if (bind(_fd, (const void *)&addr, sizeof(addr)) == -1) {
|
||||||
close(_fd);
|
close(_fd);
|
||||||
printf("[!] bind failed: %d\n", errno);
|
fprintf(stderr, "[!] bind failed: %d\n", errno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (listen(_fd, LISTEN_BACKLOG) == -1) {
|
if (listen(_fd, LISTEN_BACKLOG) == -1) {
|
||||||
close(_fd);
|
close(_fd);
|
||||||
printf("[!] listen failed: %d\n", errno);
|
fprintf(stderr, "[!] listen failed: %d\n", errno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return _fd;
|
return _fd;
|
||||||
|
|||||||
75
utils.c
75
utils.c
@@ -0,0 +1,75 @@
|
|||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros
|
||||||
|
*/
|
||||||
|
#define MAX_CLI_ARGS (20)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type definitions
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
const char *key;
|
||||||
|
char *value;
|
||||||
|
} cli_arg_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data
|
||||||
|
*/
|
||||||
|
static cli_arg_t _cli_args[MAX_CLI_ARGS];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Public API
|
||||||
|
*/
|
||||||
|
void print_usage_text() {
|
||||||
|
printf("ipoim -M <mode> -A <address> -P <port> -C <carrier> ...\n");
|
||||||
|
printf(" --- MANDATORY ARGUMENTS ---\n");
|
||||||
|
printf(" -M <mode> - operation mode ('provider' or 'last-mile')\n");
|
||||||
|
printf(" -A <address> - IPv4 to listen on/connect to\n");
|
||||||
|
printf(" -P <port> - port to listen on/connect to\n");
|
||||||
|
printf(" -E <carrier> - extension to use, one of:\n");
|
||||||
|
printf(" * pipe - use STDIN and STDOUT\n");
|
||||||
|
printf(" --- OPTIONAL ARGUMENTS ---\n");
|
||||||
|
printf(" +V - be verbose\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cli_arg_set(const char *key, char *value) {
|
||||||
|
int index_to_use = -1;
|
||||||
|
for (int i = 0; i < MAX_CLI_ARGS; ++i) {
|
||||||
|
// empty entry
|
||||||
|
if (_cli_args[i].key == NULL) {
|
||||||
|
// update index only if no place is found yet
|
||||||
|
if (index_to_use == -1)
|
||||||
|
index_to_use = i;
|
||||||
|
}
|
||||||
|
// entry with the same name
|
||||||
|
else if (!strcmp(_cli_args[i].key, key)) {
|
||||||
|
index_to_use = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// no space for the argument
|
||||||
|
if (index_to_use == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_cli_args[index_to_use].key = key;
|
||||||
|
_cli_args[index_to_use].value = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *cli_arg_get(const char *key) {
|
||||||
|
for (int i = 0; i < MAX_CLI_ARGS; ++i) {
|
||||||
|
if (_cli_args[i].key == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strcmp(_cli_args[i].key, key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return _cli_args[i].value;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|||||||
23
utils.h
23
utils.h
@@ -1,6 +1,29 @@
|
|||||||
#ifndef __UTILS_H
|
#ifndef __UTILS_H
|
||||||
#define __UTILS_H
|
#define __UTILS_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
// Print usage text.
|
||||||
|
void print_usage_text();
|
||||||
|
|
||||||
|
// Set CLI argument.
|
||||||
|
// Parameters:
|
||||||
|
// - key - argument key (without leading dash)
|
||||||
|
// - value - argument value as string
|
||||||
|
// Returns:
|
||||||
|
// - true on success
|
||||||
|
// - false on failure
|
||||||
|
// Remarks:
|
||||||
|
// - neither key nor value are copied, they are saved as pointers
|
||||||
|
// - use this function only with data from argv
|
||||||
|
bool cli_arg_set(const char *key, char *value);
|
||||||
|
|
||||||
|
// Get CLI argument.
|
||||||
|
// Parameters:
|
||||||
|
// - key - argument key (without leading dash)
|
||||||
|
// Returns:
|
||||||
|
// - pointer to the value (not owned by you)
|
||||||
|
// - NULL on failure
|
||||||
|
const char *cli_arg_get(const char *key);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user