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