Some code cleanup

This commit is contained in:
Igor Socec 2016-11-19 13:46:26 +01:00
parent c17e696566
commit b934bb120c
11 changed files with 122 additions and 112 deletions

View file

@ -51,7 +51,7 @@ int client_read(client_t *client)
}
/* handle special telnet characters coming from the client */
telnet_handle_client_read(client->data, &len);
telnet_filter_client_read(client->data, &len);
/* grab current time and store it as client's last activity */
client->last_active = time(NULL);
@ -64,7 +64,7 @@ int client_write(client_t *client, char *databuf, int datalen)
int len;
/* handle special telnet characters to display them correctly on client */
//telnet_handle_client_write(databuf, &datalen);
//telnet_filter_client_write(databuf, &datalen);
//TODO let's print received bytes during development phase...
if (debug_messages)
@ -119,7 +119,7 @@ int client_wait_line(client_t *client)
{
return -1;
}
/* we don't want empty data so stop on \r or \n */
/* we don't want empty data so ignore data starting with \r or \n */
if ( (client->data[0] == '\r') || (client->data[0] == '\n') )
{
client->data[0] = '\0';
@ -133,10 +133,10 @@ int client_wait_line(client_t *client)
int client_ask_username(client_t *client)
{
int i;
char msg[DATABUF_LEN];
char msg[BUFFER_LEN];
/* show username request to the client */
snprintf(msg, DATABUF_LEN,
snprintf(msg, BUFFER_LEN,
"\nPlease provide a username to identify yourself to"
"other users (max %d characters):\n", USERNAME_LEN);
client_write(client, msg, strlen(msg));
@ -160,7 +160,7 @@ int client_ask_username(client_t *client)
}
/* show welcome message to client */
snprintf(msg, DATABUF_LEN,
snprintf(msg, BUFFER_LEN,
"\nWelcome %s!\n\n", client->username);
client_write(client, msg, strlen(msg));

View file

@ -1,7 +1,7 @@
#pragma once
/* Handles communication with a client. */
#pragma once
#include <common.h>
#include <netinet/in.h>
@ -9,12 +9,12 @@
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 */
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 */
char username[USERNAME_LEN]; /* username for human identification */
char data[BUFFER_LEN]; /* buffer for received data */
} client_t;
/**
@ -48,7 +48,7 @@ int client_write(client_t *client, char *databuf, int datalen);
*
* Returns:
* - 0 on success
* - negative value if error occurred
* - negative value if an error occurred
*/
int client_wait_line(client_t *client);
@ -58,6 +58,6 @@ int client_wait_line(client_t *client);
*
* Returns:
* - 0 on success
* - negative value if error occurred
* - negative value if an error occurred
*/
int client_ask_username(client_t *client);

View file

@ -1,3 +1,5 @@
/* Common header file reused within the project */
#pragma once
#include <stdio.h>
@ -8,17 +10,20 @@
#include <time.h>
#include <fcntl.h>
#define DATABUF_LEN 128
/* ========================================================================== */
#define TIMESTAMP_FORMAT "%Y-%m-%dT%H:%M:%S" /* ISO 8601 */
#define TIMESTAMP_LEN 20+1 /* calculated according to the timestamp format */
#define BUFFER_LEN 128 /* length of a data buffer */
/* Global variables used throughout the application. */
int debug_messages; /* if > 0 debug messages will be printed */
/* ========================================================================== */
/* Global functions used throughout the application. */
int debug_messages; /* if > 0 debug messages will be printed */
/* ========================================================================== */
#define TIMESTAMP_FORMAT "%Y-%m-%dT%H:%M:%S" /* follow ISO 8601 format */
#define TIMESTAMP_LEN 20+1 /* size of the timestamp format above */
/**
* Converts time in seconds from Epoch to a conveniently formatted string.
* Converts time in "seconds from Epoch" to a conveniently formatted string.
*/
void time2string(time_t time, char* timestamp);

View file

@ -4,15 +4,16 @@
* communication with a specific TTY device.
*/
#include "moxerver.h"
#include "parser.h"
#include <moxerver.h>
#include <parser.h>
#include <signal.h> /* handling quit signals */
#include <pthread.h>
#define NAME "moxerver"
/* Prints help message. */
static void usage() {
static void usage()
{
//TODO maybe some styling should be done
fprintf(stderr, "Usage: %s -p tcp_port [-t tty_path] [-d] [-h]\n", NAME);
fprintf(stderr, "\t-t\ttty dev path (if not specified %s needs to be defined)\n", CONFILE);
@ -21,44 +22,55 @@ static void usage() {
}
/* Performs cleanup and exit. */
void cleanup(int exit_code) {
void cleanup(int exit_code)
{
// TODO: maybe pthread_kill() should be used for threads and cleanup there
fprintf(stderr, "[%s] cleanup and exit with %d\n", NAME, exit_code);
/* close client */
if (client.socket != -1) {
/* close the client */
if (client.socket != -1)
{
client_close(&client);
}
/* close tty device */
tty_close(&tty_dev);
/* close server */
/* close the tty device */
if (tty_dev.fd != -1)
{
tty_close(&tty_dev);
}
/* close the server */
server_close(&server);
/* exit */
exit(exit_code);
}
/* Handles received quit signals, use it for all quit signals of interest. */
void quit_handler(int signum) {
void quit_handler(int signum)
{
/* perform cleanup and exit with 0 */
fprintf(stderr, "[%s] received signal %d\n", NAME, signum);
cleanup(0);
}
/* Parse handler function, used to configure serial port */
int parse_handler(void *user, const char *section, const char *name, const char *value) {
int parse_handler(void *user, const char *section, const char *name, const char *value)
{
//printf("[%s] section = %s, name = %s, value = %s\n", __func__, section, name, value);
if (!strcmp(name, "speed") && (unsigned int)atoi(section) == server.port) {
if (!strcmp(name, "speed") && (unsigned int)atoi(section) == server.port)
{
fprintf(stderr, "[%s] setting %s speed for port %s\n", __func__, value, section);
if (cfsetispeed(&(tty_dev.ttyset), baud_to_speed(atoi(value))) < 0 ||
cfsetospeed(&(tty_dev.ttyset), baud_to_speed(atoi(value))) < 0) {
cfsetospeed(&(tty_dev.ttyset), baud_to_speed(atoi(value))) < 0)
{
fprintf(stderr, "[%s] error configuring tty device speed\n", NAME);
return -1;
}
}
if (!strcmp(name, "dev") && (unsigned int)atoi(section) == server.port)
{
strcpy(tty_dev.path, value);
}
return 1;
}
@ -70,7 +82,7 @@ void time2string(time_t time, char* timestamp)
void* thread_new_client_connection(void *args)
{
char msg[DATABUF_LEN];
char msg[BUFFER_LEN];
char timestamp[TIMESTAMP_LEN];
client_t temp_client;
@ -211,9 +223,9 @@ void* thread_client_data(void *args)
continue;
}
/* put client in "character" mode */
char msg[TELNET_MSG_SIZE_CHARMODE];
char msg[TELNET_MSG_LEN_CHARMODE];
telnet_message_set_character_mode(msg);
client_write(&client, msg, TELNET_MSG_SIZE_CHARMODE);
client_write(&client, msg, TELNET_MSG_LEN_CHARMODE);
}
/* setup parameters for select() */
@ -326,8 +338,8 @@ int main(int argc, char *argv[]) {
break;
/* get tty device path, default config used */
case 't':
if ((strnlen(optarg, DEV_PATH) == 0) ||
(strnlen(optarg, DEV_PATH) > (DEV_PATH - 1))) {
if ((strnlen(optarg, TTY_DEV_PATH_LEN) == 0) ||
(strnlen(optarg, TTY_DEV_PATH_LEN) > (TTY_DEV_PATH_LEN - 1))) {
fprintf(stderr, "[%s] error: tty path was not specified\n\n", NAME);
usage();
return -1;
@ -393,9 +405,10 @@ int main(int argc, char *argv[]) {
return -1;
}
/* start thread function (in this thread) that handles client data */
thread_client_data(NULL);
/* unexpected break from while() loop */
/* unexpected break from client data loop */
fprintf(stderr, "[%s] unexpected condition\n", NAME);
/* cleanup and exit with -1 */
cleanup(-1);

View file

@ -9,13 +9,13 @@
#define CONFILE "moxanix.cfg"
#define SERVER_WAIT_TIMEOUT 2 /* seconds for select() timeout in server loop */
#define TTY_WAIT_TIMEOUT 5 /* seconds for select() timeout in server loop */
#define TTY_WAIT_TIMEOUT 5 /* seconds for select() timeout in tty loop */
/* Global variables used throughout the application. */
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 */
server_t server; /* main server */
client_t client; /* connected client */ //TODO working with only 1 client, this can be expanded into a list
client_t new_client; /* reserved for a new client request */
tty_t tty_dev; /* connected tty device */
typedef struct
{

View file

@ -8,9 +8,9 @@ int server_setup(server_t *server, unsigned int port)
char timestamp[TIMESTAMP_LEN];
/* set up server address information */
server->address.sin_family = AF_INET; /* use IPv4 address family */
server->address.sin_port = htons(port); /* set up port number, htons is for using network byte order */
server->address.sin_addr.s_addr = INADDR_ANY; /* use local address */
server->address.sin_family = AF_INET; /* use IPv4 address family */
server->address.sin_port = htons(port); /* set up port number (htons for network byte order) */
server->address.sin_addr.s_addr = INADDR_ANY; /* use local address */
/* create stream socket using TCP */
server->socket = socket(AF_INET, SOCK_STREAM, 0);
@ -50,7 +50,7 @@ int server_setup(server_t *server, unsigned int port)
/* save server port number */
server->port = port;
fprintf(stderr,"[%s] assigned port %u\n", __func__, server->port); //ntohs(server->address.sin_port)
fprintf(stderr,"[%s] assigned port %u\n", __func__, server->port); // ntohs(server->address.sin_port)
/* listen for a client connection, allow some connections in queue */
if (listen(server->socket, 1) == -1)
@ -99,7 +99,7 @@ int server_accept(server_t *server, client_t *accepted_client)
return -errno;
}
/* get client IP address as human a readable string */
/* get client IP address as a human readable string */
inet_ntop(accepted_client->address.sin_family,
&accepted_client->address.sin_addr.s_addr,
accepted_client->ip_string, INET_ADDRSTRLEN);

View file

@ -1,15 +1,15 @@
#pragma once
/* Handles server operation. */
#pragma once
#include <common.h>
#include <client.h>
typedef struct
{
int socket; /* server socket */
struct sockaddr_in address; /* server address information */
unsigned int port; /* server port in host byte order, practical reference */
int socket; /* server socket */
struct sockaddr_in address; /* server address information */
unsigned int port; /* server port in host byte order */
} server_t;
/**

View file

@ -85,10 +85,10 @@ void telnet_message_set_character_mode(char *databuf)
//TODO Do we verify client response? What do we do if the response is not how we expected?
}
void telnet_handle_client_read(char *databuf, int *datalen)
void telnet_filter_client_read(char *databuf, int *datalen)
{
int i;
char newdata[DATABUF_LEN];
char newdata[BUFFER_LEN];
int newlen = 0;
/* process data using a new buffer */
@ -115,10 +115,10 @@ void telnet_handle_client_read(char *databuf, int *datalen)
*datalen = newlen;
}
void telnet_handle_client_write(char *databuf, int *datalen)
void telnet_filter_client_write(char *databuf, int *datalen)
{
int i;
char newdata[DATABUF_LEN]; // TODO: maybe use realloc, this is risky
char newdata[BUFFER_LEN]; // TODO: maybe use realloc, this is risky
int newlen = 0;
/* process data using a new buffer */

View file

@ -1,15 +1,15 @@
#pragma once
/* Handles details related to telnet protocol. */
#pragma once
#include <common.h>
#define TELNET_MSG_SIZE_CHARMODE 9
#define TELNET_MSG_LEN_CHARMODE 9
/**
* Creates a telnet protocol message that tells client to go into "character"
* mode. The passed data buffer must be big enough to hold the message payload
* with the size defined by TELNET_MSG_SIZE_CHARMODE.
* with the size defined by TELNET_MSG_LEN_CHARMODE.
* Operates directly on the passed data buffer.
*/
void telnet_message_set_character_mode(char *databuf);
@ -19,11 +19,11 @@ void telnet_message_set_character_mode(char *databuf);
* client. Used to filter out the handshake commands of telnet protocol.
* Operates directly on the passed data buffer and modifies the payload length.
*/
void telnet_handle_client_read(char *databuf, int *datalen);
void telnet_filter_client_read(char *databuf, int *datalen);
/**
* Handles special characters in the data buffer before sending them to the
* client. Used to correctly echo the characters to the telnet client.
* Operates directly on the passed data buffer and modifies the payload length.
*/
void telnet_handle_client_write(char *databuf, int *datalen);
void telnet_filter_client_write(char *databuf, int *datalen);

41
tty.c
View file

@ -1,32 +1,26 @@
#include <tty.h>
#define NAME "tty"
#define TTY_DEF_BAUD_RATE B115200
#define TTY_DEFAULT_BAUDRATE B115200
int tty_open(tty_t *tty_dev)
{
int fd;
// PROPOSAL:
// open tty device to get file descriptor @tty_dev.fd
// setup tty device parameters @tty_dev.ttyset
// apply settings by calling tcsetattr(fd, ttyset)
// on success copy path to @tty_dev.path
if ((fd = open (tty_dev->path, O_RDWR | O_NOCTTY | O_SYNC)) < 0)
/* open tty device to get the file descriptor */
tty_dev->fd = open (tty_dev->path, O_RDWR | O_NOCTTY | O_SYNC);
if (tty_dev->fd < 0)
{
tty_dev->fd = -1;
return -errno;
}
else
{
tty_dev->fd = fd;
}
/* store default termios setitngs */
if (tcgetattr(tty_dev->fd, &(tty_dev->ttysetdef)))
/* store default termios settings */
if (tcgetattr(tty_dev->fd, &(tty_dev->ttysetold)))
{
fprintf(stderr, "[%s] error reading device default config\n"
"\t\t-> default config will not be restored upon exit", __func__);
}
/* set tty device parameters */
tty_dev->ttyset.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR |
PARMRK | INPCK | ISTRIP | IXON);
tty_dev->ttyset.c_oflag &= ~(OCRNL | ONLCR | ONLRET |
@ -37,20 +31,21 @@ int tty_open(tty_t *tty_dev)
tty_dev->ttyset.c_cc[VMIN] = 1;
tty_dev->ttyset.c_cc[VTIME] = 5;
/* if speed is set to B0 (e.g. cfg file is not provided), default values are used */
/* if speed is set to B0 (e.g. cfg file not provided), use default values */
if (cfgetispeed(&(tty_dev->ttyset)) == baud_to_speed(0) &&
cfsetispeed(&(tty_dev->ttyset), TTY_DEF_BAUD_RATE) < 0)
cfsetispeed(&(tty_dev->ttyset), TTY_DEFAULT_BAUDRATE) < 0)
{
fprintf(stderr, "[%s] error configuring tty device speed\n", __func__);
return -errno;
}
if (cfgetospeed(&(tty_dev->ttyset)) == baud_to_speed(0) &&
cfsetospeed(&(tty_dev->ttyset), TTY_DEF_BAUD_RATE) < 0)
cfsetospeed(&(tty_dev->ttyset), TTY_DEFAULT_BAUDRATE) < 0)
{
fprintf(stderr, "[%s] error configuring tty device speed\n", __func__);
return -errno;
}
/* apply tty device settings */
if (tcsetattr(tty_dev->fd, TCSANOW, &(tty_dev->ttyset)) < 0)
{
fprintf(stderr, "[%s] error configuring tty device\n", __func__);
@ -67,7 +62,7 @@ int tty_close(tty_t *tty_dev)
fprintf(stderr, "[%s] closing tty device \n", __func__);
if (tcsetattr(fd, TCSANOW, &(tty_dev->ttysetdef)) < 0)
if (tcsetattr(fd, TCSANOW, &(tty_dev->ttysetold)) < 0)
{
fprintf(stderr, "[%s] error restoring tty device default config\n", __func__);
return -errno;
@ -81,19 +76,11 @@ int tty_close(tty_t *tty_dev)
return 0;
}
int tty_reconfigure(tty_t *tty_dev, struct termios newttyset)
{
// not sure how to organize this:
// 1. parameters in external termios struct, copied @tty_dev.ttyset, applied with tcsetattr()
// 2. parameters directly @tty_dev.ttyset, applied with tcsetattr()
return 0;
}
int tty_read(tty_t *tty_dev)
{
int len;
len = read(tty_dev->fd, tty_dev->data, DATABUF_LEN);
len = read(tty_dev->fd, tty_dev->data, BUFFER_LEN);
if (len == -1)
{
fprintf(stderr, "[%s:%d] error %d: %s\n", __func__, __LINE__,

39
tty.h
View file

@ -1,43 +1,48 @@
#pragma once
/* Handles communication with a tty device. */
#pragma once
#include <common.h>
#include <client.h>
#include <termios.h>
#define DEV_PATH 128
#define TTY_DEV_PATH_LEN 128
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 */
int fd; /* tty device file descriptor */
struct termios ttysetold; /* previous termios settings */
struct termios ttyset; /* current termios settings */
char path[TTY_DEV_PATH_LEN]; /* tty device path */
char data[BUFFER_LEN]; /* buffer for received data */
} tty_t;
/**
* Opens the tty device and configures it.
* The old device settings are saved.
*
* Returns:
* - 0 on success
* - negative errno value if an error occurred
*/
int tty_open(tty_t *tty_dev);
/**
* Closes the tty device.
* Closes the tty device connection.
* Also applies the old device settings.
*
* Returns:
* - 0 on success
* - negative errno value if an error occurred
*/
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.
*
* Returns:
* - number of read bytes on success,
* - negative errno value set by an error while readin
* - negative errno value set by an error while reading
*/
int tty_read(tty_t *tty_dev);
@ -51,8 +56,8 @@ int tty_read(tty_t *tty_dev);
int tty_write(tty_t *tty_dev, char *databuf, int datalen);
/**
* Converts POSIX speed_t to a baud rate. The values of the
* constants for speed_t are not themselves portable.
* Converts POSIX speed_t to a baud rate.
* The values of the constants for speed_t are not themselves portable.
*/
int speed_to_baud(speed_t speed);