127 lines
3.5 KiB
C
127 lines
3.5 KiB
C
/*
|
|
* Handling communication with clients.
|
|
*/
|
|
|
|
#include "moxerver.h"
|
|
|
|
/* 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;
|
|
time2string(time(NULL), timestamp);
|
|
fprintf(stderr,"[%s] socket closed for client %s @ %s\n", __func__, client->ip_string, timestamp);
|
|
return 0;
|
|
}
|
|
|
|
/* Reads data from client into client data buffer. Returns number of read bytes. */
|
|
int client_read(struct client_t *client) {
|
|
|
|
int len;
|
|
|
|
/* read client data */
|
|
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 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;
|
|
}
|
|
|
|
/* Sends data from a buffer to client. Returns number of sent bytes. */
|
|
int client_write(struct 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 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;
|
|
}
|
|
|
|
/* Waits for client to provide a username. Blocks until a username is entered. */
|
|
int client_ask_username(struct client_t *client) {
|
|
|
|
int i;
|
|
char databuf[DATABUF_LEN];
|
|
fd_set read_fds;
|
|
|
|
/* send username request to client */
|
|
snprintf(databuf, DATABUF_LEN,
|
|
"\nPlease provide a username to identify yourself to other users (max %d characters):\n", USERNAME_LEN);
|
|
client_write(client, databuf, strlen(databuf));
|
|
|
|
/* wait for client input */
|
|
client->username[0] = '\0';
|
|
while (client->username[0] == '\0') {
|
|
/* send prompt character to client */
|
|
snprintf(databuf, DATABUF_LEN, "> ");
|
|
client_write(client, databuf, strlen(databuf));
|
|
/* setup select() parameters */
|
|
FD_ZERO(&read_fds);
|
|
FD_SET(client->socket, &read_fds);
|
|
select((client->socket)+1, &read_fds, NULL, NULL, NULL);
|
|
if (FD_ISSET(client->socket, &read_fds)) {
|
|
client_read(client);
|
|
/* handle client input */
|
|
for (i = 0; i < USERNAME_LEN; i++) {
|
|
if (client->data[i] == '\r') {
|
|
break;
|
|
}
|
|
client->username[i] = client->data[i];
|
|
}
|
|
client->username[i+1] = '\0';
|
|
}
|
|
}
|
|
|
|
/* send welcome message to client */
|
|
snprintf(databuf, DATABUF_LEN,
|
|
"\nWelcome %s!\n\n", client->username);
|
|
client_write(client, databuf, strlen(databuf));
|
|
|
|
return 0;
|
|
}
|