#include #include #include #include #include #include #include #include #include #include /* TCP_NODELAY */ #include #include #include #include #define DATABUF_LEN 128 #define DEV_PATH 128 #define TIMESTAMP_FORMAT "%Y-%m-%dT%H:%M:%S" /* ISO 8601 */ #define TIMESTAMP_LEN 20+1 /* calculated following the timestamp format */ #define CONFILE "moxanix.cfg" #define USERNAME_LEN 32 /* Structures used for communication parameters. */ typedef struct { int socket; /* server socket */ struct sockaddr_in address; /* server address information */ unsigned int port; /* server port in host byte order, practical reference */ } server_t; typedef struct { int socket; /* client socket */ struct sockaddr_in address; /* client address information */ char ip_string[INET_ADDRSTRLEN]; /* client IP address as a string */ time_t last_active; /* time of client's last activity in seconds from Epoch */ char username[USERNAME_LEN]; /* username for human identification */ char data[DATABUF_LEN]; /* buffer for data received from client */ } client_t; typedef struct { int fd; /* tty file descriptor */ struct termios ttysetdef; /* default tty termios settings */ struct termios ttyset; /* tty termios settings */ char path[DEV_PATH]; /* tty device path */ char data[DATABUF_LEN]; /* buffer for data received from tty */ } tty_t; /* Global variables used throughout the application. */ int debug_messages; /* if > 0 debug messages will be printed */ server_t server; /* main server structure */ client_t client; /* connected client structure */ //TODO working with only 1 client, this can be expanded into a list client_t new_client; /* client structure for new client request */ tty_t tty_dev; /* connected tty device */ /* Global functions used throughout the application. */ /** * Converts from time in seconds from Epoch to conveniently formatted string. * * Returns: * 0 always */ int time2string(time_t time, char* timestamp); /* Functions handling server operation. */ /** * Sets up the server on specific port, binds to a socket and listens for client connections. * * Returns: * - 0 on success, * - negative errno value set appropriately by error in setup process */ int server_setup(server_t *server, unsigned int port); /** * Closes the server socket. * * Returns: * 0 always, but internally tries closing again if it fails */ int server_close(server_t *server); /** * Accepts incoming client connection. * * Returns: * - 0 on success, * - negative errno value set appropriately by error in setup process */ int server_accept(server_t *server, client_t *accepted_client); /** * Thread function handling new client connections. * If there is no connected client then first client request is accepted. * If there is a connected client then new client is asked if connected client should be dropped. * * Returns: * Return value from this thread function is not used. * Function handles global client variables: * - client structure is reset if new client is available to connect to * - new_client structure stores information about the client to connect to */ void* server_new_client_thread(void *args); /* Functions handling communication with clients. */ /** * Closes client connection. * * Returns: * 0 always, but internally tries closing again if it fails */ int client_close(client_t *client); /** * Reads data from client into client data buffer. * Also updates client's last activity timestamp. * * Returns: * - number of read bytes on success, * - negative ENODATA value (-ENODATA) if client disconnected, * - negative errno value set appropriately by error in reading */ int client_read(client_t *client); /** * Sends data from a buffer to client. * * Returns: * - number of sent bytes on success, * - negative errno value set appropriately by error in sending */ int client_write(client_t *client, char *databuf, int datalen); /** * Waits for client input in "line mode", where client sends a whole line of characters. * Blocks until input arrives. * * Returns: * - 0 on success * - negative value if error occurred */ int client_wait_line(client_t *client); /** * Waits for client to provide a username. * Blocks until a username is entered. * * Returns: * - 0 on success * - negative value if error occurred */ int client_ask_username(client_t *client); /* Functions handling communication with tty device. */ /* Opens the tty device and configures it. */ int tty_open(tty_t *tty_dev); /* Closes the tty device. */ int tty_close(tty_t *tty_dev); /* Reconfigures the tty device. */ int tty_reconfigure(tty_t *tty_dev, struct termios newttyset); /* Reads incoming data from tty device to tty data buffer. */ int tty_read(tty_t *tty_dev); /* Sends data from a buffer to tty device. */ int tty_write(tty_t *tty_dev, char *databuf, int datalen); /* Main tty thread function */ void *tty_thread_func(void *arg); int speed_to_baud(speed_t speed); speed_t baud_to_speed(int baud);