/** * Updates the r_subscriber with the new expires value * If not found, it will be inserted * @param p - the r_public to add to * @param subscriber - the subscriber to update * @param expires - new expires value, NULL if not necessary * @param ua - new user agent string, NULL if no update necessary * @param dialog - dialog for the subscription * @returns the newly added r_public, 0 on error */ r_subscriber* update_r_subscriber(r_public *p,str subscriber,int event,int* expires,dlg_t *dialog) { r_subscriber *s; if (!p) return 0; s = get_r_subscriber(p,subscriber,event); if (!s){ if (expires) return add_r_subscriber(p,subscriber,event,*expires,dialog); else return 0; }else{ if (expires) s->expires = *expires; if (s->dialog && s->dialog!=dialog) tmb.free_dlg(s->dialog); s->dialog = dialog; return s; } }
/** * Save this subscription. * @param msg - the SIP SUBSCRIBE message * @param str1 - not used * @param str2 - not used * @returns #CSCF_RETURN_TRUE if allowed, #CSCF_RETURN_FALSE if not, #CSCF_RETURN_ERROR on error */ int S_subscribe(struct sip_msg *msg,char *str1,char *str2) { int ret=CSCF_RETURN_FALSE; struct sip_uri puri; str uri={0,0}; str event; int event_i=IMS_EVENT_NONE; int expires=0,expires_time=0; str subscriber; r_public *p=0; r_subscriber *s=0,*new_s=0; dlg_t *dialog=0; LOG(L_DBG,"DBG:"M_NAME":S_subscribe: Saving SUBSCRIBE\n"); /* First check the parameters */ if (msg->first_line.type!=SIP_REQUEST) { LOG(L_ERR,"ERR:"M_NAME":S_subscribe: This message is not a request\n"); goto error; } if (msg->first_line.u.request.method.len != 9 || memcmp(msg->first_line.u.request.method.s,"SUBSCRIBE",9)!=0) { LOG(L_ERR,"ERR:"M_NAME":S_subscribe: This message is not a SUBSCRIBE\n"); goto error; } /* 1. Get the event */ event = cscf_get_event(msg); if (event.len!=3||strncasecmp(event.s,"reg",3)!=0){ LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Accepting only <Event: reg>. Found: <%.*s>\n", event.len,event.s); ret = CSCF_RETURN_FALSE; goto done; } if (event.len==0 && strncasecmp(event.s,"reg",3)==0) event_i = IMS_EVENT_REG; /* 2. Get the target of the SUBSCRIBE from RequestURI */ if (msg->new_uri.s) uri = msg->new_uri; else uri = msg->first_line.u.request.uri; if (parse_uri(uri.s, uri.len, &puri) < 0) { LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Error parsing uri <%.*s>\n", uri.len,uri.s); goto error; } uri.len = lookup_sip.len+puri.user.len+1+puri.host.len; uri.s = pkg_malloc(uri.len); if (!uri.s){ LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Error allocating %d bytes\n",uri.len); goto error; } uri.len=0; memcpy(uri.s,lookup_sip.s,lookup_sip.len); uri.len+=lookup_sip.len; memcpy(uri.s+uri.len,puri.user.s,puri.user.len); uri.len+=puri.user.len; uri.s[uri.len++]='@'; memcpy(uri.s+uri.len,puri.host.s,puri.host.len); uri.len+=puri.host.len; /* 3. Get the Subscriber's Identity */ subscriber = cscf_get_contact(msg); if (!subscriber.len){ LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Contact empty.\n"); ret = CSCF_RETURN_FALSE; goto done; } LOG(L_DBG,"DBG:"M_NAME":S_subscribe: Contact <%.*s>.\n", subscriber.len,subscriber.s); p = get_r_public(uri); /* Registration is possible even if the user is not registered... so just create one */ if (!p){ p = add_r_public(uri,0,0); } if (!p){ LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Identity not found and error on creation <%.*s>\n", uri.len,uri.s); ret = CSCF_RETURN_FALSE; goto done; } expires = cscf_get_expires_hdr(msg,0); if (expires == -1) expires = subscription_default_expires; if (expires > 0) { if (expires < subscription_min_expires) expires = subscription_min_expires; if (expires > subscription_max_expires) expires = subscription_max_expires; r_act_time(); expires_time = expires + time_now; /* get the old subscriber - if any */ s = get_r_subscriber(p,subscriber,event_i); if (!s){ /* create a new dialog */ if (tmb.new_dlg_uas(msg, 200, &dialog) < 0) { LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Error while creating dialog state\n"); ret = CSCF_RETURN_FALSE; goto error; } }else dialog = s->dialog; /* update the subscriber */ if ((new_s=update_r_subscriber(p,subscriber,event_i,&expires_time,dialog))!=0){ //if (!s) /* Only on first subscription, not on refreshes, send a notify */ S_event_reg(p,0,new_s,IMS_REGISTRAR_SUBSCRIBE,0); ret = CSCF_RETURN_TRUE; } else ret = CSCF_RETURN_FALSE; }else{ /* Unsubscribe */ /* get the old subscriber - if any */ r_act_time(); s = get_r_subscriber(p,subscriber,event_i); if (s) { s->expires = time_now; S_event_reg(p,0,s,IMS_REGISTRAR_UNSUBSCRIBE,1); del_r_subscriber(p,s); } ret = CSCF_RETURN_TRUE; } done: r_unlock(p->hash); if (expires ==0 )S_SUBSCRIBE_reply(msg,200,MSG_REG_UNSUBSCRIBE_OK,&expires,&uri); else S_SUBSCRIBE_reply(msg,200,MSG_REG_SUBSCRIBE_OK,&expires,&uri); if (uri.s) pkg_free(uri.s); return ret; error: if (p) r_unlock(p->hash); if (uri.s) pkg_free(uri.s); ret=CSCF_RETURN_FALSE; return ret; }