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
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <libxml/parser.h>
00034 #include <time.h>
00035
00036 #include "../../mem/mem.h"
00037 #include "../../dprint.h"
00038 #include "../../parser/parse_expires.h"
00039 #include "../../dprint.h"
00040 #include "../../mem/shm_mem.h"
00041 #include "../../parser/msg_parser.h"
00042 #include "../../cmpapi.h"
00043 #include "../tm/tm_load.h"
00044 #include "pua.h"
00045 #include "hash.h"
00046 #include "send_publish.h"
00047 #include "pua_callback.h"
00048 #include "event_list.h"
00049
00050
00051 str* publ_build_hdr(int expires, pua_event_t* ev, str* content_type, str* etag,
00052 str* extra_headers, int is_body)
00053 {
00054 static char buf[3000];
00055 str* str_hdr = NULL;
00056 char* expires_s = NULL;
00057 int len = 0;
00058 int t= 0;
00059 str ctype;
00060
00061 str_hdr =(str*)pkg_malloc(sizeof(str));
00062 if(str_hdr== NULL)
00063 {
00064 LM_ERR("no more memory\n");
00065 return NULL;
00066 }
00067 memset(str_hdr, 0 , sizeof(str));
00068 memset(buf, 0, 2999);
00069 str_hdr->s = buf;
00070 str_hdr->len= 0;
00071
00072 memcpy(str_hdr->s ,"Max-Forwards: ", 14);
00073 str_hdr->len = 14;
00074 str_hdr->len+= sprintf(str_hdr->s+ str_hdr->len,"%d", MAX_FORWARD);
00075 memcpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
00076 str_hdr->len += CRLF_LEN;
00077
00078 memcpy(str_hdr->s+ str_hdr->len ,"Event: ", 7);
00079 str_hdr->len+= 7;
00080 memcpy(str_hdr->s+ str_hdr->len, ev->name.s, ev->name.len);
00081 str_hdr->len+= ev->name.len;
00082 memcpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
00083 str_hdr->len += CRLF_LEN;
00084
00085
00086 memcpy(str_hdr->s+str_hdr->len ,"Expires: ", 9);
00087 str_hdr->len += 9;
00088
00089 t= expires;
00090
00091 if( t<=0 )
00092 {
00093 t= min_expires;
00094 }
00095 else
00096 {
00097 t++;
00098 }
00099 expires_s = int2str(t, &len);
00100
00101 memcpy(str_hdr->s+str_hdr->len, expires_s, len);
00102 str_hdr->len+= len;
00103 memcpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
00104 str_hdr->len += CRLF_LEN;
00105
00106 if(etag)
00107 {
00108 LM_DBG("UPDATE_TYPE [etag]= %.*s\n", etag->len, etag->s);
00109 memcpy(str_hdr->s+str_hdr->len,"SIP-If-Match: ", 14);
00110 str_hdr->len += 14;
00111 memcpy(str_hdr->s+str_hdr->len, etag->s, etag->len);
00112 str_hdr->len += etag->len;
00113 memcpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
00114 str_hdr->len += CRLF_LEN;
00115 }
00116 if(is_body)
00117 {
00118 if(content_type== NULL || content_type->s== NULL || content_type->len== 0)
00119 {
00120 ctype= ev->content_type;
00121 }
00122 else
00123 {
00124 ctype.s= content_type->s;
00125 ctype.len= content_type->len;
00126 }
00127
00128 memcpy(str_hdr->s+str_hdr->len,"Content-Type: ", 14);
00129 str_hdr->len += 14;
00130 memcpy(str_hdr->s+str_hdr->len, ctype.s, ctype.len);
00131 str_hdr->len += ctype.len;
00132 memcpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
00133 str_hdr->len += CRLF_LEN;
00134 }
00135
00136 if(extra_headers && extra_headers->s && extra_headers->len)
00137 {
00138 memcpy(str_hdr->s+str_hdr->len,extra_headers->s , extra_headers->len);
00139 str_hdr->len += extra_headers->len;
00140 }
00141 str_hdr->s[str_hdr->len] = '\0';
00142
00143 return str_hdr;
00144
00145 }
00146
00147 void publ_cback_func(struct cell *t, int type, struct tmcb_params *ps)
00148 {
00149 struct hdr_field* hdr= NULL;
00150 struct sip_msg* msg= NULL;
00151 ua_pres_t* presentity= NULL;
00152 ua_pres_t* hentity= NULL;
00153 int found = 0;
00154 int size= 0;
00155 unsigned int lexpire= 0;
00156 str etag;
00157 unsigned int hash_code;
00158
00159 if(ps->param== NULL|| *ps->param== NULL)
00160 {
00161 LM_ERR("NULL callback parameter\n");
00162 goto error;
00163 }
00164 hentity= (ua_pres_t*)(*ps->param);
00165
00166 msg= ps->rpl;
00167 if(msg == NULL)
00168 {
00169 LM_ERR("no reply message found\n ");
00170 goto error;
00171 }
00172
00173
00174 if(msg== FAKED_REPLY)
00175 {
00176 LM_DBG("FAKED_REPLY\n");
00177 goto done;
00178 }
00179
00180 if( ps->code>= 300 )
00181 {
00182 hash_code= core_hash(hentity->pres_uri, NULL,HASH_SIZE);
00183 lock_get(&HashT->p_records[hash_code].lock);
00184 presentity= search_htable( hentity, hash_code);
00185 if(presentity)
00186 {
00187 if(ps->code== 412 && hentity->body && hentity->flag!= MI_PUBLISH &&
00188 hentity->flag!= MI_ASYN_PUBLISH)
00189 {
00190
00191
00192 LM_DBG("received a 412 reply- send an INSERT_TYPE"
00193 " publish request\n");
00194 delete_htable(presentity, hash_code);
00195 lock_release(&HashT->p_records[hash_code].lock);
00196 publ_info_t publ;
00197 memset(&publ, 0, sizeof(publ_info_t));
00198 publ.pres_uri= hentity->pres_uri;
00199 publ.body= hentity->body;
00200
00201 if(hentity->desired_expires== 0)
00202 publ.expires= -1;
00203 else
00204 if(hentity->desired_expires<= (int)time(NULL))
00205 publ.expires= 0;
00206 else
00207 publ.expires= hentity->desired_expires- (int)time(NULL)+ 3;
00208
00209 publ.source_flag|= hentity->flag;
00210 publ.event|= hentity->event;
00211 publ.content_type= hentity->content_type;
00212 publ.id= hentity->id;
00213 publ.extra_headers= hentity->extra_headers;
00214 publ.cb_param= hentity->cb_param;
00215 if(send_publish(&publ)< 0)
00216 {
00217 LM_ERR("when trying to send PUBLISH\n");
00218 goto error;
00219 }
00220 }
00221 else
00222 {
00223 delete_htable(presentity, hash_code);
00224 LM_DBG("***Delete from table\n");
00225 lock_release(&HashT->p_records[hash_code].lock);
00226 }
00227 }
00228 else
00229 lock_release(&HashT->p_records[hash_code].lock);
00230 goto done;
00231 }
00232
00233 if( parse_headers(msg,HDR_EOH_F, 0)==-1 )
00234 {
00235 LM_ERR("parsing headers\n");
00236 goto error;
00237 }
00238 if(msg->expires== NULL || msg->expires->body.len<= 0)
00239 {
00240 LM_ERR("No Expires header found\n");
00241 goto error;
00242 }
00243
00244 if (!msg->expires->parsed && (parse_expires(msg->expires) < 0))
00245 {
00246 LM_ERR("cannot parse Expires header\n");
00247 goto error;
00248 }
00249 lexpire = ((exp_body_t*)msg->expires->parsed)->val;
00250 LM_DBG("lexpire= %u\n", lexpire);
00251
00252 hdr = msg->headers;
00253 while (hdr!= NULL)
00254 {
00255 if(cmp_hdrname_strzn(&hdr->name, "SIP-ETag",8)==0 )
00256 {
00257 found = 1;
00258 break;
00259 }
00260 hdr = hdr->next;
00261 }
00262 if(found== 0)
00263 {
00264 LM_ERR("no SIP-ETag header field found\n");
00265 goto error;
00266 }
00267 etag= hdr->body;
00268
00269 LM_DBG("completed with status %d [contact:%.*s]\n",
00270 ps->code, hentity->pres_uri->len, hentity->pres_uri->s);
00271
00272 hash_code= core_hash(hentity->pres_uri, NULL, HASH_SIZE);
00273 lock_get(&HashT->p_records[hash_code].lock);
00274
00275 presentity= search_htable(hentity, hash_code);
00276 if(presentity)
00277 {
00278 LM_DBG("update record\n");
00279 if(lexpire == 0)
00280 {
00281 LM_DBG("expires= 0- delete from htable\n");
00282 delete_htable(presentity, hash_code);
00283 lock_release(&HashT->p_records[hash_code].lock);
00284 goto done;
00285 }
00286
00287 update_htable(presentity, hentity->desired_expires,
00288 lexpire, &etag, hash_code, NULL);
00289 lock_release(&HashT->p_records[hash_code].lock);
00290 goto done;
00291 }
00292 lock_release(&HashT->p_records[hash_code].lock);
00293
00294 if(lexpire== 0)
00295 {
00296 LM_DBG("expires= 0: no not insert\n");
00297 goto done;
00298 }
00299 size= sizeof(ua_pres_t)+ sizeof(str)+
00300 (hentity->pres_uri->len+ hentity->tuple_id.len +
00301 hentity->id.len)* sizeof(char);
00302 if(hentity->extra_headers)
00303 size+= sizeof(str)+ hentity->extra_headers->len* sizeof(char);
00304
00305 presentity= (ua_pres_t*)shm_malloc(size);
00306 if(presentity== NULL)
00307 {
00308 LM_ERR("no more share memory\n");
00309 goto error;
00310 }
00311 memset(presentity, 0, size);
00312 memset(&presentity->etag, 0, sizeof(str));
00313
00314 size= sizeof(ua_pres_t);
00315 presentity->pres_uri= (str*)((char*)presentity+ size);
00316 size+= sizeof(str);
00317
00318 presentity->pres_uri->s= (char*)presentity+ size;
00319 memcpy(presentity->pres_uri->s, hentity->pres_uri->s,
00320 hentity->pres_uri->len);
00321 presentity->pres_uri->len= hentity->pres_uri->len;
00322 size+= hentity->pres_uri->len;
00323
00324 presentity->tuple_id.s= (char*)presentity+ size;
00325 memcpy(presentity->tuple_id.s, hentity->tuple_id.s,
00326 hentity->tuple_id.len);
00327 presentity->tuple_id.len= hentity->tuple_id.len;
00328 size+= presentity->tuple_id.len;
00329
00330 presentity->id.s=(char*)presentity+ size;
00331 memcpy(presentity->id.s, hentity->id.s,
00332 hentity->id.len);
00333 presentity->id.len= hentity->id.len;
00334 size+= presentity->id.len;
00335
00336 if(hentity->extra_headers)
00337 {
00338 presentity->extra_headers= (str*)((char*)presentity+ size);
00339 size+= sizeof(str);
00340 presentity->extra_headers->s= (char*)presentity+ size;
00341 memcpy(presentity->extra_headers->s, hentity->extra_headers->s,
00342 hentity->extra_headers->len);
00343 presentity->extra_headers->len= hentity->extra_headers->len;
00344 size+= hentity->extra_headers->len;
00345 }
00346
00347 presentity->desired_expires= hentity->desired_expires;
00348 presentity->expires= lexpire+ (int)time(NULL);
00349 presentity->flag|= hentity->flag;
00350 presentity->event|= hentity->event;
00351
00352 presentity->etag.s= (char*)shm_malloc(etag.len* sizeof(char));
00353 if(presentity->etag.s== NULL)
00354 {
00355 LM_ERR("No more share memory\n");
00356 goto error;
00357 }
00358 memcpy(presentity->etag.s, etag.s, etag.len);
00359 presentity->etag.len= etag.len;
00360
00361 insert_htable( presentity);
00362 LM_DBG("***Inserted in hash table\n");
00363
00364 done:
00365 if(hentity->ua_flag == REQ_OTHER)
00366 {
00367 run_pua_callbacks(hentity, msg);
00368 }
00369 if(*ps->param)
00370 {
00371 shm_free(*ps->param);
00372 *ps->param= NULL;
00373 }
00374 return;
00375
00376 error:
00377 if(*ps->param)
00378 {
00379 shm_free(*ps->param);
00380 *ps->param= NULL;
00381 }
00382
00383 return;
00384 }
00385
00386 int send_publish( publ_info_t* publ )
00387 {
00388 str met = {"PUBLISH", 7};
00389 str* str_hdr = NULL;
00390 ua_pres_t* presentity= NULL;
00391 str* body= NULL;
00392 str* tuple_id= NULL;
00393 ua_pres_t* cb_param= NULL, pres;
00394 unsigned int hash_code;
00395 str etag= {0, 0};
00396 int ver= 0;
00397 int result;
00398 int ret_code= 0;
00399 pua_event_t* ev= NULL;
00400
00401 LM_DBG("pres_uri=%.*s\n", publ->pres_uri->len, publ->pres_uri->s );
00402
00403
00404
00405 ev= get_event(publ->event);
00406 if(ev== NULL)
00407 {
00408 LM_ERR("event not found in list\n");
00409 goto error;
00410 }
00411
00412 memset(&pres, 0, sizeof(ua_pres_t));
00413 pres.pres_uri= publ->pres_uri;
00414 pres.flag= publ->source_flag;
00415 pres.id= publ->id;
00416 pres.event= publ->event;
00417 if(publ->etag)
00418 pres.etag= *publ->etag;
00419
00420 hash_code= core_hash(publ->pres_uri, NULL, HASH_SIZE);
00421
00422 lock_get(&HashT->p_records[hash_code].lock);
00423
00424 presentity= search_htable(&pres, hash_code);
00425
00426 if(publ->etag && presentity== NULL)
00427 {
00428 lock_release(&HashT->p_records[hash_code].lock);
00429 return 418;
00430 }
00431
00432 if(publ->flag & INSERT_TYPE)
00433 goto insert;
00434
00435 if(presentity== NULL)
00436 {
00437 insert:
00438 lock_release(&HashT->p_records[hash_code].lock);
00439 LM_DBG("insert type\n");
00440
00441 if(publ->flag & UPDATE_TYPE )
00442 {
00443 LM_DBG("UPDATE_TYPE and no record found \n");
00444 publ->flag= INSERT_TYPE;
00445 }
00446 if(publ->expires== 0)
00447 {
00448 LM_DBG("request for a publish with expires 0 and"
00449 " no record found\n");
00450 return 0;
00451 }
00452 if(publ->body== NULL)
00453 {
00454 LM_ERR("New PUBLISH and no body found- invalid request\n");
00455 return ERR_PUBLISH_NO_BODY;
00456 }
00457 }
00458 else
00459 {
00460 publ->flag= UPDATE_TYPE;
00461 etag.s= (char*)pkg_malloc(presentity->etag.len* sizeof(char));
00462 if(etag.s== NULL)
00463 {
00464 LM_ERR("while allocating memory\n");
00465 lock_release(&HashT->p_records[hash_code].lock);
00466 return -1;
00467 }
00468 memcpy(etag.s, presentity->etag.s, presentity->etag.len);
00469 etag.len= presentity->etag.len;
00470
00471 if(presentity->tuple_id.s && presentity->tuple_id.len)
00472 {
00473
00474 tuple_id=(str*)pkg_malloc(sizeof(str));
00475 if(tuple_id== NULL)
00476 {
00477 LM_ERR("No more memory\n");
00478 lock_release(&HashT->p_records[hash_code].lock);
00479 goto error;
00480 }
00481 tuple_id->s= (char*)pkg_malloc(presentity->tuple_id.len* sizeof(char));
00482 if(tuple_id->s== NULL)
00483 {
00484 LM_ERR("No more memory\n");
00485 lock_release(&HashT->p_records[hash_code].lock);
00486 goto error;
00487 }
00488 memcpy(tuple_id->s, presentity->tuple_id.s, presentity->tuple_id.len);
00489 tuple_id->len= presentity->tuple_id.len;
00490 }
00491
00492 if(publ->expires== 0)
00493 {
00494 LM_DBG("expires= 0- delete from hash table\n");
00495 lock_release(&HashT->p_records[hash_code].lock);
00496 goto send_publish;
00497 }
00498 presentity->version++;
00499 ver= presentity->version;
00500 lock_release(&HashT->p_records[hash_code].lock);
00501 }
00502
00503
00504
00505 if(publ->body && publ->body->s)
00506 {
00507 ret_code= ev->process_body(publ, &body, ver, &tuple_id );
00508 if( ret_code< 0 || body== NULL)
00509 {
00510 LM_ERR("while processing body\n");
00511 if(body== NULL)
00512 LM_ERR("NULL body\n");
00513 goto error;
00514 }
00515 }
00516 if(tuple_id)
00517 LM_DBG("tuple_id= %.*s\n", tuple_id->len, tuple_id->s );
00518
00519 send_publish:
00520
00521
00522
00523 cb_param= publish_cbparam(publ, body, tuple_id, REQ_OTHER);
00524 if(cb_param== NULL)
00525 {
00526 LM_ERR("constructing callback parameter\n");
00527 goto error;
00528 }
00529
00530 if(publ->flag & UPDATE_TYPE)
00531 LM_DBG("etag:%.*s\n", etag.len, etag.s);
00532 str_hdr = publ_build_hdr((publ->expires< 0)?3600:publ->expires, ev, &publ->content_type,
00533 (publ->flag & UPDATE_TYPE)?&etag:NULL, publ->extra_headers, (body)?1:0);
00534
00535 if(str_hdr == NULL)
00536 {
00537 LM_ERR("while building extra_headers\n");
00538 goto error;
00539 }
00540
00541 LM_DBG("publ->pres_uri:\n%.*s\n ", publ->pres_uri->len, publ->pres_uri->s);
00542 LM_DBG("str_hdr:\n%.*s %d\n ", str_hdr->len, str_hdr->s, str_hdr->len);
00543 if(body && body->len && body->s )
00544 LM_DBG("body:\n%.*s\n ", body->len, body->s);
00545
00546 result= tmb.t_request(&met,
00547 publ->pres_uri,
00548 publ->pres_uri,
00549 publ->pres_uri,
00550 str_hdr,
00551 body,
00552 &outbound_proxy,
00553 publ_cback_func,
00554 (void*)cb_param
00555 );
00556
00557 if(result< 0)
00558 {
00559 LM_ERR("in t_request tm module function\n");
00560 goto error;
00561 }
00562
00563 pkg_free(str_hdr);
00564
00565 if( body && ret_code)
00566 {
00567 if(body->s)
00568 free(body->s);
00569 pkg_free(body);
00570 }
00571 if(etag.s)
00572 pkg_free(etag.s);
00573 if(tuple_id)
00574 {
00575 if(tuple_id->s)
00576 pkg_free(tuple_id->s);
00577 pkg_free(tuple_id);
00578 }
00579
00580 return 0;
00581
00582 error:
00583 if(etag.s)
00584 pkg_free(etag.s);
00585
00586 if(cb_param)
00587 shm_free(cb_param);
00588
00589 if(body&& ret_code)
00590 {
00591 if(body->s)
00592 free(body->s);
00593 pkg_free(body);
00594 }
00595 if(str_hdr)
00596 pkg_free(str_hdr);
00597 if(tuple_id)
00598 {
00599 if(tuple_id->s)
00600 pkg_free(tuple_id->s);
00601 pkg_free(tuple_id);
00602 }
00603 return -1;
00604 }
00605
00606 ua_pres_t* publish_cbparam(publ_info_t* publ,str* body,str* tuple_id,
00607 int ua_flag)
00608 {
00609 int size;
00610 ua_pres_t* cb_param= NULL;
00611
00612 size= sizeof(ua_pres_t)+ sizeof(str)+ (publ->pres_uri->len+
00613 + publ->content_type.len+ publ->id.len+ 1)*sizeof(char);
00614 if(body && body->s && body->len)
00615 size+= sizeof(str)+ body->len* sizeof(char);
00616 if(publ->etag)
00617 size+= publ->etag->len* sizeof(char);
00618 if(publ->extra_headers)
00619 size+= sizeof(str)+ publ->extra_headers->len* sizeof(char);
00620 if(tuple_id )
00621 size+= tuple_id->len* sizeof(char);
00622
00623 cb_param= (ua_pres_t*)shm_malloc(size);
00624 if(cb_param== NULL)
00625 {
00626 LM_ERR("ERROR no more share memory while allocating cb_param"
00627 " - size= %d\n", size);
00628 return NULL;
00629 }
00630 memset(cb_param, 0, size);
00631
00632 size = sizeof(ua_pres_t);
00633
00634 cb_param->pres_uri = (str*)((char*)cb_param + size);
00635 size+= sizeof(str);
00636 cb_param->pres_uri->s = (char*)cb_param + size;
00637 memcpy(cb_param->pres_uri->s, publ->pres_uri->s ,
00638 publ->pres_uri->len ) ;
00639 cb_param->pres_uri->len= publ->pres_uri->len;
00640 size+= publ->pres_uri->len;
00641
00642 if(publ->id.s && publ->id.len)
00643 {
00644 cb_param->id.s = ((char*)cb_param+ size);
00645 memcpy(cb_param->id.s, publ->id.s, publ->id.len);
00646 cb_param->id.len= publ->id.len;
00647 size+= publ->id.len;
00648 }
00649
00650 if(body && body->s && body->len)
00651 {
00652 cb_param->body = (str*)((char*)cb_param + size);
00653 size+= sizeof(str);
00654
00655 cb_param->body->s = (char*)cb_param + size;
00656 memcpy(cb_param->body->s, body->s ,
00657 body->len ) ;
00658 cb_param->body->len= body->len;
00659 size+= body->len;
00660 }
00661 if(publ->etag)
00662 {
00663 cb_param->etag.s = (char*)cb_param + size;
00664 memcpy(cb_param->etag.s, publ->etag->s ,
00665 publ->etag->len ) ;
00666 cb_param->etag.len= publ->etag->len;
00667 size+= publ->etag->len;
00668 }
00669 if(publ->extra_headers)
00670 {
00671 cb_param->extra_headers = (str*)((char*)cb_param + size);
00672 size+= sizeof(str);
00673 cb_param->extra_headers->s = (char*)cb_param + size;
00674 memcpy(cb_param->extra_headers->s, publ->extra_headers->s ,
00675 publ->extra_headers->len ) ;
00676 cb_param->extra_headers->len= publ->extra_headers->len;
00677 size+= publ->extra_headers->len;
00678 }
00679
00680 if(publ->content_type.s && publ->content_type.len)
00681 {
00682 cb_param->content_type.s= (char*)cb_param + size;
00683 memcpy(cb_param->content_type.s, publ->content_type.s, publ->content_type.len);
00684 cb_param->content_type.len= publ->content_type.len;
00685 size+= publ->content_type.len;
00686 }
00687 if(tuple_id)
00688 {
00689 cb_param->tuple_id.s = (char*)cb_param+ size;
00690 memcpy(cb_param->tuple_id.s, tuple_id->s ,tuple_id->len);
00691 cb_param->tuple_id.len= tuple_id->len;
00692 size+= tuple_id->len;
00693 }
00694 cb_param->event= publ->event;
00695 cb_param->flag|= publ->source_flag;
00696 cb_param->cb_param= publ->cb_param;
00697 cb_param->ua_flag= ua_flag;
00698
00699 if(publ->expires< 0)
00700 cb_param->desired_expires= 0;
00701 else
00702 cb_param->desired_expires=publ->expires+ (int)time(NULL);
00703
00704 return cb_param;
00705 }