1 /*
2 * imc module - instant messaging conferencing implementation
3 *
4 * Copyright (C) 2006 Voice Sistem S.R.L.
5 *
6 * This file is part of Kamailio, a free SIP server.
7 *
8 * Kamailio is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
12 *
13 * Kamailio is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 */
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <strings.h>
29
30 #include <sys/types.h>
31 #include "../../core/mem/shm_mem.h"
32 #include "../../core/mem/mem.h"
33 #include "../../core/sr_module.h"
34 #include "../../core/dprint.h"
35 #include "../../core/parser/parse_uri.h"
36 #include "../../core/parser/msg_parser.h"
37
38 #include "imc.h"
39 #include "imc_cmd.h"
40
41 #define ROOMS "Rooms:\n"
42 #define MEMBERS "Members:\n"
43
44 #define PREFIX "*** "
45
46 #define IMC_BUF_SIZE 32768
47 static char imc_body_buf[IMC_BUF_SIZE];
48
49 static str imc_msg_type = { "MESSAGE", 7 };
50
51 static str msg_room_created = STR_STATIC_INIT(PREFIX "Room was created");
52 static str msg_room_destroyed = STR_STATIC_INIT(PREFIX "Room has been destroyed");
53 static str msg_room_not_found = STR_STATIC_INIT(PREFIX "Room not found");
54 static str msg_room_exists = STR_STATIC_INIT(PREFIX "Room already exists");
55 static str msg_leave_error = STR_STATIC_INIT(PREFIX "You are the room's owner and cannot leave. Use #destroy if you wish to destroy the room.");
56 static str msg_room_exists_priv = STR_STATIC_INIT(PREFIX "A private room with the same name already exists");
57 static str msg_room_exists_member = STR_STATIC_INIT(PREFIX "Room already exists and you are a member");
58 static str msg_user_joined = STR_STATIC_INIT(PREFIX "%.*s has joined the room");
59 static str msg_already_joined = STR_STATIC_INIT(PREFIX "You are in the room already");
60 static str msg_user_left = STR_STATIC_INIT(PREFIX "%.*s has left the room");
61 static str msg_join_attempt_bcast = STR_STATIC_INIT(PREFIX "%.*s attempted to join the room");
62 static str msg_join_attempt_ucast = STR_STATIC_INIT(PREFIX "Private rooms are by invitation only. Room owners have been notified.");
63 static str msg_invite = STR_STATIC_INIT(PREFIX "%.*s invites you to join the room (send '%.*saccept' or '%.*sreject')");
64 static str msg_add_reject = STR_STATIC_INIT(PREFIX "You don't have the permmission to add members to this room");
65 #if 0
66 static str msg_rejected = STR_STATIC_INIT(PREFIX "%.*s has rejected invitation");
67 #endif
68 static str msg_user_removed = STR_STATIC_INIT(PREFIX "You have been removed from the room");
69 static str msg_invalid_command = STR_STATIC_INIT(PREFIX "Invalid command '%.*s' (send '%.*shelp' for help)");
70
71 int imc_send_message(str *src, str *dst, str *headers, str *body);
72 int imc_room_broadcast(imc_room_p room, str *ctype, str *body);
73 void imc_inv_callback( struct cell *t, int type, struct tmcb_params *ps);
74
75
76 extern imc_hentry_p _imc_htable;
77 extern int imc_hash_size;
78
79
get_callid(struct sip_msg * msg)80 static str *get_callid(struct sip_msg *msg)
81 {
82 if ((parse_headers(msg, HDR_CALLID_F, 0) != -1)
83 && msg->callid) {
84 return &msg->callid->body;
85 }
86 return NULL;
87 }
88
89
build_headers(struct sip_msg * msg)90 static str *build_headers(struct sip_msg *msg)
91 {
92 static str name = STR_STATIC_INIT("In-Reply-To: ");
93 static char buf[1024];
94 static str rv;
95 str *callid;
96
97 if ((callid = get_callid(msg)) == NULL)
98 return &all_hdrs;
99
100 rv.s = buf;
101 rv.len = all_hdrs.len + name.len + callid->len;
102
103 if (rv.len > sizeof(buf)) {
104 LM_ERR("Header buffer too small for In-Reply-To header\n");
105 return &all_hdrs;
106 }
107
108 memcpy(buf, all_hdrs.s, all_hdrs.len);
109 memcpy(buf + all_hdrs.len, name.s, name.len);
110 memcpy(buf + all_hdrs.len + name.len, callid->s, callid->len);
111 return &rv;
112 }
113
114
format_uri(str uri)115 static str *format_uri(str uri)
116 {
117 static char buf[512];
118 static str rv;
119 struct sip_uri parsed;
120
121 rv.s = NULL;
122 rv.len = 0;
123
124 if (parse_uri(uri.s, uri.len, &parsed) != 0) {
125 LM_ERR("bad uri [%.*s]!\n", STR_FMT(&uri));
126 } else {
127 rv.s = buf;
128 rv.len = snprintf(buf, sizeof(buf), "[%.*s]", STR_FMT(&parsed.user));
129 if (rv.len >= sizeof(buf)) {
130 LM_ERR("Buffer too small\n");
131 rv.len = 0;
132 }
133 }
134 return &rv;
135 }
136
137
138 /*
139 * Given string in value and a parsed URI in template, build a full
140 * URI as follows:
141 * 1) If value has no URI scheme, add sip:
142 * 2) If value has no domain, add domain from template
143 * 3) Use the string in value for the username portion
144 *
145 * This function is intended for converting a URI or number provided
146 * by the user in a command to a full SIP URI. The caller is
147 * responsible for freeing the buffer in res->s which will be
148 * allocated with pkg_malloc.
149 */
build_uri(str * res,str value,struct sip_uri * template)150 static int build_uri(str *res, str value, struct sip_uri *template)
151 {
152 int len = value.len, add_domain = 0, add_scheme = 0;
153
154 if (memchr(value.s, ':', value.len) == NULL) {
155 add_scheme = 1;
156 len += 4; /* sip: */
157 }
158
159 if (memchr(value.s, '@', value.len) == NULL) {
160 add_domain = 1;
161 len += 1 + template->host.len;
162 }
163
164 if ((res->s = (char*)pkg_malloc(len)) == NULL) {
165 LM_ERR("No memory left\n");
166 return -1;
167 }
168 res->len = len;
169 len = 0;
170
171 if (add_scheme) {
172 strcpy(res->
173 s, "sip:");
174 len += 4;
175 }
176
177 memcpy(res->s + len, value.s, value.len);
178 len += value.len;
179
180 if (add_domain) {
181 res->s[len++] = '@';
182 memcpy(res->s + len, template->host.s, template->host.len);
183 }
184 return 0;
185 }
186
187
188 /*
189 * Return a struct imc_uri which contains a SIP URI both in string
190 * form and parsed to components. Calls build_uri internally and then
191 * parses the resulting URI with parse_uri. See the description of
192 * build_uri for more detail on arguments.
193 *
194 * The caller is responsible for pkg_freeing res->uri.s
195 */
build_imc_uri(struct imc_uri * res,str value,struct sip_uri * template)196 static int build_imc_uri(struct imc_uri *res, str value, struct sip_uri *template)
197 {
198 int rc;
199
200 rc = build_uri(&res->uri, value, template);
201 if (rc != 0) return rc;
202
203 if (parse_uri(res->uri.s, res->uri.len, &res->parsed) != 0) {
204 LM_ERR("bad uri [%.*s]!\n", STR_FMT(&res->uri));
205 pkg_free(res->uri.s);
206 res->uri.s = NULL;
207 res->uri.len = 0;
208 return -1;
209 }
210 return 0;
211 }
212
213
214 /**
215 * parse cmd
216 */
imc_parse_cmd(char * buf,int len,imc_cmd_p cmd)217 int imc_parse_cmd(char *buf, int len, imc_cmd_p cmd)
218 {
219 char *p;
220 int i;
221 if(buf==NULL || len<=0 || cmd==NULL)
222 {
223 LM_ERR("invalid parameters\n");
224 return -1;
225 }
226
227 memset(cmd, 0, sizeof(imc_cmd_t));
228 if(buf[0]!=imc_cmd_start_char)
229 {
230 LM_ERR("invalid command [%.*s]\n", len, buf);
231 return -1;
232 }
233 p = &buf[1];
234 cmd->name.s = p;
235 while(*p && p<buf+len)
236 {
237 if(*p==' ' || *p=='\t' || *p=='\r' || *p=='\n')
238 break;
239 p++;
240 }
241 if(cmd->name.s == p)
242 {
243 LM_ERR("no command in [%.*s]\n", len, buf);
244 return -1;
245 }
246 cmd->name.len = p - cmd->name.s;
247
248 /* identify the command */
249 if(cmd->name.len==(sizeof("create")-1)
250 && !strncasecmp(cmd->name.s, "create", cmd->name.len))
251 {
252 cmd->type = IMC_CMDID_CREATE;
253 } else if(cmd->name.len==(sizeof("join")-1)
254 && !strncasecmp(cmd->name.s, "join", cmd->name.len)) {
255 cmd->type = IMC_CMDID_JOIN;
256 } else if(cmd->name.len==(sizeof("invite")-1)
257 && !strncasecmp(cmd->name.s, "invite", cmd->name.len)) {
258 cmd->type = IMC_CMDID_INVITE;
259 } else if(cmd->name.len==(sizeof("add")-1)
260 && !strncasecmp(cmd->name.s, "add", cmd->name.len)) {
261 cmd->type = IMC_CMDID_ADD;
262 } else if(cmd->name.len==(sizeof("accept")-1)
263 && !strncasecmp(cmd->name.s, "accept", cmd->name.len)) {
264 cmd->type = IMC_CMDID_ACCEPT;
265 } else if(cmd->name.len==(sizeof("reject")-1)
266 && !strncasecmp(cmd->name.s, "reject", cmd->name.len)) {
267 cmd->type = IMC_CMDID_REJECT;
268 } else if(cmd->name.len==(sizeof("deny")-1)
269 && !strncasecmp(cmd->name.s, "deny", cmd->name.len)) {
270 cmd->type = IMC_CMDID_REJECT;
271 } else if(cmd->name.len==(sizeof("remove")-1)
272 && !strncasecmp(cmd->name.s, "remove", cmd->name.len)) {
273 cmd->type = IMC_CMDID_REMOVE;
274 } else if(cmd->name.len==(sizeof("leave")-1)
275 && !strncasecmp(cmd->name.s, "leave", cmd->name.len)) {
276 cmd->type = IMC_CMDID_LEAVE;
277 } else if(cmd->name.len==(sizeof("exit")-1)
278 && !strncasecmp(cmd->name.s, "exit", cmd->name.len)) {
279 cmd->type = IMC_CMDID_LEAVE;
280 } else if(cmd->name.len==(sizeof("members")-1)
281 && !strncasecmp(cmd->name.s, "members", cmd->name.len)) {
282 cmd->type = IMC_CMDID_MEMBERS;
283 } else if(cmd->name.len==(sizeof("rooms")-1)
284 && !strncasecmp(cmd->name.s, "rooms", cmd->name.len)) {
285 cmd->type = IMC_CMDID_ROOMS;
286 } else if(cmd->name.len==(sizeof("list")-1)
287 && !strncasecmp(cmd->name.s, "list", cmd->name.len)) {
288 cmd->type = IMC_CMDID_MEMBERS;
289 } else if(cmd->name.len==(sizeof("destroy")-1)
290 && !strncasecmp(cmd->name.s, "destroy", cmd->name.len)) {
291 cmd->type = IMC_CMDID_DESTROY;
292 } else if(cmd->name.len==(sizeof("help")-1)
293 && !strncasecmp(cmd->name.s, "help", cmd->name.len)) {
294 cmd->type = IMC_CMDID_HELP;
295 goto done;
296 } else {
297 cmd->type = IMC_CMDID_UNKNOWN;
298 goto done;
299 }
300
301
302 if(*p=='\0' || p>=buf+len)
303 goto done;
304
305 i=0;
306 do {
307 while(p<buf+len && (*p==' ' || *p=='\t'))
308 p++;
309 if(p>=buf+len || *p=='\0' || *p=='\r' || *p=='\n')
310 goto done;
311 cmd->param[i].s = p;
312 while(p<buf+len)
313 {
314 if(*p=='\0' || *p==' ' || *p=='\t' || *p=='\r' || *p=='\n')
315 break;
316 p++;
317 }
318 cmd->param[i].len = p - cmd->param[i].s;
319 i++;
320 if(i>=IMC_CMD_MAX_PARAM)
321 break;
322 } while(1);
323
324 done:
325 LM_DBG("command: [%.*s]\n", STR_FMT(&cmd->name));
326 for(i=0; i<IMC_CMD_MAX_PARAM; i++)
327 {
328 if(cmd->param[i].len<=0)
329 break;
330 LM_DBG("parameter %d=[%.*s]\n", i, STR_FMT(&cmd->param[i]));
331 }
332 return 0;
333 }
334
335
336
imc_handle_create(struct sip_msg * msg,imc_cmd_t * cmd,struct imc_uri * src,struct imc_uri * dst)337 int imc_handle_create(struct sip_msg* msg, imc_cmd_t *cmd,
338 struct imc_uri *src, struct imc_uri *dst)
339 {
340 int rv = -1;
341 imc_room_p rm = 0;
342 imc_member_p member = 0;
343 int flag_room = 0;
344 int flag_member = 0;
345 str body;
346 struct imc_uri room;
347 int params = 0;
348 str rs = STR_NULL, ps = STR_NULL;
349
350 memset(&room, '\0', sizeof(room));
351
352 if (cmd->param[0].s) {
353 params++;
354 if (cmd->param[1].s) {
355 params++;
356 }
357 }
358
359 switch(params) {
360 case 0:
361 /* With no parameter, use To for the room uri and create a public room */
362 break;
363
364 case 1:
365 /* With one parameter, if the value is "private", it indicates
366 * a private room, otherwise it is the URI of the room and we
367 * create a public room. */
368 if (cmd->param[0].len == IMC_ROOM_PRIVATE_LEN
369 && !strncasecmp(cmd->param[0].s, IMC_ROOM_PRIVATE,
370 cmd->param[0].len)) {
371 ps = cmd->param[0];
372 } else {
373 rs = cmd->param[0];
374 }
375 break;
376
377 case 2:
378 /* With two parameters, the first parameter is room URI and
379 * the second parameter must be "private". */
380 rs = cmd->param[0];
381 ps = cmd->param[1];
382 break;
383
384 default:
385 LM_ERR("Invalid number of parameters %d\n", params);
386 goto error;
387 }
388
389 if (build_imc_uri(&room, rs.s ? rs : dst->parsed.user, &dst->parsed) != 0)
390 goto error;
391
392 if (ps.s) {
393 if (ps.len == IMC_ROOM_PRIVATE_LEN
394 && !strncasecmp(ps.s, IMC_ROOM_PRIVATE, ps.len)) {
395 flag_room |= IMC_ROOM_PRIV;
396 LM_DBG("Room with private flag on\n");
397 } else {
398 LM_ERR("Second argument to command 'create' must be string 'private'\n");
399 goto error;
400 }
401 }
402
403 rm = imc_get_room(&room.parsed.user, &room.parsed.host);
404 if (rm == NULL) {
405 LM_DBG("Creating new room [%.*s]\n", STR_FMT(&room.uri));
406
407 rm = imc_add_room(&room.parsed.user, &room.parsed.host, flag_room);
408 if (rm == NULL) {
409 LM_ERR("Failed to add new room\n");
410 goto error;
411 }
412 LM_DBG("Added room [%.*s]\n", STR_FMT(&rm->uri));
413
414 flag_member |= IMC_MEMBER_OWNER;
415 /* adding the owner as the first member*/
416 member = imc_add_member(rm, &src->parsed.user, &src->parsed.host, flag_member);
417 if (member == NULL) {
418 LM_ERR("failed to add owner [%.*s]\n", STR_FMT(&src->uri));
419 goto error;
420 }
421 LM_DBG("Added [%.*s] as the first member in room [%.*s]\n",
422 STR_FMT(&member->uri), STR_FMT(&rm->uri));
423
424 imc_send_message(&rm->uri, &member->uri, build_headers(msg), &msg_room_created);
425 goto done;
426 }
427
428 LM_DBG("Room [%.*s] already exists\n", STR_FMT(&rm->uri));
429
430 if (imc_check_on_create) {
431 imc_send_message(&dst->uri, &src->uri, build_headers(msg), &msg_room_exists);
432 goto done;
433 }
434
435 if (rm->flags & IMC_ROOM_PRIV) {
436 imc_send_message(&dst->uri, &src->uri, build_headers(msg), &msg_room_exists_priv);
437 goto done;
438 }
439
440 LM_DBG("Checking if user [%.*s] is a member\n", STR_FMT(&src->uri));
441 member = imc_get_member(rm, &src->parsed.user, &src->parsed.host);
442
443 if (member) {
444 imc_send_message(&dst->uri, &src->uri, build_headers(msg), &msg_room_exists_member);
445 goto done;
446 }
447
448 member = imc_add_member(rm, &src->parsed.user, &src->parsed.host, flag_member);
449 if (member == NULL) {
450 LM_ERR("Failed to add member [%.*s]\n", STR_FMT(&src->uri));
451 goto error;
452 }
453 LM_DBG("Added [%.*s] as member to room [%.*s]\n", STR_FMT(&member->uri),
454 STR_FMT(&rm->uri));
455
456 body.s = imc_body_buf;
457 body.len = snprintf(body.s, sizeof(imc_body_buf), msg_user_joined.s,
458 STR_FMT(format_uri(member->uri)));
459
460 if (body.len < 0) {
461 LM_ERR("Error while building response\n");
462 goto error;
463 }
464
465 if (body.len > 0)
466 imc_room_broadcast(rm, build_headers(msg), &body);
467
468 if (body.len >= sizeof(imc_body_buf))
469 LM_ERR("Truncated message '%.*s'\n", STR_FMT(&body));
470
471 done:
472 rv = 0;
473 error:
474 if (room.uri.s) pkg_free(room.uri.s);
475 if (rm != NULL) imc_release_room(rm);
476 return rv;
477 }
478
479
imc_handle_join(struct sip_msg * msg,imc_cmd_t * cmd,struct imc_uri * src,struct imc_uri * dst)480 int imc_handle_join(struct sip_msg* msg, imc_cmd_t *cmd,
481 struct imc_uri *src, struct imc_uri *dst)
482 {
483 int rv = -1;
484 imc_room_p rm = 0;
485 imc_member_p member = 0;
486 int flag_room = 0;
487 int flag_member = 0;
488 str body;
489 struct imc_uri room;
490
491 if(cmd==NULL || src==NULL || dst==NULL) {
492 return -1;
493 }
494
495 memset(&room, '\0', sizeof(room));
496 if (build_imc_uri(&room, cmd->param[0].s ? cmd->param[0] : dst->parsed.user, &dst->parsed))
497 goto error;
498
499 rm = imc_get_room(&room.parsed.user, &room.parsed.host);
500 if (rm == NULL || (rm->flags & IMC_ROOM_DELETED)) {
501 LM_DBG("Room [%.*s] not found\n", STR_FMT(&room.uri));
502
503 if (!imc_create_on_join) {
504 imc_send_message(&dst->uri, &src->uri, build_headers(msg), &msg_room_not_found);
505 goto done;
506 }
507
508 LM_DBG("Creating room [%.*s]\n", STR_FMT(&room.uri));
509 rm = imc_add_room(&room.parsed.user, &room.parsed.host, flag_room);
510 if (rm == NULL) {
511 LM_ERR("Failed to add new room [%.*s]\n", STR_FMT(&room.uri));
512 goto error;
513 }
514 LM_DBG("Created a new room [%.*s]\n", STR_FMT(&rm->uri));
515 flag_member |= IMC_MEMBER_OWNER;
516 member = imc_add_member(rm, &src->parsed.user, &src->parsed.host, flag_member);
517 if (member == NULL) {
518 LM_ERR("Failed to add new member [%.*s]\n", STR_FMT(&src->uri));
519 goto error;
520 }
521 /* send info message */
522 imc_send_message(&rm->uri, &member->uri, build_headers(msg), &msg_room_created);
523 goto done;
524 }
525
526 LM_DBG("Found room [%.*s]\n", STR_FMT(&rm->uri));
527
528 member = imc_get_member(rm, &src->parsed.user, &src->parsed.host);
529 if (member && !(member->flags & IMC_MEMBER_DELETED)) {
530 LM_DBG("User [%.*s] is already in the room\n", STR_FMT(&member->uri));
531 imc_send_message(&rm->uri, &member->uri, build_headers(msg), &msg_already_joined);
532 goto done;
533 }
534
535 body.s = imc_body_buf;
536 if (!(rm->flags & IMC_ROOM_PRIV)) {
537 LM_DBG("adding new member [%.*s]\n", STR_FMT(&src->uri));
538 member = imc_add_member(rm, &src->parsed.user, &src->parsed.host, flag_member);
539 if (member == NULL) {
540 LM_ERR("Failed to add new user [%.*s]\n", STR_FMT(&src->uri));
541 goto error;
542 }
543
544 body.len = snprintf(body.s, sizeof(imc_body_buf), msg_user_joined.s,
545 STR_FMT(format_uri(src->uri)));
546 } else {
547 LM_DBG("Attept to join private room [%.*s] by [%.*s]\n",
548 STR_FMT(&rm->uri), STR_FMT(&src->uri));
549
550 body.len = snprintf(body.s, sizeof(imc_body_buf), msg_join_attempt_bcast.s,
551 STR_FMT(format_uri(src->uri)));
552 imc_send_message(&rm->uri, &src->uri, build_headers(msg), &msg_join_attempt_ucast);
553 }
554
555 if (body.len < 0) {
556 LM_ERR("Error while building response\n");
557 goto error;
558 }
559
560 if (body.len > 0)
561 imc_room_broadcast(rm, build_headers(msg), &body);
562
563 if (body.len >= sizeof(imc_body_buf))
564 LM_ERR("Truncated message '%.*s'\n", STR_FMT(&body));
565
566 done:
567 if (member != NULL && (member->flags & IMC_MEMBER_INVITED))
568 member->flags &= ~IMC_MEMBER_INVITED;
569
570 rv = 0;
571 error:
572 if (room.uri.s != NULL) pkg_free(room.uri.s);
573 if (rm != NULL) imc_release_room(rm);
574 return rv;
575 }
576
577
imc_handle_invite(struct sip_msg * msg,imc_cmd_t * cmd,struct imc_uri * src,struct imc_uri * dst)578 int imc_handle_invite(struct sip_msg* msg, imc_cmd_t *cmd,
579 struct imc_uri *src, struct imc_uri *dst)
580 {
581 int rv = -1;
582 imc_room_p rm = 0;
583 imc_member_p member = 0;
584 int flag_member = 0;
585 str body;
586 del_member_t *cback_param = NULL;
587 int result;
588 uac_req_t uac_r;
589 struct imc_uri user, room;
590
591 memset(&user, '\0', sizeof(user));
592 memset(&room, '\0', sizeof(room));
593
594 if (cmd->param[0].s == NULL) {
595 LM_INFO("Invite command with missing argument from [%.*s]\n", STR_FMT(&src->uri));
596 goto error;
597 }
598
599 if (build_imc_uri(&user, cmd->param[0], &dst->parsed))
600 goto error;
601
602 if (build_imc_uri(&room, cmd->param[1].s ? cmd->param[1] : dst->parsed.user, &dst->parsed))
603 goto error;
604
605 rm = imc_get_room(&room.parsed.user, &room.parsed.host);
606 if (rm == NULL || (rm->flags & IMC_ROOM_DELETED)) {
607 LM_ERR("Room [%.*s] does not exist!\n", STR_FMT(&room.uri));
608 goto error;
609 }
610 member = imc_get_member(rm, &src->parsed.user, &src->parsed.host);
611
612 if (member == NULL) {
613 LM_ERR("User [%.*s] is not member of room [%.*s]!\n",
614 STR_FMT(&src->uri), STR_FMT(&room.uri));
615 goto error;
616 }
617
618 if (!(member->flags & IMC_MEMBER_OWNER) &&
619 !(member->flags & IMC_MEMBER_ADMIN)) {
620 LM_ERR("User [%.*s] has no right to invite others!\n", STR_FMT(&member->uri));
621 goto error;
622 }
623
624 member = imc_get_member(rm, &user.parsed.user, &user.parsed.host);
625 if (member != NULL) {
626 LM_ERR("User [%.*s] is already in room [%.*s]!\n", STR_FMT(&member->uri), STR_FMT(&rm->uri));
627 goto error;
628 }
629
630 flag_member |= IMC_MEMBER_INVITED;
631 member = imc_add_member(rm, &user.parsed.user, &user.parsed.host, flag_member);
632 if (member == NULL) {
633 LM_ERR("Adding member [%.*s] failed\n", STR_FMT(&user.uri));
634 goto error;
635 }
636
637 body.s = imc_body_buf;
638 body.len = snprintf(body.s, sizeof(imc_body_buf), msg_invite.s, STR_FMT(format_uri(src->uri)),
639 STR_FMT(&imc_cmd_start_str), STR_FMT(&imc_cmd_start_str));
640
641 if (body.len < 0) {
642 LM_ERR("Error while building response\n");
643 goto error;
644 }
645
646 LM_DBG("to=[%.*s]\nfrom=[%.*s]\nbody=[%.*s]\n",
647 STR_FMT(&member->uri), STR_FMT(&rm->uri), STR_FMT(&body));
648
649 if (body.len >= sizeof(imc_body_buf))
650 LM_ERR("Truncated message '%.*s'\n", STR_FMT(&body));
651
652 if ((cback_param = (del_member_t*)shm_malloc(sizeof(del_member_t))) == NULL) {
653 LM_ERR("No shared memory left\n");
654 goto error;
655 }
656 memset(cback_param, 0, sizeof(del_member_t));
657 cback_param->room_name = rm->name;
658 cback_param->room_domain = rm->domain;
659 cback_param->member_name = member->user;
660 cback_param->member_domain = member->domain;
661 cback_param->inv_uri = member->uri;
662 /*?!?! possible race with 'remove user' */
663
664 set_uac_req(&uac_r, &imc_msg_type, build_headers(msg), &body, 0, TMCB_LOCAL_COMPLETED,
665 imc_inv_callback, (void*)(cback_param));
666 result = tmb.t_request(&uac_r,
667 &member->uri, /* Request-URI */
668 &member->uri, /* To */
669 &rm->uri, /* From */
670 (outbound_proxy.s) ? &outbound_proxy : NULL/* outbound proxy*/
671 );
672 if (result < 0) {
673 LM_ERR("Error in tm send request\n");
674 shm_free(cback_param);
675 goto error;
676 }
677
678 rv = 0;
679 error:
680 if (user.uri.s != NULL) pkg_free(user.uri.s);
681 if (room.uri.s != NULL) pkg_free(room.uri.s);
682 if (rm != NULL) imc_release_room(rm);
683 return rv;
684 }
685
686
imc_handle_add(struct sip_msg * msg,imc_cmd_t * cmd,struct imc_uri * src,struct imc_uri * dst)687 int imc_handle_add(struct sip_msg* msg, imc_cmd_t *cmd,
688 struct imc_uri *src, struct imc_uri *dst)
689 {
690 int rv = -1;
691 imc_room_p rm = 0;
692 imc_member_p member = 0;
693 str body;
694 struct imc_uri user, room;
695
696 memset(&user, '\0', sizeof(user));
697 memset(&room, '\0', sizeof(room));
698
699 if (cmd->param[0].s == NULL) {
700 LM_INFO("Add command with missing argument from [%.*s]\n", STR_FMT(&src->uri));
701 goto error;
702 }
703
704 if (build_imc_uri(&user, cmd->param[0], &dst->parsed))
705 goto error;
706
707 if (build_imc_uri(&room, cmd->param[1].s ? cmd->param[1] : dst->parsed.user, &dst->parsed))
708 goto error;
709
710 rm = imc_get_room(&room.parsed.user, &room.parsed.host);
711 if (rm == NULL || (rm->flags & IMC_ROOM_DELETED)) {
712 LM_ERR("Room [%.*s] does not exist!\n", STR_FMT(&room.uri));
713 goto error;
714 }
715 member = imc_get_member(rm, &src->parsed.user, &src->parsed.host);
716
717 if (member == NULL) {
718 LM_ERR("User [%.*s] is not member of room [%.*s]!\n",
719 STR_FMT(&src->uri), STR_FMT(&room.uri));
720 goto error;
721 }
722
723 if (!(member->flags & IMC_MEMBER_OWNER) &&
724 !(member->flags & IMC_MEMBER_ADMIN)) {
725 LM_ERR("User [%.*s] has no right to add others!\n", STR_FMT(&member->uri));
726 imc_send_message(&rm->uri, &member->uri, build_headers(msg), &msg_add_reject);
727 goto done;
728 }
729
730 member = imc_get_member(rm, &user.parsed.user, &user.parsed.host);
731 if (member != NULL) {
732 LM_ERR("User [%.*s] is already in room [%.*s]!\n", STR_FMT(&member->uri), STR_FMT(&rm->uri));
733 goto error;
734 }
735
736 member = imc_add_member(rm, &user.parsed.user, &user.parsed.host, 0);
737 if (member == NULL) {
738 LM_ERR("Adding member [%.*s] failed\n", STR_FMT(&user.uri));
739 goto error;
740 }
741
742 body.s = imc_body_buf;
743 body.len = snprintf(body.s, sizeof(imc_body_buf), msg_user_joined.s, STR_FMT(format_uri(member->uri)));
744
745 if (body.len < 0) {
746 LM_ERR("Error while building response\n");
747 goto error;
748 }
749
750 if (body.len > 0)
751 imc_room_broadcast(rm, build_headers(msg), &body);
752
753 if (body.len >= sizeof(imc_body_buf))
754 LM_ERR("Truncated message '%.*s'\n", STR_FMT(&body));
755
756 done:
757 rv = 0;
758 error:
759 if (user.uri.s != NULL) pkg_free(user.uri.s);
760 if (room.uri.s != NULL) pkg_free(room.uri.s);
761 if (rm != NULL) imc_release_room(rm);
762 return rv;
763 }
764
765
imc_handle_accept(struct sip_msg * msg,imc_cmd_t * cmd,struct imc_uri * src,struct imc_uri * dst)766 int imc_handle_accept(struct sip_msg* msg, imc_cmd_t *cmd,
767 struct imc_uri *src, struct imc_uri *dst)
768 {
769 int rv = -1;
770 imc_room_p rm = 0;
771 imc_member_p member = 0;
772 str body;
773 struct imc_uri room;
774
775 memset(&room, '\0', sizeof(room));
776
777 if (build_imc_uri(&room, cmd->param[0].s ? cmd->param[0] : dst->parsed.user, &dst->parsed))
778 goto error;
779
780 rm = imc_get_room(&room.parsed.user, &room.parsed.host);
781 if (rm == NULL || (rm->flags & IMC_ROOM_DELETED)) {
782 LM_ERR("Room [%.*s] does not exist!\n", STR_FMT(&room.uri));
783 goto error;
784 }
785
786 /* if aready invited add as a member */
787 member = imc_get_member(rm, &src->parsed.user, &src->parsed.host);
788 if (member == NULL || !(member->flags & IMC_MEMBER_INVITED)) {
789 LM_ERR("User [%.*s] not invited to the room!\n", STR_FMT(&src->uri));
790 goto error;
791 }
792
793 member->flags &= ~IMC_MEMBER_INVITED;
794
795 body.s = imc_body_buf;
796 body.len = snprintf(body.s, sizeof(imc_body_buf), msg_user_joined.s, STR_FMT(format_uri(member->uri)));
797
798 if (body.len < 0) {
799 LM_ERR("Error while building response\n");
800 goto error;
801 }
802
803 if (body.len > 0)
804 imc_room_broadcast(rm, build_headers(msg), &body);
805
806 if (body.len >= sizeof(imc_body_buf))
807 LM_ERR("Truncated message '%.*s'\n", STR_FMT(&body));
808
809 rv = 0;
810 error:
811 if (room.uri.s != NULL) pkg_free(room.uri.s);
812 if (rm != NULL) imc_release_room(rm);
813 return rv;
814 }
815
816
imc_handle_remove(struct sip_msg * msg,imc_cmd_t * cmd,struct imc_uri * src,struct imc_uri * dst)817 int imc_handle_remove(struct sip_msg* msg, imc_cmd_t *cmd,
818 struct imc_uri *src, struct imc_uri *dst)
819 {
820 int rv = -1;
821 imc_room_p rm = 0;
822 imc_member_p member = 0;
823 str body;
824 struct imc_uri user, room;
825
826 memset(&user, '\0', sizeof(user));
827 memset(&room, '\0', sizeof(room));
828
829 if (build_imc_uri(&user, cmd->param[0], &dst->parsed))
830 goto error;
831
832 if (build_imc_uri(&room, cmd->param[1].s ? cmd->param[1] : dst->parsed.user, &dst->parsed))
833 goto error;
834
835 rm = imc_get_room(&room.parsed.user, &room.parsed.host);
836 if (rm == NULL || (rm->flags & IMC_ROOM_DELETED)) {
837 LM_ERR("Room [%.*s] does not exist!\n", STR_FMT(&room.uri));
838 goto error;
839 }
840
841 /* verify if the user who sent the request is a member in the room
842 * and has the right to remove other users */
843 member = imc_get_member(rm, &src->parsed.user, &src->parsed.host);
844 if (member == NULL) {
845 LM_ERR("User [%.*s] is not member of room [%.*s]!\n",
846 STR_FMT(&src->uri), STR_FMT(&rm->uri));
847 goto error;
848 }
849
850 if (!(member->flags & IMC_MEMBER_OWNER) && !(member->flags & IMC_MEMBER_ADMIN)) {
851 LM_ERR("User [%.*s] has no right to remove from room [%.*s]!\n",
852 STR_FMT(&src->uri), STR_FMT(&rm->uri));
853 goto error;
854 }
855
856 /* verify if the user that is to be removed is a member of the room */
857 member = imc_get_member(rm, &user.parsed.user, &user.parsed.host);
858 if (member == NULL) {
859 LM_ERR("User [%.*s] is not member of room [%.*s]!\n",
860 STR_FMT(&user.uri), STR_FMT(&rm->uri));
861 goto error;
862 }
863
864 if (member->flags & IMC_MEMBER_OWNER) {
865 LM_ERR("User [%.*s] is owner of room [%.*s] and cannot be removed!\n",
866 STR_FMT(&member->uri), STR_FMT(&rm->uri));
867 goto error;
868 }
869
870 LM_DBG("to: [%.*s]\nfrom: [%.*s]\nbody: [%.*s]\n",
871 STR_FMT(&member->uri) , STR_FMT(&rm->uri),
872 STR_FMT(&msg_user_removed));
873 imc_send_message(&rm->uri, &member->uri, build_headers(msg), &msg_user_removed);
874
875 member->flags |= IMC_MEMBER_DELETED;
876 imc_del_member(rm, &user.parsed.user, &user.parsed.host);
877
878 body.s = imc_body_buf;
879 body.len = snprintf(body.s, sizeof(imc_body_buf), msg_user_left.s, STR_FMT(format_uri(member->uri)));
880
881 if (body.len < 0) {
882 LM_ERR("Error while building response\n");
883 goto error;
884 }
885
886 if (body.len > 0)
887 imc_room_broadcast(rm, build_headers(msg), &body);
888
889 if (body.len >= sizeof(imc_body_buf))
890 LM_ERR("Truncated message '%.*s'\n", STR_FMT(&body));
891
892 rv = 0;
893 error:
894 if (user.uri.s != NULL) pkg_free(user.uri.s);
895 if (room.uri.s != NULL) pkg_free(room.uri.s);
896 if (rm != NULL) imc_release_room(rm);
897 return rv;
898 }
899
900
imc_handle_reject(struct sip_msg * msg,imc_cmd_t * cmd,struct imc_uri * src,struct imc_uri * dst)901 int imc_handle_reject(struct sip_msg* msg, imc_cmd_t *cmd,
902 struct imc_uri *src, struct imc_uri *dst)
903 {
904 int rv = -1;
905 imc_room_p rm = 0;
906 imc_member_p member = 0;
907 struct imc_uri room;
908
909 memset(&room, '\0', sizeof(room));
910 if (build_imc_uri(&room, cmd->param[0].s ? cmd->param[0] : dst->parsed.user, &dst->parsed))
911 goto error;
912
913 rm = imc_get_room(&room.parsed.user, &room.parsed.host);
914 if (rm == NULL || (rm->flags & IMC_ROOM_DELETED)) {
915 LM_ERR("Room [%.*s] does not exist!\n", STR_FMT(&room.uri));
916 goto error;
917 }
918
919 /* If the user is an invited member, delete it from the list */
920 member = imc_get_member(rm, &src->parsed.user, &src->parsed.host);
921 if (member == NULL || !(member->flags & IMC_MEMBER_INVITED)) {
922 LM_ERR("User [%.*s] was not invited to room [%.*s]!\n",
923 STR_FMT(&src->uri), STR_FMT(&rm->uri));
924 goto error;
925 }
926
927 #if 0
928 body.s = imc_body_buf;
929 body.len = snprintf(body.s, sizeof(imc_body_buf), msg_rejected.s, STR_FMT(format_uri(src->uri)));
930 if (body.len > 0)
931 imc_send_message(&rm->uri, &member->uri, build_headers(msg), &body);
932 #endif
933
934 LM_DBG("User [%.*s] rejected invitation to room [%.*s]!\n",
935 STR_FMT(&src->uri), STR_FMT(&rm->uri));
936
937 imc_del_member(rm, &src->parsed.user, &src->parsed.host);
938
939 rv = 0;
940 error:
941 if (room.uri.s != NULL) pkg_free(room.uri.s);
942 if (rm != NULL) imc_release_room(rm);
943 return rv;
944 }
945
946
imc_handle_members(struct sip_msg * msg,imc_cmd_t * cmd,struct imc_uri * src,struct imc_uri * dst)947 int imc_handle_members(struct sip_msg* msg, imc_cmd_t *cmd,
948 struct imc_uri *src, struct imc_uri *dst)
949 {
950 int rv = -1;
951 imc_room_p rm = 0;
952 imc_member_p member = 0;
953 imc_member_p imp = 0;
954 str body, *name;
955 char *p;
956 size_t left;
957 struct imc_uri room;
958
959 memset(&room, '\0', sizeof(room));
960 if (build_imc_uri(&room, cmd->param[0].s ? cmd->param[0] : dst->parsed.user,
961 &dst->parsed)) {
962 goto done;
963 }
964
965 rm = imc_get_room(&room.parsed.user, &room.parsed.host);
966 if (rm == NULL || (rm->flags & IMC_ROOM_DELETED)) {
967 LM_ERR("Room [%.*s] does not exist!\n", STR_FMT(&room.uri));
968 goto done;
969 }
970
971 /* verify if the user is a member of the room */
972 member = imc_get_member(rm, &src->parsed.user, &src->parsed.host);
973 if (member == NULL) {
974 LM_ERR("User [%.*s] is not member of room [%.*s]!\n",
975 STR_FMT(&src->uri), STR_FMT(&rm->uri));
976 goto done;
977 }
978
979 p = imc_body_buf;
980 imc_body_buf[IMC_BUF_SIZE - 1] = '\0';
981 left = sizeof(imc_body_buf) - 1;
982
983 memcpy(p, MEMBERS, sizeof(MEMBERS) - 1);
984 p += sizeof(MEMBERS) - 1;
985 left -= sizeof(MEMBERS) - 1;
986
987 imp = rm->members;
988 while (imp) {
989 if ((imp->flags & IMC_MEMBER_INVITED) || (imp->flags & IMC_MEMBER_DELETED)
990 || (imp->flags & IMC_MEMBER_SKIP)) {
991 imp = imp->next;
992 continue;
993 }
994
995 if (imp->flags & IMC_MEMBER_OWNER) {
996 if (left < 2) goto overrun;
997 *p++ = '*';
998 left--;
999 } else if (imp->flags & IMC_MEMBER_ADMIN) {
1000 if (left < 2) goto overrun;
1001 *p++ = '~';
1002 left--;
1003 }
1004
1005 name = format_uri(imp->uri);
1006 if (left < name->len + 1) goto overrun;
1007 strncpy(p, name->s, name->len);
1008 p += name->len;
1009 left -= name->len;
1010
1011 if (left < 2) goto overrun;
1012 *p++ = '\n';
1013 left--;
1014
1015 imp = imp->next;
1016 }
1017
1018 /* write over last '\n' */
1019 *(--p) = 0;
1020 body.s = imc_body_buf;
1021 body.len = p - body.s;
1022
1023 LM_DBG("members = '%.*s'\n", STR_FMT(&body));
1024 LM_DBG("Message-ID: '%.*s'\n", STR_FMT(get_callid(msg)));
1025 imc_send_message(&rm->uri, &member->uri, build_headers(msg), &body);
1026
1027 rv = 0;
1028 goto done;
1029
1030 overrun:
1031 LM_ERR("Buffer too small for member list message\n");
1032
1033 done:
1034 if (room.uri.s != NULL) pkg_free(room.uri.s);
1035 if (rm != NULL) imc_release_room(rm);
1036 return rv;
1037 }
1038
1039
imc_handle_rooms(struct sip_msg * msg,imc_cmd_t * cmd,struct imc_uri * src,struct imc_uri * dst)1040 int imc_handle_rooms(struct sip_msg* msg, imc_cmd_t *cmd,
1041 struct imc_uri *src, struct imc_uri *dst)
1042 {
1043 int i, rv = -1;
1044 imc_room_p room;
1045 str body, *name;
1046 char *p;
1047 size_t left;
1048
1049 p = imc_body_buf;
1050 left = sizeof(imc_body_buf) - 2;
1051
1052 memcpy(p, ROOMS, sizeof(ROOMS) - 1);
1053 p += sizeof(ROOMS) - 1;
1054 left -= sizeof(ROOMS) - 1;
1055
1056 for (i = 0; i < imc_hash_size; i++) {
1057 lock_get(&_imc_htable[i].lock);
1058 for (room = _imc_htable[i].rooms; room != NULL ; room = room->next) {
1059 if (room->flags & IMC_ROOM_DELETED) continue;
1060
1061 name = format_uri(room->uri);
1062 if (left < name->len) {
1063 lock_release(&_imc_htable[i].lock);
1064 goto error;
1065 }
1066 strncpy(p, name->s, name->len);
1067 p += name->len;
1068 left -= name->len;
1069
1070 if (left < 1) {
1071 lock_release(&_imc_htable[i].lock);
1072 goto error;
1073 }
1074 *p++ = '\n';
1075 left--;
1076 }
1077 lock_release(&_imc_htable[i].lock);
1078 }
1079
1080 /* write over last '\n' */
1081 *(--p) = 0;
1082 body.s = imc_body_buf;
1083 body.len = p - body.s;
1084
1085 LM_DBG("rooms = '%.*s'\n", STR_FMT(&body));
1086 imc_send_message(&dst->uri, &src->uri, build_headers(msg), &body);
1087
1088 return 0;
1089
1090 error:
1091 LM_ERR("Buffer too small for member list message\n");
1092 return rv;
1093 }
1094
1095
imc_handle_leave(struct sip_msg * msg,imc_cmd_t * cmd,struct imc_uri * src,struct imc_uri * dst)1096 int imc_handle_leave(struct sip_msg* msg, imc_cmd_t *cmd,
1097 struct imc_uri *src, struct imc_uri *dst)
1098 {
1099 int rv = -1;
1100 imc_room_p rm = 0;
1101 imc_member_p member = 0;
1102 str body;
1103 struct imc_uri room;
1104
1105 memset(&room, '\0', sizeof(room));
1106 if (build_imc_uri(&room, cmd->param[0].s ? cmd->param[0] : dst->parsed.user, &dst->parsed))
1107 goto error;
1108
1109 rm = imc_get_room(&room.parsed.user, &room.parsed.host);
1110 if (rm == NULL || (rm->flags & IMC_ROOM_DELETED)) {
1111 LM_ERR("Room [%.*s] does not exist!\n", STR_FMT(&room.uri));
1112 goto error;
1113 }
1114
1115 /* verify if the user is a member of the room */
1116 member = imc_get_member(rm, &src->parsed.user, &src->parsed.host);
1117 if (member == NULL) {
1118 LM_ERR("User [%.*s] is not member of room [%.*s]!\n",
1119 STR_FMT(&src->uri), STR_FMT(&rm->uri));
1120 goto error;
1121 }
1122
1123 if (member->flags & IMC_MEMBER_OWNER) {
1124 imc_send_message(&rm->uri, &member->uri, build_headers(msg), &msg_leave_error);
1125 goto done;
1126 }
1127
1128 body.s = imc_body_buf;
1129 body.len = snprintf(body.s, sizeof(imc_body_buf), msg_user_left.s, STR_FMT(format_uri(member->uri)));
1130
1131 if (body.len < 0) {
1132 LM_ERR("Error while building response\n");
1133 goto error;
1134 }
1135
1136 if (body.len > 0)
1137 imc_room_broadcast(rm, build_headers(msg), &body);
1138
1139 if (body.len >= sizeof(imc_body_buf))
1140 LM_ERR("Truncated message '%.*s'\n", STR_FMT(&body));
1141
1142 member->flags |= IMC_MEMBER_DELETED;
1143 imc_del_member(rm, &src->parsed.user, &src->parsed.host);
1144
1145 done:
1146 rv = 0;
1147 error:
1148 if (room.uri.s != NULL) pkg_free(room.uri.s);
1149 if (rm != NULL) imc_release_room(rm);
1150 return rv;
1151 }
1152
1153
imc_handle_destroy(struct sip_msg * msg,imc_cmd_t * cmd,struct imc_uri * src,struct imc_uri * dst)1154 int imc_handle_destroy(struct sip_msg* msg, imc_cmd_t *cmd,
1155 struct imc_uri *src, struct imc_uri *dst)
1156 {
1157 int rv = -1;
1158 imc_room_p rm = 0;
1159 imc_member_p member = 0;
1160 struct imc_uri room;
1161
1162 memset(&room, '\0', sizeof(room));
1163 if (build_imc_uri(&room, cmd->param[0].s ? cmd->param[0] : dst->parsed.user, &dst->parsed))
1164 goto error;
1165
1166 rm = imc_get_room(&room.parsed.user, &room.parsed.host);
1167 if (rm == NULL || (rm->flags & IMC_ROOM_DELETED)) {
1168 LM_ERR("Room [%.*s] does not exist!\n", STR_FMT(&room.uri));
1169 goto error;
1170 }
1171
1172 /* verify is the user is a member of the room*/
1173 member = imc_get_member(rm, &src->parsed.user, &src->parsed.host);
1174 if (member == NULL) {
1175 LM_ERR("User [%.*s] is not a member of room [%.*s]!\n",
1176 STR_FMT(&src->uri), STR_FMT(&rm->uri));
1177 goto error;
1178 }
1179
1180 if (!(member->flags & IMC_MEMBER_OWNER)) {
1181 LM_ERR("User [%.*s] is not owner of room [%.*s] and cannot destroy it!\n",
1182 STR_FMT(&src->uri), STR_FMT(&rm->uri));
1183 goto error;
1184 }
1185 rm->flags |= IMC_ROOM_DELETED;
1186
1187 /* braodcast message */
1188 imc_room_broadcast(rm, build_headers(msg), &msg_room_destroyed);
1189
1190 imc_release_room(rm);
1191 rm = NULL;
1192
1193 LM_DBG("Deleting room [%.*s]\n", STR_FMT(&room.uri));
1194 imc_del_room(&room.parsed.user, &room.parsed.host);
1195
1196 rv = 0;
1197 error:
1198 if (room.uri.s != NULL) pkg_free(room.uri.s);
1199 if (rm != NULL) imc_release_room(rm);
1200 return rv;
1201 }
1202
1203
imc_handle_help(struct sip_msg * msg,imc_cmd_t * cmd,struct imc_uri * src,struct imc_uri * dst)1204 int imc_handle_help(struct sip_msg* msg, imc_cmd_t *cmd, struct imc_uri *src, struct imc_uri *dst)
1205 {
1206 str body;
1207 uac_req_t uac_r;
1208
1209 body.s = IMC_HELP_MSG;
1210 body.len = IMC_HELP_MSG_LEN;
1211
1212 LM_DBG("to: [%.*s] from: [%.*s]\n", STR_FMT(&src->uri), STR_FMT(&dst->uri));
1213 set_uac_req(&uac_r, &imc_msg_type, build_headers(msg), &body, 0, 0, 0, 0);
1214 tmb.t_request(&uac_r,
1215 NULL, /* Request-URI */
1216 &src->uri, /* To */
1217 &dst->uri, /* From */
1218 (outbound_proxy.s)?&outbound_proxy:NULL/* outbound proxy */
1219 );
1220 return 0;
1221 }
1222
1223
imc_handle_unknown(struct sip_msg * msg,imc_cmd_t * cmd,struct imc_uri * src,struct imc_uri * dst)1224 int imc_handle_unknown(struct sip_msg* msg, imc_cmd_t *cmd, struct imc_uri *src, struct imc_uri *dst)
1225 {
1226 str body;
1227 uac_req_t uac_r;
1228
1229 body.s = imc_body_buf;
1230 body.len = snprintf(body.s, sizeof(imc_body_buf), msg_invalid_command.s,
1231 STR_FMT(&cmd->name), STR_FMT(&imc_cmd_start_str));
1232
1233 if (body.len < 0 || body.len >= sizeof(imc_body_buf)) {
1234 LM_ERR("Unable to print message\n");
1235 return -1;
1236 }
1237
1238 LM_DBG("to: [%.*s] from: [%.*s]\n", STR_FMT(&src->uri), STR_FMT(&dst->uri));
1239 set_uac_req(&uac_r, &imc_msg_type, build_headers(msg), &body, 0, 0, 0, 0);
1240 tmb.t_request(&uac_r,
1241 NULL, /* Request-URI */
1242 &src->uri, /* To */
1243 &dst->uri, /* From */
1244 (outbound_proxy.s)?&outbound_proxy:NULL /* outbound proxy */
1245 );
1246 return 0;
1247 }
1248
1249
imc_handle_message(struct sip_msg * msg,str * msgbody,struct imc_uri * src,struct imc_uri * dst)1250 int imc_handle_message(struct sip_msg* msg, str *msgbody,
1251 struct imc_uri *src, struct imc_uri *dst)
1252 {
1253 int rv = -1;
1254 imc_room_p room = 0;
1255 imc_member_p member = 0;
1256 str body, *user;
1257
1258 room = imc_get_room(&dst->parsed.user, &dst->parsed.host);
1259 if (room == NULL || (room->flags & IMC_ROOM_DELETED)) {
1260 LM_DBG("Room [%.*s] does not exist!\n", STR_FMT(&dst->uri));
1261 goto error;
1262 }
1263
1264 member = imc_get_member(room, &src->parsed.user, &src->parsed.host);
1265 if (member == NULL || (member->flags & IMC_MEMBER_INVITED)) {
1266 LM_ERR("User [%.*s] has no right to send messages to room [%.*s]!\n",
1267 STR_FMT(&src->uri), STR_FMT(&room->uri));
1268 goto error;
1269 }
1270
1271 LM_DBG("Broadcast to room [%.*s]\n", STR_FMT(&room->uri));
1272
1273 user = format_uri(member->uri);
1274
1275 body.s = imc_body_buf;
1276 body.len = snprintf(body.s, sizeof(imc_body_buf), "%.*s: %.*s", STR_FMT(user), STR_FMT(msgbody));
1277
1278 if (body.len < 0) {
1279 LM_ERR("Error while printing message\n");
1280 goto error;
1281 }
1282
1283 if (body.len >= sizeof(imc_body_buf)) {
1284 LM_ERR("Buffer too small for message '%.*s'\n", STR_FMT(&body));
1285 goto error;
1286 }
1287
1288 member->flags |= IMC_MEMBER_SKIP;
1289 imc_room_broadcast(room, build_headers(msg), &body);
1290 member->flags &= ~IMC_MEMBER_SKIP;
1291
1292 rv = 0;
1293 error:
1294 if (room != NULL) imc_release_room(room);
1295 return rv;
1296 }
1297
1298
imc_room_broadcast(imc_room_p room,str * ctype,str * body)1299 int imc_room_broadcast(imc_room_p room, str *ctype, str *body)
1300 {
1301 imc_member_p imp;
1302
1303 if (room == NULL || body == NULL)
1304 return -1;
1305
1306 imp = room->members;
1307
1308 LM_DBG("nr = %d\n", room->nr_of_members);
1309
1310 while(imp) {
1311 LM_DBG("to uri = %.*s\n", STR_FMT(&imp->uri));
1312 if ((imp->flags & IMC_MEMBER_INVITED) || (imp->flags & IMC_MEMBER_DELETED)
1313 || (imp->flags & IMC_MEMBER_SKIP)) {
1314 imp = imp->next;
1315 continue;
1316 }
1317
1318 /* to-do: callback to remove user if delivery fails */
1319 imc_send_message(&room->uri, &imp->uri, ctype, body);
1320
1321 imp = imp->next;
1322 }
1323 return 0;
1324 }
1325
1326
imc_send_message(str * src,str * dst,str * headers,str * body)1327 int imc_send_message(str *src, str *dst, str *headers, str *body)
1328 {
1329 uac_req_t uac_r;
1330
1331 if (src == NULL || dst == NULL || body == NULL)
1332 return -1;
1333
1334 /* to-do: callback to remove user if delivery fails */
1335 set_uac_req(&uac_r, &imc_msg_type, headers, body, 0, 0, 0, 0);
1336 tmb.t_request(&uac_r,
1337 NULL, /* Request-URI */
1338 dst, /* To */
1339 src, /* From */
1340 (outbound_proxy.s)?&outbound_proxy:NULL /* outbound proxy */
1341 );
1342 return 0;
1343 }
1344
1345
imc_inv_callback(struct cell * t,int type,struct tmcb_params * ps)1346 void imc_inv_callback(struct cell *t, int type, struct tmcb_params *ps)
1347 {
1348 str body_final;
1349 char from_uri_buf[256];
1350 char to_uri_buf[256];
1351 char body_buf[256];
1352 str from_uri_s, to_uri_s;
1353 imc_member_p member= NULL;
1354 imc_room_p room = NULL;
1355 uac_req_t uac_r;
1356
1357 if (ps->param == NULL || *ps->param == NULL ||
1358 (del_member_t*)(*ps->param) == NULL) {
1359 LM_DBG("member not received\n");
1360 return;
1361 }
1362
1363 LM_DBG("completed with status %d [member name domain:"
1364 "%p/%.*s/%.*s]\n",ps->code, ps->param,
1365 STR_FMT(&((del_member_t *)(*ps->param))->member_name),
1366 STR_FMT(&((del_member_t *)(*ps->param))->member_domain));
1367 if (ps->code < 300) {
1368 return;
1369 } else {
1370 room = imc_get_room(&((del_member_t *)(*ps->param))->room_name,
1371 &((del_member_t *)(*ps->param))->room_domain);
1372 if (room ==NULL) {
1373 LM_ERR("The room does not exist!\n");
1374 goto error;
1375 }
1376 /*verify if the user who sent the request is a member in the room
1377 * and has the right to remove other users */
1378 member = imc_get_member(room,
1379 &((del_member_t *)(*ps->param))->member_name,
1380 &((del_member_t *)(*ps->param))->member_domain);
1381
1382 if( member == NULL) {
1383 LM_ERR("The user is not a member of the room!\n");
1384 goto error;
1385 }
1386 imc_del_member(room,
1387 &((del_member_t *)(*ps->param))->member_name,
1388 &((del_member_t *)(*ps->param))->member_domain);
1389 goto build_inform;
1390 }
1391
1392 build_inform:
1393 body_final.s = body_buf;
1394 body_final.len = member->uri.len - 4 /* sip: part of URI */ + 20;
1395 memcpy(body_final.s, member->uri.s + 4, member->uri.len - 4);
1396 memcpy(body_final.s + member->uri.len - 4," is not registered. ", 21);
1397
1398 goto send_message;
1399
1400 send_message:
1401
1402 from_uri_s.s = from_uri_buf;
1403 from_uri_s.len = room->uri.len;
1404 strncpy(from_uri_s.s, room->uri.s, room->uri.len);
1405
1406 LM_DBG("sending message\n");
1407
1408 to_uri_s.s = to_uri_buf;
1409 to_uri_s.len = ((del_member_t *)(*ps->param))->inv_uri.len;
1410 strncpy(to_uri_s.s, ((del_member_t *)(*ps->param))->inv_uri.s,
1411 ((del_member_t *)(*ps->param))->inv_uri.len);
1412
1413 LM_DBG("to: %.*s\nfrom: %.*s\nbody: %.*s\n", STR_FMT(&to_uri_s),
1414 STR_FMT(&from_uri_s), STR_FMT(&body_final));
1415 set_uac_req(&uac_r, &imc_msg_type, &extra_hdrs, &body_final, 0, 0, 0, 0);
1416 tmb.t_request(&uac_r,
1417 NULL, /* Request-URI */
1418 &to_uri_s, /* To */
1419 &from_uri_s, /* From */
1420 (outbound_proxy.s)?&outbound_proxy:NULL /* outbound proxy*/
1421 );
1422
1423 error:
1424 if (room != NULL) imc_release_room(room);
1425 if ((del_member_t *)(*ps->param)) shm_free(*ps->param);
1426 }
1427