connected client needs to provide a username which will be communicated to rejected clients
This commit is contained in:
parent
55367f5fee
commit
75b30f3aa6
5 changed files with 63 additions and 17 deletions
43
client.c
43
client.c
|
@ -82,3 +82,46 @@ int client_write(struct client_t *client, char *databuf, int datalen) {
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
- support multiple client connections at the same time
|
||||
- first client has control
|
||||
- additional clients can see the traffic
|
||||
- read-only: requests from controlling client and responses from tty device
|
||||
- need to avoid unintentional lock up if controlling client stays connected but user goes away and forgets about it
|
||||
- additional clients should be able to force disconnecting controlling client
|
||||
- first additional client that forces this becomes controlling client
|
||||
|
||||
- require username when connecting to the server
|
||||
- allows tracking users
|
||||
- makes the feature above (forcing disconnect) easier to use
|
||||
- username can be connected to a person easier than an IP address
|
|
@ -210,12 +210,14 @@ int main(int argc, char *argv[]) {
|
|||
fprintf(stderr, "[%s] problem accepting client\n", NAME);
|
||||
continue;
|
||||
}
|
||||
/* ask client to provide a username before going to "character" mode */
|
||||
client_ask_username(&client);
|
||||
/* put client in "character" mode */
|
||||
telnet_set_character_mode(&client);
|
||||
}
|
||||
/* reject connection request if a client is already connected */
|
||||
else {
|
||||
server_reject(&server);
|
||||
server_reject(&server, &client);
|
||||
}
|
||||
}
|
||||
/* check client status if connected */
|
||||
|
|
13
moxerver.h
13
moxerver.h
|
@ -17,6 +17,7 @@
|
|||
#define TIMESTAMP_FORMAT "%d.%m.%Y. %H:%M:%S"
|
||||
#define TIMESTAMP_LEN 20+1 /* calculated following timestamp format */
|
||||
#define CONFILE "moxanix.cfg"
|
||||
#define USERNAME_LEN 32
|
||||
|
||||
/* Structures used for communication parameters. */
|
||||
struct server_t {
|
||||
|
@ -30,6 +31,7 @@ struct client_t {
|
|||
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 */
|
||||
};
|
||||
|
||||
|
@ -94,7 +96,7 @@ int server_accept(struct server_t *server, struct client_t *accepted_client);
|
|||
* Returns:
|
||||
* 0 always, errors with rejected client are ignored
|
||||
*/
|
||||
int server_reject(struct server_t *server);
|
||||
int server_reject(struct server_t *server, struct client_t *client);
|
||||
|
||||
|
||||
/* Functions handling communication with clients. */
|
||||
|
@ -127,6 +129,15 @@ int client_read(struct client_t *client);
|
|||
*/
|
||||
int client_write(struct client_t *client, char *databuf, int datalen);
|
||||
|
||||
/**
|
||||
* Waits for client to provide a username.
|
||||
* Blocks until a username is entered.
|
||||
*
|
||||
* Returns:
|
||||
* 0 always
|
||||
*/
|
||||
int client_ask_username(struct client_t *client);
|
||||
|
||||
|
||||
/* Functions handling details related to telnet protocol. */
|
||||
|
||||
|
|
8
server.c
8
server.c
|
@ -104,7 +104,7 @@ int server_accept(struct server_t *server, struct client_t *accepted_client) {
|
|||
}
|
||||
|
||||
/* Rejects incoming client connection. Errors with rejected client are ignored. */
|
||||
int server_reject(struct server_t *server) {
|
||||
int server_reject(struct server_t *server, struct client_t *client) {
|
||||
|
||||
int namelen;
|
||||
struct client_t rclient;
|
||||
|
@ -114,8 +114,10 @@ int server_reject(struct server_t *server) {
|
|||
/* accept connection request */
|
||||
namelen = sizeof(rclient.address);
|
||||
rclient.socket = accept(server->socket, (struct sockaddr *) &rclient.address, (socklen_t *) &namelen);
|
||||
/* send reject message */
|
||||
sprintf(reject_msg, "[%s] port %u is already being used\n", __func__, server->port);
|
||||
/* send reject message to client */
|
||||
time2string(client->last_active, timestamp);
|
||||
sprintf(reject_msg, "\nPort %u is already being used:\ncurrent user: %s\nlast activity: @ %s\n\n",
|
||||
server->port, client->username, timestamp);
|
||||
send(rclient.socket, reject_msg, strlen(reject_msg), 0);
|
||||
/* close connection */
|
||||
close(rclient.socket);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue