moxanix/client.c
Igor Socec c17e696566 More extraction of functionality
Extracting server and tty functions into separate headers.
Thread functions for new connections, tty data and client data
are also extracted and used as separate functional blocks.
2016-11-19 01:48:12 +01:00

168 lines
3.7 KiB
C

#include <client.h>
#include <telnet.h>
void client_close(client_t *client)
{
char timestamp[TIMESTAMP_LEN];
/* force closing in case of error */
if (close(client->socket) == -1)
{
close(client->socket);
}
client->socket = -1;
time2string(time(NULL), timestamp);
fprintf(stderr,"[%s] socket closed for client %s @ %s\n", __func__,
client->ip_string, timestamp);
}
int client_read(client_t *client)
{
int len;
/* read data from the client */
len = recv(client->socket, client->data, sizeof(client->data)-1, 0);
if (len == -1)
{
fprintf(stderr, "[%s:%d] error %d: %s\n", __func__, __LINE__,
errno, strerror(errno));
return -errno;
}
/* a disconnected client socket is ready for reading but read returns 0 */
if (len == 0)
{
fprintf(stderr, "[%s:%d] no data available from client\n",
__func__, __LINE__);
return -ENODATA;
}
//TODO let's print received bytes during development phase...
if (debug_messages)
{
int i;
for(i = 0; i < len; i++)
{
fprintf(stderr, "client %s <- %u '%c'\n",
client->ip_string,
(unsigned char) client->data[i],
(unsigned char) client->data[i]);
}
}
/* handle special telnet characters coming from the client */
telnet_handle_client_read(client->data, &len);
/* grab current time and store it as client's last activity */
client->last_active = time(NULL);
return len;
}
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);
//TODO let's print received bytes during development phase...
if (debug_messages)
{
int i;
for(i = 0; i < datalen; i++)
{
fprintf(stderr, "client %s -> %u '%c'\n",
client->ip_string,
(unsigned char) databuf[i],
(unsigned char) databuf[i]);
}
}
/* send data to the client */
len = send(client->socket, databuf, datalen, 0);
if (len == -1)
{
fprintf(stderr, "[%s:%d] error %d: %s\n", __func__, __LINE__,
errno, strerror(errno));
return -errno;
}
return len;
}
int client_wait_line(client_t *client)
{
fd_set read_fds;
struct timeval tv;
client->data[0] = '\0';
/* loop waiting for client input */
while (client->data[0] == '\0')
{
/* setup select() parameters */
tv.tv_sec = 15; /* 15 second timeout */
tv.tv_usec = 0;
FD_ZERO(&read_fds);
FD_SET(client->socket, &read_fds);
/* send prompt character to the client */
client_write(client, "> ", 2);
/* block until input arrives */
if (select((client->socket)+1, &read_fds, NULL, NULL, &tv) <= 0)
{
return -1;
}
if (FD_ISSET(client->socket, &read_fds))
{
/* read client input */
if (client_read(client) == -1)
{
return -1;
}
/* we don't want empty data so stop on \r or \n */
if ( (client->data[0] == '\r') || (client->data[0] == '\n') )
{
client->data[0] = '\0';
}
}
}
return 0;
}
int client_ask_username(client_t *client)
{
int i;
char msg[DATABUF_LEN];
/* show username request to the client */
snprintf(msg, DATABUF_LEN,
"\nPlease provide a username to identify yourself to"
"other users (max %d characters):\n", USERNAME_LEN);
client_write(client, msg, strlen(msg));
/* wait for client input */
if (client_wait_line(client) != 0)
{
return -1;
}
/* save received data as client username */
for (i = 0; i < USERNAME_LEN; i++)
{
if ( (client->data[i] == '\r') || (client->data[i] == '\n') )
{
/* don't include \r or \n in the username */
client->username[i] = '\0';
break;
}
client->username[i] = client->data[i];
}
/* show welcome message to client */
snprintf(msg, DATABUF_LEN,
"\nWelcome %s!\n\n", client->username);
client_write(client, msg, strlen(msg));
return 0;
}