1 /*
2 * uhub - A tiny ADC p2p connection hub
3 * Copyright (C) 2007-2014, Jan Vidar Krey
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 #include "uhub.h"
21
22 #ifdef DEBUG_SENDQ
user_log_str(struct hub_user * user)23 static const char* user_log_str(struct hub_user* user)
24 {
25 static char buf[128];
26 if (user)
27 {
28 snprintf(buf, 128, "user={ %p, \"%s\", %s/%s}", user, user->id.nick, sid_to_string(user->id.sid), user->id.cid);
29 }
30 else
31 {
32 snprintf(buf, 128, "user={ %p }", user);
33 }
34 return buf;
35 }
36 #endif
37
user_create(struct hub_info * hub,struct net_connection * con,struct ip_addr_encap * addr)38 struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr)
39 {
40 struct hub_user* user = NULL;
41
42 LOG_TRACE("user_create(), hub=%p, con[sd=%d]", hub, net_con_get_sd(con));
43
44 user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
45
46 if (user == NULL)
47 return NULL; /* OOM */
48
49 user->send_queue = ioq_send_create();
50 user->recv_queue = ioq_recv_create();
51
52 user->connection = con;
53 net_con_reinitialize(user->connection, net_event, user, NET_EVENT_READ);
54
55 memcpy(&user->id.addr, addr, sizeof(struct ip_addr_encap));
56 user_set_state(user, state_protocol);
57
58 flood_control_reset(&user->flood_chat);
59 flood_control_reset(&user->flood_connect);
60 flood_control_reset(&user->flood_search);
61 flood_control_reset(&user->flood_update);
62 flood_control_reset(&user->flood_extras);
63
64 user->hub = hub;
65 return user;
66 }
67
68
user_destroy(struct hub_user * user)69 void user_destroy(struct hub_user* user)
70 {
71 LOG_TRACE("user_destroy(), user=%p", user);
72
73 ioq_recv_destroy(user->recv_queue);
74 ioq_send_destroy(user->send_queue);
75
76 if (user->connection)
77 {
78 LOG_TRACE("user_destory() -> net_con_close(%p)", user->connection);
79 net_con_close(user->connection);
80 }
81
82 adc_msg_free(user->info);
83 user_clear_feature_cast_support(user);
84 hub_free(user);
85 }
86
user_set_state(struct hub_user * user,enum user_state state)87 void user_set_state(struct hub_user* user, enum user_state state)
88 {
89 if ((user->state == state_cleanup && state != state_disconnected) || (user->state == state_disconnected))
90 {
91 return;
92 }
93
94 user->state = state;
95 }
96
user_set_info(struct hub_user * user,struct adc_message * cmd)97 void user_set_info(struct hub_user* user, struct adc_message* cmd)
98 {
99 adc_msg_free(user->info);
100 if (cmd)
101 {
102 user->info = adc_msg_incref(cmd);
103 }
104 else
105 {
106 user->info = 0;
107 }
108 }
109
user_update_info(struct hub_user * u,struct adc_message * cmd)110 void user_update_info(struct hub_user* u, struct adc_message* cmd)
111 {
112 char prefix[2];
113 char* argument;
114 size_t n = 0;
115 struct adc_message* cmd_new = adc_msg_copy(u->info);
116 if (!cmd_new)
117 {
118 /* FIXME: OOM! */
119 return;
120 }
121
122 /*
123 * FIXME: Optimization potential:
124 *
125 * remove parts of cmd that do not really change anything in cmd_new.
126 * this can save bandwidth if clients send multiple updates for information
127 * that does not really change anything.
128 */
129 argument = adc_msg_get_argument(cmd, n++);
130 while (argument)
131 {
132 if (strlen(argument) >= 2)
133 {
134 prefix[0] = argument[0];
135 prefix[1] = argument[1];
136 adc_msg_replace_named_argument(cmd_new, prefix, argument+2);
137 }
138
139 hub_free(argument);
140 argument = adc_msg_get_argument(cmd, n++);
141 }
142 user_set_info(u, cmd_new);
143 adc_msg_free(cmd_new);
144 }
145
146
convert_support_fourcc(int fourcc)147 static int convert_support_fourcc(int fourcc)
148 {
149 switch (fourcc)
150 {
151 case FOURCC('B','A','S','0'):
152 return feature_bas0;
153
154 case FOURCC('B','A','S','E'):
155 return feature_base;
156
157 case FOURCC('A','U','T','0'):
158 return feature_auto;
159
160 case FOURCC('U','C','M','0'):
161 case FOURCC('U','C','M','D'):
162 return feature_ucmd;
163
164 case FOURCC('Z','L','I','F'):
165 return feature_zlif;
166
167 case FOURCC('B','B','S','0'):
168 return feature_bbs;
169
170 case FOURCC('T','I','G','R'):
171 return feature_tiger;
172
173 case FOURCC('B','L','O','M'):
174 case FOURCC('B','L','O','0'):
175 return feature_bloom;
176
177 case FOURCC('P','I','N','G'):
178 return feature_ping;
179
180 case FOURCC('L','I','N','K'):
181 return feature_link;
182
183 case FOURCC('A','D','C','S'):
184 return feature_adcs;
185
186 // ignore these extensions, they are not useful for the hub.
187 case FOURCC('D','H','T','0'):
188 return 0;
189
190 default:
191 LOG_DEBUG("Unknown extension: %x", fourcc);
192 return 0;
193 }
194 }
195
user_support_add(struct hub_user * user,int fourcc)196 void user_support_add(struct hub_user* user, int fourcc)
197 {
198 int feature_mask = convert_support_fourcc(fourcc);
199 user->flags |= feature_mask;
200 }
201
user_flag_get(struct hub_user * user,enum user_flags flag)202 int user_flag_get(struct hub_user* user, enum user_flags flag)
203 {
204 return user->flags & flag;
205 }
206
user_flag_set(struct hub_user * user,enum user_flags flag)207 void user_flag_set(struct hub_user* user, enum user_flags flag)
208 {
209 user->flags |= flag;
210 }
211
user_flag_unset(struct hub_user * user,enum user_flags flag)212 void user_flag_unset(struct hub_user* user, enum user_flags flag)
213 {
214 user->flags &= ~flag;
215 }
216
user_set_nat_override(struct hub_user * user)217 void user_set_nat_override(struct hub_user* user)
218 {
219 user_flag_set(user, flag_nat);
220 }
221
user_is_nat_override(struct hub_user * user)222 int user_is_nat_override(struct hub_user* user)
223 {
224 return user_flag_get(user, flag_nat);
225 }
226
user_support_remove(struct hub_user * user,int fourcc)227 void user_support_remove(struct hub_user* user, int fourcc)
228 {
229 int feature_mask = convert_support_fourcc(fourcc);
230 user->flags &= ~feature_mask;
231 }
232
user_have_feature_cast_support(struct hub_user * user,char feature[4])233 int user_have_feature_cast_support(struct hub_user* user, char feature[4])
234 {
235 char* tmp;
236 LIST_FOREACH(char*, tmp, user->feature_cast,
237 {
238 if (strncmp(tmp, feature, 4) == 0)
239 return 1;
240 });
241 return 0;
242 }
243
user_set_feature_cast_support(struct hub_user * u,char feature[4])244 int user_set_feature_cast_support(struct hub_user* u, char feature[4])
245 {
246 if (!u->feature_cast)
247 {
248 u->feature_cast = list_create();
249 }
250
251 if (!u->feature_cast)
252 {
253 return 0; /* OOM! */
254 }
255
256 list_append(u->feature_cast, hub_strndup(feature, 4));
257 return 1;
258 }
259
user_clear_feature_cast_support(struct hub_user * u)260 void user_clear_feature_cast_support(struct hub_user* u)
261 {
262 if (u->feature_cast)
263 {
264 list_clear(u->feature_cast, &hub_free);
265 list_destroy(u->feature_cast);
266 u->feature_cast = 0;
267 }
268 }
269
user_is_logged_in(struct hub_user * user)270 int user_is_logged_in(struct hub_user* user)
271 {
272 if (user->state == state_normal)
273 return 1;
274 return 0;
275 }
276
user_is_connecting(struct hub_user * user)277 int user_is_connecting(struct hub_user* user)
278 {
279 if (user->state == state_protocol || user->state == state_identify || user->state == state_verify)
280 return 1;
281 return 0;
282 }
283
user_is_protocol_negotiating(struct hub_user * user)284 int user_is_protocol_negotiating(struct hub_user* user)
285 {
286 if (user->state == state_protocol)
287 return 1;
288 return 0;
289 }
290
user_is_disconnecting(struct hub_user * user)291 int user_is_disconnecting(struct hub_user* user)
292 {
293 if (user->state == state_cleanup || user->state == state_disconnected)
294 return 1;
295 return 0;
296 }
297
user_is_protected(struct hub_user * user)298 int user_is_protected(struct hub_user* user)
299 {
300 return auth_cred_is_protected(user->credentials);
301 }
302
303 /**
304 * Returns 1 if a user is registered.
305 * Only registered users will be let in if the hub is configured for registered
306 * users only.
307 */
user_is_registered(struct hub_user * user)308 int user_is_registered(struct hub_user* user)
309 {
310 return auth_cred_is_registered(user->credentials);
311 }
312
user_net_io_want_write(struct hub_user * user)313 void user_net_io_want_write(struct hub_user* user)
314 {
315 net_con_update(user->connection, NET_EVENT_READ | NET_EVENT_WRITE);
316 }
317
user_net_io_want_read(struct hub_user * user)318 void user_net_io_want_read(struct hub_user* user)
319 {
320 net_con_update(user->connection, NET_EVENT_READ);
321 }
322
user_get_quit_reason_string(enum user_quit_reason reason)323 const char* user_get_quit_reason_string(enum user_quit_reason reason)
324 {
325 switch (reason)
326 {
327 case quit_unknown: return "unknown"; break;
328 case quit_disconnected: return "disconnected"; break;
329 case quit_kicked: return "kicked"; break;
330 case quit_banned: return "banned"; break;
331 case quit_timeout: return "timeout"; break;
332 case quit_send_queue: return "send queue"; break;
333 case quit_memory_error: return "out of memory"; break;
334 case quit_socket_error: return "socket error"; break;
335 case quit_protocol_error: return "protocol error"; break;
336 case quit_logon_error: return "login error"; break;
337 case quit_update_error: return "update error"; break;
338 case quit_hub_disabled: return "hub disabled"; break;
339 case quit_ghost_timeout: return "ghost"; break;
340 }
341
342 return "unknown";
343 }
344
user_get_address(struct hub_user * user)345 const char* user_get_address(struct hub_user* user)
346 {
347 return ip_convert_to_string(&user->id.addr);
348 }
349