-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient_list.c
executable file
·136 lines (108 loc) · 3.21 KB
/
client_list.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include "client_list.h"
#include "log.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
client_list_t client_list = {NULL, NULL, 0};
struct client_node *create_client_node() {
struct client_node *cn = malloc(sizeof(struct client_node));
check_alloc(cn);
cn->state = NONE;
cn->next = NULL;
cn->req_to = NULL;
cn->req_from = NULL;
cn->play_with = NULL;
cn->data = NULL;
cn->data_count = 0;
cn->data_cursor = 0;
cn->read_dispatch = NULL;
cn->write_dispatch = NULL;
cn->muted = FALSE;
return cn;
}
struct client_node *destroy_client_node(struct client_node *cn) {
struct client_node *ret;
assert(cn != NULL);
ret = cn->next;
if ( cn->data != NULL ) free(cn->data);
free(cn);
return ret;
}
void destroy_client_list(struct client_node *cn) {
while ( cn != NULL )
cn = destroy_client_node(cn);
}
void add_client_node(struct client_node *cn) {
assert(cn != NULL);
if ( client_list.tail == NULL ) {
client_list.head = client_list.tail = cn;
} else {
client_list.tail->next = cn;
client_list.tail = cn;
}
cn->next = NULL;
client_list.count++;
}
struct client_node *remove_client_node(struct client_node *cn) {
struct client_node *ptr;
assert(cn != NULL);
if ( client_list.head == cn ) client_list.head = cn->next;
ptr = client_list.head;
while ( ptr != NULL && ptr->next != cn ) ptr = ptr->next;
if ( ptr != NULL && ptr->next == cn ) ptr->next = cn->next;
if ( client_list.tail == cn ) client_list.tail = ptr;
client_list.count--;
return ptr;
}
struct client_node *get_client_by_socket(int socket) {
struct client_node *nc = client_list.head;
while ( nc != NULL && nc->socket != socket ) nc = nc->next;
return nc;
}
struct client_node *get_client_by_username(const char *username) {
struct client_node *nc = client_list.head;
while ( nc &&
(nc->state == CONNECTED || strcmp(nc->username, username) != 0) )
nc = nc->next;
return nc;
}
/* CLIENT_REPR_SIZE = max(
strlen("[longest_username]"),
strlen("123.456.789.123:12345")
) + 1 */
#if MAX_USERNAME_LENGTH + 3 > 22
#define CLIENT_REPR_SIZE MAX_USERNAME_LENGTH + 3
#else
#define CLIENT_REPR_SIZE 22
#endif
char client_repr_buffer[CLIENT_REPR_SIZE];
const char *client_sockaddr_p(struct client_node *client) {
const char *s;
assert(client != NULL);
s = inet_ntop(AF_INET, &(client->addr.sin_addr), client_repr_buffer,
INET_ADDRSTRLEN);
if ( s == NULL ) log_message(LOG_DEBUG, "Client has invalid address");
sprintf(client_repr_buffer + strlen(client_repr_buffer), ":%hu",
ntohs(client->addr.sin_port));
return client_repr_buffer;
}
const char *client_canon_p(struct client_node *client) {
assert(client != NULL);
switch ( client->state ) {
case NONE:
case CONNECTED:
return client_sockaddr_p(client);
case FREE:
case BUSY:
case PLAY:
sprintf(client_repr_buffer, "[%s]", client->username);
}
return client_repr_buffer;
}
int log_statechange(struct client_node *client) {
assert(client != NULL);
return flog_message(LOG_DEBUG, "%s is now %s", client_canon_p(client),
state_name(client->state));
}