Some code cleanup
This commit is contained in:
parent
c17e696566
commit
b934bb120c
11 changed files with 122 additions and 112 deletions
12
client.c
12
client.c
|
@ -51,7 +51,7 @@ int client_read(client_t *client)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle special telnet characters coming from the 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 */
|
/* grab current time and store it as client's last activity */
|
||||||
client->last_active = time(NULL);
|
client->last_active = time(NULL);
|
||||||
|
@ -64,7 +64,7 @@ int client_write(client_t *client, char *databuf, int datalen)
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
/* handle special telnet characters to display them correctly on client */
|
/* 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...
|
//TODO let's print received bytes during development phase...
|
||||||
if (debug_messages)
|
if (debug_messages)
|
||||||
|
@ -119,7 +119,7 @@ int client_wait_line(client_t *client)
|
||||||
{
|
{
|
||||||
return -1;
|
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') )
|
if ( (client->data[0] == '\r') || (client->data[0] == '\n') )
|
||||||
{
|
{
|
||||||
client->data[0] = '\0';
|
client->data[0] = '\0';
|
||||||
|
@ -133,10 +133,10 @@ int client_wait_line(client_t *client)
|
||||||
int client_ask_username(client_t *client)
|
int client_ask_username(client_t *client)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char msg[DATABUF_LEN];
|
char msg[BUFFER_LEN];
|
||||||
|
|
||||||
/* show username request to the client */
|
/* show username request to the client */
|
||||||
snprintf(msg, DATABUF_LEN,
|
snprintf(msg, BUFFER_LEN,
|
||||||
"\nPlease provide a username to identify yourself to"
|
"\nPlease provide a username to identify yourself to"
|
||||||
"other users (max %d characters):\n", USERNAME_LEN);
|
"other users (max %d characters):\n", USERNAME_LEN);
|
||||||
client_write(client, msg, strlen(msg));
|
client_write(client, msg, strlen(msg));
|
||||||
|
@ -160,7 +160,7 @@ int client_ask_username(client_t *client)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* show welcome message to client */
|
/* show welcome message to client */
|
||||||
snprintf(msg, DATABUF_LEN,
|
snprintf(msg, BUFFER_LEN,
|
||||||
"\nWelcome %s!\n\n", client->username);
|
"\nWelcome %s!\n\n", client->username);
|
||||||
client_write(client, msg, strlen(msg));
|
client_write(client, msg, strlen(msg));
|
||||||
|
|
||||||
|
|
12
client.h
12
client.h
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
/* Handles communication with a client. */
|
/* Handles communication with a client. */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
@ -12,9 +12,9 @@ typedef struct
|
||||||
int socket; /* client socket */
|
int socket; /* client socket */
|
||||||
struct sockaddr_in address; /* client address information */
|
struct sockaddr_in address; /* client address information */
|
||||||
char ip_string[INET_ADDRSTRLEN]; /* client IP address as a string */
|
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 */
|
time_t last_active; /* time of client's last activity */
|
||||||
char username[USERNAME_LEN]; /* username for human identification */
|
char username[USERNAME_LEN]; /* username for human identification */
|
||||||
char data[DATABUF_LEN]; /* buffer for data received from client */
|
char data[BUFFER_LEN]; /* buffer for received data */
|
||||||
} client_t;
|
} client_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,7 +48,7 @@ int client_write(client_t *client, char *databuf, int datalen);
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* - 0 on success
|
* - 0 on success
|
||||||
* - negative value if error occurred
|
* - negative value if an error occurred
|
||||||
*/
|
*/
|
||||||
int client_wait_line(client_t *client);
|
int client_wait_line(client_t *client);
|
||||||
|
|
||||||
|
@ -58,6 +58,6 @@ int client_wait_line(client_t *client);
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* - 0 on success
|
* - 0 on success
|
||||||
* - negative value if error occurred
|
* - negative value if an error occurred
|
||||||
*/
|
*/
|
||||||
int client_ask_username(client_t *client);
|
int client_ask_username(client_t *client);
|
||||||
|
|
17
common.h
17
common.h
|
@ -1,3 +1,5 @@
|
||||||
|
/* Common header file reused within the project */
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -8,17 +10,20 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#define DATABUF_LEN 128
|
/* ========================================================================== */
|
||||||
|
|
||||||
#define TIMESTAMP_FORMAT "%Y-%m-%dT%H:%M:%S" /* ISO 8601 */
|
#define BUFFER_LEN 128 /* length of a data buffer */
|
||||||
#define TIMESTAMP_LEN 20+1 /* calculated according to the timestamp format */
|
|
||||||
|
/* ========================================================================== */
|
||||||
|
|
||||||
/* Global variables used throughout the application. */
|
|
||||||
int debug_messages; /* if > 0 debug messages will be printed */
|
int debug_messages; /* if > 0 debug messages will be printed */
|
||||||
|
|
||||||
/* Global functions used throughout the application. */
|
/* ========================================================================== */
|
||||||
|
|
||||||
|
#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);
|
void time2string(time_t time, char* timestamp);
|
||||||
|
|
51
moxerver.c
51
moxerver.c
|
@ -4,15 +4,16 @@
|
||||||
* communication with a specific TTY device.
|
* communication with a specific TTY device.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "moxerver.h"
|
#include <moxerver.h>
|
||||||
#include "parser.h"
|
#include <parser.h>
|
||||||
#include <signal.h> /* handling quit signals */
|
#include <signal.h> /* handling quit signals */
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
#define NAME "moxerver"
|
#define NAME "moxerver"
|
||||||
|
|
||||||
/* Prints help message. */
|
/* Prints help message. */
|
||||||
static void usage() {
|
static void usage()
|
||||||
|
{
|
||||||
//TODO maybe some styling should be done
|
//TODO maybe some styling should be done
|
||||||
fprintf(stderr, "Usage: %s -p tcp_port [-t tty_path] [-d] [-h]\n", NAME);
|
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);
|
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. */
|
/* 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);
|
fprintf(stderr, "[%s] cleanup and exit with %d\n", NAME, exit_code);
|
||||||
/* close client */
|
/* close the client */
|
||||||
if (client.socket != -1) {
|
if (client.socket != -1)
|
||||||
|
{
|
||||||
client_close(&client);
|
client_close(&client);
|
||||||
}
|
}
|
||||||
/* close tty device */
|
/* close the tty device */
|
||||||
|
if (tty_dev.fd != -1)
|
||||||
|
{
|
||||||
tty_close(&tty_dev);
|
tty_close(&tty_dev);
|
||||||
/* close server */
|
}
|
||||||
|
/* close the server */
|
||||||
server_close(&server);
|
server_close(&server);
|
||||||
/* exit */
|
/* exit */
|
||||||
exit(exit_code);
|
exit(exit_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles received quit signals, use it for all quit signals of interest. */
|
/* 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 */
|
/* perform cleanup and exit with 0 */
|
||||||
fprintf(stderr, "[%s] received signal %d\n", NAME, signum);
|
fprintf(stderr, "[%s] received signal %d\n", NAME, signum);
|
||||||
cleanup(0);
|
cleanup(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse handler function, used to configure serial port */
|
/* 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);
|
//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);
|
fprintf(stderr, "[%s] setting %s speed for port %s\n", __func__, value, section);
|
||||||
|
|
||||||
if (cfsetispeed(&(tty_dev.ttyset), baud_to_speed(atoi(value))) < 0 ||
|
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);
|
fprintf(stderr, "[%s] error configuring tty device speed\n", NAME);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(name, "dev") && (unsigned int)atoi(section) == server.port)
|
if (!strcmp(name, "dev") && (unsigned int)atoi(section) == server.port)
|
||||||
|
{
|
||||||
strcpy(tty_dev.path, value);
|
strcpy(tty_dev.path, value);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -70,7 +82,7 @@ void time2string(time_t time, char* timestamp)
|
||||||
|
|
||||||
void* thread_new_client_connection(void *args)
|
void* thread_new_client_connection(void *args)
|
||||||
{
|
{
|
||||||
char msg[DATABUF_LEN];
|
char msg[BUFFER_LEN];
|
||||||
char timestamp[TIMESTAMP_LEN];
|
char timestamp[TIMESTAMP_LEN];
|
||||||
client_t temp_client;
|
client_t temp_client;
|
||||||
|
|
||||||
|
@ -211,9 +223,9 @@ void* thread_client_data(void *args)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* put client in "character" mode */
|
/* put client in "character" mode */
|
||||||
char msg[TELNET_MSG_SIZE_CHARMODE];
|
char msg[TELNET_MSG_LEN_CHARMODE];
|
||||||
telnet_message_set_character_mode(msg);
|
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() */
|
/* setup parameters for select() */
|
||||||
|
@ -326,8 +338,8 @@ int main(int argc, char *argv[]) {
|
||||||
break;
|
break;
|
||||||
/* get tty device path, default config used */
|
/* get tty device path, default config used */
|
||||||
case 't':
|
case 't':
|
||||||
if ((strnlen(optarg, DEV_PATH) == 0) ||
|
if ((strnlen(optarg, TTY_DEV_PATH_LEN) == 0) ||
|
||||||
(strnlen(optarg, DEV_PATH) > (DEV_PATH - 1))) {
|
(strnlen(optarg, TTY_DEV_PATH_LEN) > (TTY_DEV_PATH_LEN - 1))) {
|
||||||
fprintf(stderr, "[%s] error: tty path was not specified\n\n", NAME);
|
fprintf(stderr, "[%s] error: tty path was not specified\n\n", NAME);
|
||||||
usage();
|
usage();
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -393,9 +405,10 @@ int main(int argc, char *argv[]) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* start thread function (in this thread) that handles client data */
|
||||||
thread_client_data(NULL);
|
thread_client_data(NULL);
|
||||||
|
|
||||||
/* unexpected break from while() loop */
|
/* unexpected break from client data loop */
|
||||||
fprintf(stderr, "[%s] unexpected condition\n", NAME);
|
fprintf(stderr, "[%s] unexpected condition\n", NAME);
|
||||||
/* cleanup and exit with -1 */
|
/* cleanup and exit with -1 */
|
||||||
cleanup(-1);
|
cleanup(-1);
|
||||||
|
|
|
@ -9,12 +9,12 @@
|
||||||
#define CONFILE "moxanix.cfg"
|
#define CONFILE "moxanix.cfg"
|
||||||
|
|
||||||
#define SERVER_WAIT_TIMEOUT 2 /* seconds for select() timeout in server loop */
|
#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. */
|
/* Global variables used throughout the application. */
|
||||||
server_t server; /* main server structure */
|
server_t server; /* main server */
|
||||||
client_t client; /* connected client structure */ //TODO working with only 1 client, this can be expanded into a list
|
client_t client; /* connected client */ //TODO working with only 1 client, this can be expanded into a list
|
||||||
client_t new_client; /* client structure for new client request */
|
client_t new_client; /* reserved for a new client request */
|
||||||
tty_t tty_dev; /* connected tty device */
|
tty_t tty_dev; /* connected tty device */
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
6
server.c
6
server.c
|
@ -9,7 +9,7 @@ int server_setup(server_t *server, unsigned int port)
|
||||||
|
|
||||||
/* set up server address information */
|
/* set up server address information */
|
||||||
server->address.sin_family = AF_INET; /* use IPv4 address family */
|
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_port = htons(port); /* set up port number (htons for network byte order) */
|
||||||
server->address.sin_addr.s_addr = INADDR_ANY; /* use local address */
|
server->address.sin_addr.s_addr = INADDR_ANY; /* use local address */
|
||||||
|
|
||||||
/* create stream socket using TCP */
|
/* create stream socket using TCP */
|
||||||
|
@ -50,7 +50,7 @@ int server_setup(server_t *server, unsigned int port)
|
||||||
|
|
||||||
/* save server port number */
|
/* save server port number */
|
||||||
server->port = port;
|
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 */
|
/* listen for a client connection, allow some connections in queue */
|
||||||
if (listen(server->socket, 1) == -1)
|
if (listen(server->socket, 1) == -1)
|
||||||
|
@ -99,7 +99,7 @@ int server_accept(server_t *server, client_t *accepted_client)
|
||||||
return -errno;
|
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,
|
inet_ntop(accepted_client->address.sin_family,
|
||||||
&accepted_client->address.sin_addr.s_addr,
|
&accepted_client->address.sin_addr.s_addr,
|
||||||
accepted_client->ip_string, INET_ADDRSTRLEN);
|
accepted_client->ip_string, INET_ADDRSTRLEN);
|
||||||
|
|
6
server.h
6
server.h
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
/* Handles server operation. */
|
/* Handles server operation. */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <client.h>
|
#include <client.h>
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ typedef struct
|
||||||
{
|
{
|
||||||
int socket; /* server socket */
|
int socket; /* server socket */
|
||||||
struct sockaddr_in address; /* server address information */
|
struct sockaddr_in address; /* server address information */
|
||||||
unsigned int port; /* server port in host byte order, practical reference */
|
unsigned int port; /* server port in host byte order */
|
||||||
} server_t;
|
} server_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
8
telnet.c
8
telnet.c
|
@ -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?
|
//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;
|
int i;
|
||||||
char newdata[DATABUF_LEN];
|
char newdata[BUFFER_LEN];
|
||||||
int newlen = 0;
|
int newlen = 0;
|
||||||
|
|
||||||
/* process data using a new buffer */
|
/* process data using a new buffer */
|
||||||
|
@ -115,10 +115,10 @@ void telnet_handle_client_read(char *databuf, int *datalen)
|
||||||
*datalen = newlen;
|
*datalen = newlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
void telnet_handle_client_write(char *databuf, int *datalen)
|
void telnet_filter_client_write(char *databuf, int *datalen)
|
||||||
{
|
{
|
||||||
int i;
|
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;
|
int newlen = 0;
|
||||||
|
|
||||||
/* process data using a new buffer */
|
/* process data using a new buffer */
|
||||||
|
|
12
telnet.h
12
telnet.h
|
@ -1,15 +1,15 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
/* Handles details related to telnet protocol. */
|
/* Handles details related to telnet protocol. */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <common.h>
|
#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"
|
* 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
|
* 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.
|
* Operates directly on the passed data buffer.
|
||||||
*/
|
*/
|
||||||
void telnet_message_set_character_mode(char *databuf);
|
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.
|
* client. Used to filter out the handshake commands of telnet protocol.
|
||||||
* Operates directly on the passed data buffer and modifies the payload length.
|
* 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
|
* Handles special characters in the data buffer before sending them to the
|
||||||
* client. Used to correctly echo the characters to the telnet client.
|
* client. Used to correctly echo the characters to the telnet client.
|
||||||
* Operates directly on the passed data buffer and modifies the payload length.
|
* 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
41
tty.c
|
@ -1,32 +1,26 @@
|
||||||
#include <tty.h>
|
#include <tty.h>
|
||||||
|
|
||||||
#define NAME "tty"
|
#define NAME "tty"
|
||||||
#define TTY_DEF_BAUD_RATE B115200
|
#define TTY_DEFAULT_BAUDRATE B115200
|
||||||
|
|
||||||
int tty_open(tty_t *tty_dev)
|
int tty_open(tty_t *tty_dev)
|
||||||
{
|
{
|
||||||
int fd;
|
/* open tty device to get the file descriptor */
|
||||||
// PROPOSAL:
|
tty_dev->fd = open (tty_dev->path, O_RDWR | O_NOCTTY | O_SYNC);
|
||||||
// open tty device to get file descriptor @tty_dev.fd
|
if (tty_dev->fd < 0)
|
||||||
// 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)
|
|
||||||
{
|
{
|
||||||
|
tty_dev->fd = -1;
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
tty_dev->fd = fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* store default termios setitngs */
|
/* store default termios settings */
|
||||||
if (tcgetattr(tty_dev->fd, &(tty_dev->ttysetdef)))
|
if (tcgetattr(tty_dev->fd, &(tty_dev->ttysetold)))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "[%s] error reading device default config\n"
|
fprintf(stderr, "[%s] error reading device default config\n"
|
||||||
"\t\t-> default config will not be restored upon exit", __func__);
|
"\t\t-> default config will not be restored upon exit", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* set tty device parameters */
|
||||||
tty_dev->ttyset.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR |
|
tty_dev->ttyset.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR |
|
||||||
PARMRK | INPCK | ISTRIP | IXON);
|
PARMRK | INPCK | ISTRIP | IXON);
|
||||||
tty_dev->ttyset.c_oflag &= ~(OCRNL | ONLCR | ONLRET |
|
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[VMIN] = 1;
|
||||||
tty_dev->ttyset.c_cc[VTIME] = 5;
|
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) &&
|
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__);
|
fprintf(stderr, "[%s] error configuring tty device speed\n", __func__);
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
if (cfgetospeed(&(tty_dev->ttyset)) == baud_to_speed(0) &&
|
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__);
|
fprintf(stderr, "[%s] error configuring tty device speed\n", __func__);
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* apply tty device settings */
|
||||||
if (tcsetattr(tty_dev->fd, TCSANOW, &(tty_dev->ttyset)) < 0)
|
if (tcsetattr(tty_dev->fd, TCSANOW, &(tty_dev->ttyset)) < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "[%s] error configuring tty device\n", __func__);
|
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__);
|
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__);
|
fprintf(stderr, "[%s] error restoring tty device default config\n", __func__);
|
||||||
return -errno;
|
return -errno;
|
||||||
|
@ -81,19 +76,11 @@ int tty_close(tty_t *tty_dev)
|
||||||
return 0;
|
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 tty_read(tty_t *tty_dev)
|
||||||
{
|
{
|
||||||
int len;
|
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)
|
if (len == -1)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "[%s:%d] error %d: %s\n", __func__, __LINE__,
|
fprintf(stderr, "[%s:%d] error %d: %s\n", __func__, __LINE__,
|
||||||
|
|
39
tty.h
39
tty.h
|
@ -1,43 +1,48 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
/* Handles communication with a tty device. */
|
/* Handles communication with a tty device. */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <client.h>
|
#include <client.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
|
||||||
#define DEV_PATH 128
|
#define TTY_DEV_PATH_LEN 128
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int fd; /* tty file descriptor */
|
int fd; /* tty device file descriptor */
|
||||||
struct termios ttysetdef; /* default tty termios settings */
|
struct termios ttysetold; /* previous termios settings */
|
||||||
struct termios ttyset; /* tty termios settings */
|
struct termios ttyset; /* current termios settings */
|
||||||
char path[DEV_PATH]; /* tty device path */
|
char path[TTY_DEV_PATH_LEN]; /* tty device path */
|
||||||
char data[DATABUF_LEN]; /* buffer for data received from tty */
|
char data[BUFFER_LEN]; /* buffer for received data */
|
||||||
} tty_t;
|
} tty_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the tty device and configures it.
|
* 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);
|
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);
|
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.
|
* Reads incoming data from tty device to tty data buffer.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* - number of read bytes on success,
|
* - 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);
|
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);
|
int tty_write(tty_t *tty_dev, char *databuf, int datalen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts POSIX speed_t to a baud rate. The values of the
|
* Converts POSIX speed_t to a baud rate.
|
||||||
* constants for speed_t are not themselves portable.
|
* The values of the constants for speed_t are not themselves portable.
|
||||||
*/
|
*/
|
||||||
int speed_to_baud(speed_t speed);
|
int speed_to_baud(speed_t speed);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue