diff --git a/client.c b/client.c index 93314cb..40c058d 100644 --- a/client.c +++ b/client.c @@ -6,12 +6,14 @@ /* Closes client connection. */ int client_close(struct client_t *client) { + char timestamp[TIMESTAMP_LEN]; /* force closing in case of error */ if (close(client->socket) == -1) { close(client->socket); } client->socket = -1; - fprintf(stderr,"[%s] socket closed for client %s\n", __func__, client->ip_string); + time2string(time(NULL), timestamp); + fprintf(stderr,"[%s] socket closed for client %s @ %s\n", __func__, client->ip_string, timestamp); return 0; } @@ -46,6 +48,9 @@ int client_read(struct client_t *client) { /* handle special telnet characters coming from client */ telnet_handle_client_read(client->data, &len); + /* grab current time and store it as client last activity */ + client->last_active = time(NULL); + return len; } diff --git a/moxerver.c b/moxerver.c index 842402e..71c1aa4 100644 --- a/moxerver.c +++ b/moxerver.c @@ -11,14 +11,12 @@ #define NAME "moxerver" #define SERVER_WAIT_TIMEOUT 5 /* seconds for select() timeout in server loop */ -#define PORT_MIN 4001 /* minimum TCP port number */ -#define PORT_MAX 4008 /* maximum TCP port number */ /* Prints help message. */ static void usage() { //TODO maybe some styling should be done - fprintf(stderr, "Usage: moxerver -p tcp_port -t tty_path [-h]\n"); - fprintf(stderr, "- tcp_port range [%d .. %d]\n\n", PORT_MIN, PORT_MAX); + fprintf(stderr, "Usage: %s -p tcp_port -t tty_path [-h]\n", NAME); + fprintf(stderr, "\n"); } /* Performs cleanup and exit. */ @@ -42,6 +40,12 @@ void quit_handler(int signum) { cleanup(0); } +/* Converts from time in seconds from Epoch to conveniently formatted string. */ +int time2string(time_t time, char* timestamp) { + strftime(timestamp, TIMESTAMP_LEN, TIMESTAMP_FORMAT, localtime(&time)); + return 0; +} + /* MoxaNix main program loop. */ int main(int argc, char *argv[]) { @@ -94,14 +98,6 @@ int main(int argc, char *argv[]) { return -1; } } - /* check arguments */ - if (tcp_port < PORT_MIN || tcp_port > PORT_MAX) { - //TODO do we really put port constraints in moxerver? Maybe higher SW layer that controls all servers should handle it. - fprintf(stderr, "[%s] error: port number out of %d-%d range\n\n", - NAME, PORT_MIN, PORT_MAX); - usage(); - return -1; - } /* introduction message */ fprintf(stderr, "[%s] === MoxaNix ===\n", NAME); @@ -152,6 +148,7 @@ int main(int argc, char *argv[]) { ret = server_accept(&server, &client); if ( ret != 0) { /* print error but continue waiting for connection request */ + //TODO maybe we should break here to avoid endless loop fprintf(stderr, "[%s] problem accepting client\n", NAME); continue; } @@ -184,7 +181,17 @@ int main(int argc, char *argv[]) { } } if (ret == 0) { - fprintf(stderr, "[%s] server waiting\n", NAME); + /* do something with inactive client */ + if (client.socket != -1) { + //TODO we could drop client if inactive for some time + time_t current_time = time(NULL); + fprintf(stderr, "[%s] client last active %u seconds ago\n", NAME, + (unsigned int) (current_time - client.last_active)); + } + /* do something while listening for client connections */ + else { + fprintf(stderr, "[%s] listening for client connection\n", NAME); + } } } /* END while() loop */ diff --git a/moxerver.h b/moxerver.h index 0ce11a0..d663ee2 100644 --- a/moxerver.h +++ b/moxerver.h @@ -10,10 +10,12 @@ #include /* TCP_NODELAY */ #include #include +#include -#define DATA_BUFLEN 128 +#define DATABUF_LEN 128 #define DEV_PATH 32 - +#define TIMESTAMP_FORMAT "%d.%m.%Y. %H:%M:%S" +#define TIMESTAMP_LEN 20+1 /* calculated following timestamp format */ /* Structures used for communication parameters. */ struct server_t { @@ -26,14 +28,15 @@ struct client_t { int socket; /* client socket */ struct sockaddr_in address; /* client address information */ char ip_string[INET_ADDRSTRLEN]; /* client IP address as a string */ - char data[DATA_BUFLEN]; /* buffer for data received from client */ + time_t last_active; /* time of client's last activity in seconds from Epoch */ + char data[DATABUF_LEN]; /* buffer for data received from client */ }; struct tty_t { int fd; /* tty file descriptor */ struct termios ttyset; /* tty termios settings */ char path[DEV_PATH]; /* tty device path */ - char data[DATA_BUFLEN]; /* buffer for data received from tty */ + char data[DATABUF_LEN]; /* buffer for data received from tty */ }; @@ -43,6 +46,17 @@ struct client_t client; /* connected client structure */ //TODO working with on struct 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. */ /** @@ -58,7 +72,7 @@ int server_setup(struct server_t *server, unsigned int port); * Closes the server socket. * * Returns: - * 0 always, but internally tries closing again if it fails. + * 0 always, but internally tries closing again if it fails */ int server_close(struct server_t *server); @@ -86,12 +100,13 @@ int server_reject(struct server_t *server); * Closes client connection. * * Returns: - * 0 always, but internally tries closing again if it fails. + * 0 always, but internally tries closing again if it fails */ int client_close(struct 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, diff --git a/server.c b/server.c index e5c7dd3..e6a96c6 100644 --- a/server.c +++ b/server.c @@ -8,6 +8,7 @@ int server_setup(struct server_t *server, unsigned int port) { int opt; + char timestamp[TIMESTAMP_LEN]; /* set up server address information */ server->address.sin_family = AF_INET; /* use IPv4 address family */ @@ -52,17 +53,20 @@ int server_setup(struct server_t *server, unsigned int port) { return -errno; } - fprintf(stderr,"[%s] server is up, listening for client connection\n", __func__); + time2string(time(NULL), timestamp); + fprintf(stderr,"[%s] server is up @ %s\n", __func__, timestamp); return 0; } /* Closes the server socket. */ int server_close(struct server_t *server) { + char timestamp[TIMESTAMP_LEN]; /* force closing in case of error */ if (close(server->socket) == -1) { close(server->socket); } - fprintf(stderr,"[%s] socket closed, server is down\n", __func__); + time2string(time(NULL), timestamp); + fprintf(stderr,"[%s] socket closed, server is down @ %s\n", __func__, timestamp); return 0; } @@ -70,6 +74,7 @@ int server_close(struct server_t *server) { int server_accept(struct server_t *server, struct client_t *accepted_client) { int namelen; + char timestamp[TIMESTAMP_LEN]; /* accept connection request */ namelen = sizeof(accepted_client->address); @@ -88,10 +93,13 @@ int server_accept(struct server_t *server, struct client_t *accepted_client) { inet_ntop(accepted_client->address.sin_family, &accepted_client->address.sin_addr.s_addr, accepted_client->ip_string, INET_ADDRSTRLEN); + /* grab current time and store it as client last activity*/ + accepted_client->last_active = time(NULL); + /* print client information */ - //TODO also print timestamp - fprintf(stderr, "[%s] accepted client %s on port %u\n", __func__, - accepted_client->ip_string, server->port); + time2string(accepted_client->last_active, timestamp); + fprintf(stderr, "[%s] accepted client %s on port %u @ %s\n", __func__, + accepted_client->ip_string, server->port, timestamp); return 0; } @@ -101,6 +109,7 @@ int server_reject(struct server_t *server) { int namelen; struct client_t rclient; char reject_msg[128]; + char timestamp[TIMESTAMP_LEN]; /* accept connection request */ namelen = sizeof(rclient.address); @@ -111,6 +120,7 @@ int server_reject(struct server_t *server) { /* close connection */ close(rclient.socket); - fprintf(stderr, "[%s] rejected new client request, there is alredy a client connected\n", __func__); + time2string(time(NULL), timestamp); + fprintf(stderr, "[%s] rejected new client request @ %s\n", __func__, timestamp); return 0; } diff --git a/telnet.c b/telnet.c index 31c8a3e..c0702bd 100644 --- a/telnet.c +++ b/telnet.c @@ -96,7 +96,7 @@ int telnet_set_character_mode(struct client_t *client) { int telnet_handle_client_read(char *databuf, int *datalen) { int i; - char newdata[DATA_BUFLEN]; + char newdata[DATABUF_LEN]; int newlen = 0; /* process data using a new buffer */ @@ -123,7 +123,7 @@ int telnet_handle_client_read(char *databuf, int *datalen) { int telnet_handle_client_write(char *databuf, int *datalen) { int i; - char newdata[DATA_BUFLEN]; + char newdata[DATABUF_LEN]; int newlen = 0; /* process data using a new buffer */ diff --git a/tty.c b/tty.c index cd3d2c2..0f60e4e 100644 --- a/tty.c +++ b/tty.c @@ -93,7 +93,7 @@ void *tty_thread_func(void *arg) { ret = select(tty_dev->fd + 1, &read_fds, NULL, NULL, &tv); if (ret > 0 && FD_ISSET(tty_dev->fd, &read_fds)) { - br = read(tty_dev->fd, tty_dev->data, DATA_BUFLEN); + br = read(tty_dev->fd, tty_dev->data, DATABUF_LEN); client_write(&client, tty_dev->data, br); } else {