00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <stdio.h>
00030 #include <string.h>
00031 #include <stdlib.h>
00032 #include <sys/types.h>
00033 #include <sys/ipc.h>
00034 #include <unistd.h>
00035 #include <fcntl.h>
00036 #include <time.h>
00037 #include "../../db/db.h"
00038 #include "../../db/db_res.h"
00039 #include "../../sr_module.h"
00040 #include "../../dprint.h"
00041 #include "../../ut.h"
00042 #include "../../timer.h"
00043 #include "../../str.h"
00044 #include "../../mem/shm_mem.h"
00045 #include "../../db/db.h"
00046 #include "../../parser/parse_from.h"
00047 #include "../../parser/parse_content.h"
00048 #include "../../parser/contact/parse_contact.h"
00049 #include "../../resolve.h"
00050 #include "../../hash_func.h"
00051 #include "../../mi/mi.h"
00052
00053 #include "../tm/tm_load.h"
00054
00055
00056 #include "imc_mng.h"
00057 #include "imc_cmd.h"
00058
00059 MODULE_VERSION
00060
00061
00062
00063 db_con_t *imc_db = NULL;
00064 db_func_t imc_dbf;
00065 static str db_url = str_init(DEFAULT_DB_URL);
00066 str outbound_proxy = {NULL, 0};
00067
00068 static str rooms_table = str_init("imc_rooms");
00069 static str members_table = str_init("imc_members");
00070
00071 static str imc_col_username = str_init("username");
00072 static str imc_col_domain = str_init("domain");
00073 static str imc_col_flag = str_init("flag");
00074 static str imc_col_room = str_init("room");
00075 static str imc_col_name = str_init("name");
00076
00077 imc_hentry_p _imc_htable = NULL;
00078 int imc_hash_size = 4;
00079 str imc_cmd_start_str = str_init(IMC_CMD_START_STR);
00080 char imc_cmd_start_char;
00081
00082
00083 static int mod_init(void);
00084 static int child_init(int);
00085
00086 static int imc_manager(struct sip_msg*, char *, char *);
00087
00088 static struct mi_root* imc_mi_list_rooms(struct mi_root* cmd, void* param);
00089 static struct mi_root* imc_mi_list_members(struct mi_root* cmd, void* param);
00090
00091 void destroy(void);
00092
00093
00094 struct tm_binds tmb;
00095
00096
00097 void inv_callback( struct cell *t, int type, struct tmcb_params *ps);
00098
00099 static cmd_export_t cmds[]={
00100 {"imc_manager", (cmd_function)imc_manager, 0, 0, 0, REQUEST_ROUTE},
00101 {0,0,0,0,0,0}
00102 };
00103
00104
00105 static param_export_t params[]={
00106 {"db_url", STR_PARAM, &db_url.s},
00107 {"hash_size", INT_PARAM, &imc_hash_size},
00108 {"imc_cmd_start_char", STR_PARAM, &imc_cmd_start_str.s},
00109 {"rooms_table", STR_PARAM, &rooms_table.s},
00110 {"members_table", STR_PARAM, &members_table.s},
00111 {"outbound_proxy", STR_PARAM, &outbound_proxy.s},
00112 {0,0,0}
00113 };
00114
00115 #ifdef STATISTICS
00116 #include "../../statistics.h"
00117
00118 stat_var* imc_active_rooms;
00119
00120 stat_export_t imc_stats[] = {
00121 {"active_rooms" , 0, &imc_active_rooms },
00122 {0,0,0}
00123 };
00124
00125 #endif
00126
00127 static mi_export_t mi_cmds[] = {
00128 { "imc_list_rooms", imc_mi_list_rooms, MI_NO_INPUT_FLAG, 0, 0 },
00129 { "imc_list_members", imc_mi_list_members, 0, 0, 0 },
00130 { 0, 0, 0, 0, 0}
00131 };
00132
00133
00134
00135
00136 struct module_exports exports= {
00137 "imc",
00138 DEFAULT_DLFLAGS,
00139 cmds,
00140 params,
00141 #ifdef STATISTICS
00142 imc_stats,
00143 #else
00144 0,
00145 #endif
00146 mi_cmds,
00147 0,
00148 0,
00149 mod_init,
00150 0,
00151 (destroy_function) destroy,
00152 child_init
00153 };
00154
00155
00156
00157
00158 int add_from_db(void)
00159 {
00160 imc_member_p member = NULL;
00161 int i, j, flag;
00162 db_key_t mq_result_cols[4], mquery_cols[2];
00163 db_key_t rq_result_cols[4];
00164 db_val_t mquery_vals[2];
00165 db_res_t *r_res= NULL;
00166 db_res_t *m_res= NULL;
00167 db_row_t *m_row = NULL, *r_row = NULL;
00168 db_val_t *m_row_vals, *r_row_vals = NULL;
00169 str name, domain;
00170 imc_room_p room = NULL;
00171 int er_ret = -1;
00172
00173 rq_result_cols[0] = &imc_col_name;
00174 rq_result_cols[1] = &imc_col_domain;
00175 rq_result_cols[2] = &imc_col_flag;
00176
00177 mq_result_cols[0] = &imc_col_username;
00178 mq_result_cols[1] = &imc_col_domain;
00179 mq_result_cols[2] = &imc_col_flag;
00180
00181 mquery_cols[0] = &imc_col_room;
00182 mquery_vals[0].type = DB_STR;
00183 mquery_vals[0].nul = 0;
00184
00185 if(imc_dbf.use_table(imc_db, &rooms_table)< 0)
00186 {
00187 LM_ERR("use_table failed\n");
00188 return -1;
00189 }
00190
00191 if(imc_dbf.query(imc_db,0, 0, 0, rq_result_cols,0, 3, 0,&r_res)< 0)
00192 {
00193 LM_ERR("failed to querry table\n");
00194 return -1;
00195 }
00196 if(r_res && r_res->n<=0)
00197 {
00198 LM_INFO("the query returned no result\n");
00199 imc_dbf.free_result(imc_db, r_res);
00200 r_res = NULL;
00201 return 0;
00202 }
00203
00204 LM_DBG("found %d rooms\n", r_res->n);
00205
00206 for(i =0 ; i< r_res->n ; i++)
00207 {
00208
00209 r_row = &r_res->rows[i];
00210 r_row_vals = ROW_VALUES(r_row);
00211
00212 name.s = r_row_vals[0].val.str_val.s;
00213 name.len = strlen(name.s);
00214
00215 domain.s = r_row_vals[1].val.str_val.s;
00216 domain.len = strlen(domain.s);
00217
00218 flag = r_row_vals[2].val.int_val;
00219
00220 room = imc_add_room(&name, &domain, flag);
00221 if(room == NULL)
00222 {
00223 LM_ERR("failed to add room\n ");
00224 goto error;
00225 }
00226
00227
00228 if(imc_dbf.use_table(imc_db, &members_table)< 0)
00229 {
00230 LM_ERR("use_table failed\n ");
00231 goto error;
00232 }
00233
00234 mquery_vals[0].val.str_val= room->uri;
00235
00236 if(imc_dbf.query(imc_db, mquery_cols, 0, mquery_vals, mq_result_cols,
00237 1, 3, 0, &m_res)< 0)
00238 {
00239 LM_ERR("failed to querry table\n");
00240 goto error;
00241 }
00242
00243 if(m_res && m_res->n <=0)
00244 {
00245 LM_INFO("the query returned no result\n");
00246 er_ret = 0;
00247 goto error;
00248 }
00249 for(j =0; j< m_res->n; j++)
00250 {
00251 m_row = &m_res->rows[j];
00252 m_row_vals = ROW_VALUES(m_row);
00253
00254 name.s = m_row_vals[0].val.str_val.s;
00255 name.len = strlen(name.s);
00256
00257 domain.s = m_row_vals[1].val.str_val.s;
00258 domain.len = strlen(domain.s);
00259
00260 flag = m_row_vals[2].val.int_val;
00261
00262 LM_DBG("adding memeber: [name]=%.*s [domain]=%.*s"
00263 " in [room]= %.*s\n",name.len, name.s, domain.len,domain.s,
00264 room->uri.len, room->uri.s);
00265
00266 member = imc_add_member(room, &name, &domain, flag);
00267 if(member == NULL)
00268 {
00269 LM_ERR("failed to adding member\n ");
00270 goto error;
00271 }
00272 imc_release_room(room);
00273 }
00274
00275 if(m_res)
00276 {
00277 imc_dbf.free_result(imc_db, m_res);
00278 m_res = NULL;
00279 }
00280 }
00281
00282 if(imc_dbf.use_table(imc_db, &members_table)< 0)
00283 {
00284 LM_ERR("use table failed\n ");
00285 goto error;
00286 }
00287
00288 if(imc_dbf.delete(imc_db, 0, 0 , 0, 0) < 0)
00289 {
00290 LM_ERR("failed to delete information from db\n");
00291 goto error;
00292 }
00293
00294 if(imc_dbf.use_table(imc_db, &rooms_table)< 0)
00295 {
00296 LM_ERR("use table failed\n ");
00297 goto error;
00298 }
00299
00300 if(imc_dbf.delete(imc_db, 0, 0 , 0, 0) < 0)
00301 {
00302 LM_ERR("failed to delete information from db\n");
00303 goto error;
00304 }
00305
00306 if(r_res)
00307 {
00308 imc_dbf.free_result(imc_db, r_res);
00309 r_res = NULL;
00310 }
00311 if(m_res)
00312 {
00313 imc_dbf.free_result(imc_db, m_res);
00314 m_res = NULL;
00315 }
00316
00317 return 0;
00318
00319 error:
00320 if(r_res)
00321 {
00322 imc_dbf.free_result(imc_db, r_res);
00323 r_res = NULL;
00324 }
00325 if(m_res)
00326 {
00327 imc_dbf.free_result(imc_db, m_res);
00328 m_res = NULL;
00329 }
00330 if(room)
00331 imc_release_room(room);
00332 return er_ret;
00333
00334 }
00335
00336
00337 static int mod_init(void)
00338 {
00339 if(imc_hash_size <= 0)
00340 {
00341 LM_ERR("invalid hash size\n");
00342 return -1;
00343 }
00344
00345 imc_hash_size = 1 << imc_hash_size;
00346
00347 if(imc_htable_init() < 0)
00348 {
00349 LM_ERR("initializing hash table\n");
00350 return -1;
00351 }
00352
00353 imc_cmd_start_str.len = strlen(imc_cmd_start_str.s);
00354
00355 if(outbound_proxy.s)
00356 outbound_proxy.len = strlen(outbound_proxy.s);
00357
00358 rooms_table.len = strlen(rooms_table.s);
00359 members_table.len = strlen(members_table.s);
00360
00361
00362 db_url.len = strlen(db_url.s);
00363 LM_DBG("db_url=%s/%d/%p\n", ZSW(db_url.s), db_url.len, db_url.s);
00364
00365 if (db_bind_mod(&db_url, &imc_dbf))
00366 {
00367 LM_DBG("database module not found\n");
00368 return -1;
00369 }
00370
00371 imc_db = imc_dbf.init(&db_url);
00372 if (!imc_db)
00373 {
00374 LM_ERR("failed to connect to the database\n");
00375 return -1;
00376 }
00377
00378 if(add_from_db() <0)
00379 {
00380 LM_ERR("failed to get information from db\n");
00381 return -1;
00382 }
00383
00384
00385 if (load_tm_api(&tmb)!=0) {
00386 LM_ERR("unable to load tm api\n");
00387 return -1;
00388 }
00389
00390 imc_cmd_start_char = imc_cmd_start_str.s[0];
00391
00392 if(imc_db)
00393 imc_dbf.close(imc_db);
00394 imc_db = NULL;
00395
00396 return 0;
00397 }
00398
00399
00400
00401
00402 static int child_init(int rank)
00403 {
00404 if (imc_dbf.init==0)
00405 {
00406 LM_ERR("database not bound\n");
00407 return -1;
00408 }
00409 imc_db = imc_dbf.init(&db_url);
00410 if (!imc_db)
00411 {
00412 LM_ERR("child %d: Error while connecting database\n", rank);
00413 return -1;
00414 }
00415 else
00416 {
00417 if (imc_dbf.use_table(imc_db, &rooms_table) < 0)
00418 {
00419 LM_ERR("child %d: Error in use_table '%.*s'\n", rank, rooms_table.len, rooms_table.s);
00420 return -1;
00421 }
00422 if (imc_dbf.use_table(imc_db, &members_table) < 0)
00423 {
00424 LM_ERR("child %d: Error in use_table '%.*s'\n", rank, members_table.len, members_table.s);
00425 return -1;
00426 }
00427
00428 LM_DBG("child %d: Database connection opened successfully\n", rank);
00429 }
00430
00431 return 0;
00432 }
00433
00434
00435 static int imc_manager(struct sip_msg* msg, char *str1, char *str2)
00436 {
00437 imc_cmd_t cmd;
00438 str body;
00439 struct sip_uri from_uri, *pto_uri=NULL, *pfrom_uri=NULL;
00440 struct to_body *pfrom;
00441
00442 body.s = get_body( msg );
00443 if (body.s==0)
00444 {
00445 LM_ERR("cannot extract body from msg\n");
00446 goto error;
00447 }
00448
00449
00450 if (!msg->content_length)
00451 {
00452 LM_ERR("no Content-Length\n");
00453 goto error;
00454 }
00455 body.len = get_content_length( msg );
00456
00457 if(body.len <= 0)
00458 {
00459 LM_DBG("empty body!\n");
00460 goto error;
00461 }
00462
00463 if(parse_sip_msg_uri(msg)<0)
00464 {
00465 LM_ERR("failed to parse r-uri\n");
00466 goto error;
00467 }
00468
00469 pto_uri=&msg->parsed_uri;
00470
00471 if(parse_from_header(msg)<0)
00472 {
00473 LM_ERR("failed to parse From header\n");
00474 goto error;
00475 }
00476 pfrom = (struct to_body*)msg->from->parsed;
00477 if(parse_uri(pfrom->uri.s, pfrom->uri.len, &from_uri)<0){
00478 LM_ERR("failed to parse From URI\n");
00479 goto error;
00480 }
00481 pfrom_uri=&from_uri;
00482
00483 if(body.s[0]== imc_cmd_start_char)
00484 {
00485 LM_DBG("found command\n");
00486 if(imc_parse_cmd(body.s, body.len, &cmd)<0)
00487 {
00488 LM_ERR("failed to parse imc cmd!\n");
00489 goto error;
00490 }
00491
00492 switch(cmd.type)
00493 {
00494 case IMC_CMDID_CREATE:
00495 if(imc_handle_create(msg, &cmd, pfrom_uri, pto_uri)<0)
00496 {
00497 LM_ERR("failed to handle 'create'\n");
00498 goto error;
00499 }
00500 break;
00501 case IMC_CMDID_JOIN:
00502 if(imc_handle_join(msg, &cmd, pfrom_uri, pto_uri)<0)
00503 {
00504 LM_ERR("failed to handle 'join'\n");
00505 goto error;
00506 }
00507 break;
00508 case IMC_CMDID_INVITE:
00509 if(imc_handle_invite(msg, &cmd, pfrom_uri, pto_uri)<0)
00510 {
00511 LM_ERR("failed to handle 'invite'\n");
00512 goto error;
00513 }
00514 break;
00515 case IMC_CMDID_ACCEPT:
00516 if(imc_handle_accept(msg, &cmd, pfrom_uri, pto_uri)<0)
00517 {
00518 LM_ERR("failed to handle 'accept'\n");
00519 goto error;
00520 }
00521 break;
00522 case IMC_CMDID_DENY:
00523 if(imc_handle_deny(msg, &cmd, pfrom_uri, pto_uri)<0)
00524 {
00525 LM_ERR("failed to handle 'deny'\n");
00526 goto error;
00527 }
00528 break;
00529 case IMC_CMDID_REMOVE:
00530 if(imc_handle_remove(msg, &cmd, pfrom_uri, pto_uri)<0)
00531 {
00532 LM_ERR("failed to handle 'remove'\n");
00533 goto error;
00534 }
00535 break;
00536 case IMC_CMDID_EXIT:
00537 if(imc_handle_exit(msg, &cmd, pfrom_uri, pto_uri)<0)
00538 {
00539 LM_ERR("failed to handle 'exit'\n");
00540 goto error;
00541 }
00542 break;
00543 case IMC_CMDID_LIST:
00544 if(imc_handle_list(msg, &cmd, pfrom_uri, pto_uri)<0)
00545 {
00546 LM_ERR("failed to handle 'list'\n");
00547 goto error;
00548 }
00549 break;
00550 case IMC_CMDID_DESTROY:
00551 if(imc_handle_destroy(msg, &cmd, pfrom_uri, pto_uri)<0)
00552 {
00553 LM_ERR("failed to handle 'destroy'\n");
00554 goto error;
00555 }
00556 break;
00557 case IMC_CMDID_HELP:
00558 if(imc_handle_help(msg, &cmd, &pfrom->uri,
00559 (msg->new_uri.s)?&msg->new_uri:&msg->first_line.u.request.uri)<0)
00560 {
00561 LM_ERR("failed to handle 'help'\n");
00562 goto error;
00563 }
00564 break;
00565 default:
00566 if(imc_handle_unknown(msg, &cmd, &pfrom->uri,
00567 (msg->new_uri.s)?&msg->new_uri:&msg->first_line.u.request.uri)<0)
00568 {
00569 LM_ERR("failed to handle 'unknown'\n");
00570 goto error;
00571 }
00572 }
00573
00574 goto done;
00575 }
00576
00577 if(imc_handle_message(msg, &body, pfrom_uri, pto_uri)<0)
00578 {
00579 LM_ERR("failed to handle 'message'\n");
00580 goto error;
00581 }
00582
00583 done:
00584 return 1;
00585
00586 error:
00587
00588 return -1;
00589 }
00590
00591
00592
00593
00594 void destroy(void)
00595 {
00596 imc_room_p irp = NULL;
00597 imc_member_p member = NULL;
00598 int i;
00599 db_key_t mq_cols[4];
00600 db_val_t mq_vals[4];
00601 db_key_t rq_cols[4];
00602 db_val_t rq_vals[4];
00603
00604 if(imc_db==NULL)
00605 goto done;
00606
00607 mq_cols[0] = &imc_col_username;
00608 mq_vals[0].type = DB_STR;
00609 mq_vals[0].nul = 0;
00610
00611 mq_cols[1] = &imc_col_domain;
00612 mq_vals[1].type = DB_STR;
00613 mq_vals[1].nul = 0;
00614
00615 mq_cols[2] = &imc_col_flag;
00616 mq_vals[2].type = DB_INT;
00617 mq_vals[2].nul = 0;
00618
00619 mq_cols[3] = &imc_col_room;
00620 mq_vals[3].type = DB_STR;
00621 mq_vals[3].nul = 0;
00622
00623
00624 rq_cols[0] = &imc_col_name;
00625 rq_vals[0].type = DB_STR;
00626 rq_vals[0].nul = 0;
00627
00628 rq_cols[1] = &imc_col_domain;
00629 rq_vals[1].type = DB_STR;
00630 rq_vals[1].nul = 0;
00631
00632 rq_cols[2] = &imc_col_flag;
00633 rq_vals[2].type = DB_INT;
00634 rq_vals[2].nul = 0;
00635
00636 for(i=0; i<imc_hash_size; i++)
00637 {
00638 irp = _imc_htable[i].rooms;
00639
00640 while(irp)
00641 {
00642 rq_vals[0].val.str_val = irp->name;
00643 rq_vals[1].val.str_val = irp->domain;
00644 rq_vals[2].val.int_val = irp->flags;
00645
00646 if(imc_dbf.use_table(imc_db, &rooms_table)< 0)
00647 {
00648 LM_ERR("use_table failed\n");
00649 return;
00650 }
00651
00652 if(imc_dbf.insert(imc_db, rq_cols, rq_vals, 3)<0)
00653 {
00654 LM_ERR("failed to insert into table imc_rooms\n");
00655 return;
00656 }
00657 LM_DBG("room %d %.*s\n", i, irp->name.len, irp->name.s);
00658 member = irp->members;
00659 while(member)
00660 {
00661 mq_vals[0].val.str_val = member->user;
00662 mq_vals[1].val.str_val = member->domain;
00663 mq_vals[2].val.int_val = member->flags;
00664 mq_vals[3].val.str_val = irp->uri;
00665
00666 if(imc_dbf.use_table(imc_db, &members_table)< 0)
00667 {
00668 LM_ERR("use_table failed\n");
00669 return;
00670 }
00671
00672 if(imc_dbf.insert(imc_db, mq_cols, mq_vals, 4)<0)
00673 {
00674 LM_ERR("failed to insert into table imc_rooms\n");
00675 return;
00676 }
00677 member = member->next;
00678 }
00679 irp = irp->next;
00680 }
00681 }
00682
00683 done:
00684 imc_htable_destroy();
00685 }
00686
00687
00688
00689 static struct mi_root* imc_mi_list_rooms(struct mi_root* cmd_tree, void* param)
00690 {
00691 int i, len;
00692 struct mi_root* rpl_tree= NULL;
00693 struct mi_node* rpl= NULL;
00694 struct mi_node* node= NULL;
00695 struct mi_attr* attr= NULL;
00696 imc_room_p irp = NULL;
00697 char* p = NULL;
00698
00699 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00700 if(rpl_tree == NULL)
00701 return 0;
00702 rpl = &rpl_tree->node;
00703
00704 for(i=0; i<imc_hash_size; i++)
00705 {
00706 lock_get(&_imc_htable[i].lock);
00707 irp = _imc_htable[i].rooms;
00708 while(irp){
00709 node = add_mi_node_child(rpl, 0, "ROOM", 4, 0, 0);
00710 if( node == NULL)
00711 goto error;
00712
00713 attr= add_mi_attr(node, MI_DUP_VALUE, "URI", 3, irp->uri.s,
00714 irp->uri.len);
00715 if(attr == NULL)
00716 goto error;
00717
00718 p = int2str(irp->nr_of_members, &len);
00719 attr= add_mi_attr(node, 0, "MEMBERS", 7,p, len );
00720 if(attr == NULL)
00721 goto error;
00722
00723 attr= add_mi_attr(node, MI_DUP_VALUE, "OWNER", 5,
00724 irp->members->uri.s, irp->members->uri.len);
00725 if(attr == NULL)
00726 goto error;
00727
00728 irp = irp->next;
00729 }
00730 lock_release(&_imc_htable[i].lock);
00731 }
00732
00733 return rpl_tree;
00734
00735 error:
00736 lock_release(&_imc_htable[i].lock);
00737 free_mi_tree(rpl_tree);
00738 return 0;
00739
00740 }
00741
00742
00743 static struct mi_root* imc_mi_list_members(struct mi_root* cmd_tree,
00744 void* param)
00745 {
00746 int i, len;
00747 struct mi_root* rpl_tree = NULL;
00748 struct mi_node* node= NULL;
00749 struct mi_node* node_r= NULL;
00750 struct mi_attr* attr= NULL;
00751 char rnbuf[256];
00752 str room_name;
00753 imc_room_p room;
00754 struct sip_uri inv_uri, *pinv_uri;
00755 imc_member_p imp=NULL;
00756 char* p = NULL;
00757
00758 node= cmd_tree->node.kids;
00759 if(node == NULL|| node->next!=NULL)
00760 return 0;
00761
00762
00763 room_name.s = rnbuf;
00764 room_name.len= node->value.len;
00765 memcpy(room_name.s, node->value.s, node->value.len);
00766 if(room_name.s == NULL || room_name.len == 0)
00767 {
00768 LM_ERR(" no room name!\n");
00769 return init_mi_tree( 404, "room name not found", 19);
00770 }
00771 rnbuf[room_name.len] = '\0';
00772 if(*room_name.s=='\0' || *room_name.s=='.')
00773 {
00774 LM_INFO("empty room name\n");
00775 return init_mi_tree( 400, "empty param", 11);
00776 }
00777
00778
00779 parse_uri(room_name.s,room_name.len, &inv_uri);
00780 pinv_uri=&inv_uri;
00781 room=imc_get_room(&pinv_uri->user, &pinv_uri->host);
00782
00783 if(room==NULL)
00784 {
00785 LM_ERR("no such room!\n");
00786 return init_mi_tree( 404, "no such room", 14);
00787 }
00788
00789 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00790 if(rpl_tree == NULL)
00791 return 0;
00792
00793 node_r = add_mi_node_child( &rpl_tree->node, MI_DUP_VALUE, "ROOM", 4,
00794 room_name.s, room_name.len);
00795 if(node_r == NULL)
00796 goto error;
00797
00798
00799 imp = room->members;
00800 i=0;
00801 while(imp)
00802 {
00803 i++;
00804 node = add_mi_node_child(node_r, MI_DUP_VALUE, "MEMBER",6, imp->uri.s,
00805 imp->uri.len);
00806 if(node == NULL)
00807 goto error;
00808 imp = imp->next;
00809 }
00810
00811 p = int2str(i, &len);
00812 attr= add_mi_attr(node_r, MI_DUP_VALUE, "NR_OF_MEMBERS", 13, p, len);
00813 if(attr == 0)
00814 goto error;
00815
00816 imc_release_room(room);
00817
00818 return rpl_tree;
00819
00820 error:
00821 imc_release_room(room);
00822 free_mi_tree(rpl_tree);
00823 return 0;
00824 }