static Ret_t prv_start_message_cb(InstanceID_t id, VoidPtr_t userData, SmlSyncHdrPtr_t headerP) { internals_t * internP = (internals_t *)userData; SmlStatusPtr_t statusP; SmlChalPtr_t challengeP = NULL; char * dataStr; if (internP->reply_ref) { free(internP->reply_ref); } internP->sequence = NULL; internP->seq_code = 0; internP->reply_ref = smlPcdata2String(headerP->msgID); if (headerP->cred) { internP->srv_auth = check_credentials(headerP->cred, internP->account->toClientCred); challengeP= get_challenge(internP->account->toClientCred); store_nonce(internP->dmtreeH->MOs, internP->account, false); } dataStr = smlPcdata2String(headerP->respURI); if (dataStr) { set_new_uri(internP, dataStr); free(dataStr); } statusP = create_status(internP, internP->srv_auth, NULL); statusP->chal = challengeP; add_target_ref(statusP, headerP->target); add_source_ref(statusP, headerP->source); add_element(internP, (basicElement_t *)statusP); return SML_ERR_OK; }
int ds_select_dst_impl(struct sip_msg *msg, char *set_, char *alg_, int set_new) { extern int *ds_activelist; extern char ***ds_setp_a, ***ds_setp_b; extern int *ds_setlen_a, *ds_setlen_b; int set, alg; unsigned int hash; str uri; if(msg==NULL) { LOG(L_ERR, "DISPATCHER:ds_select_dst: bad parameters\n"); return -1; } if ( get_int_fparam(&set, msg, (fparam_t*)set_) < 0 ) { LOG(L_ERR, "DISPATCHER:ds_select_dst: bad set value (%d)\n", set); return -1; } if ( get_int_fparam(&alg, msg, (fparam_t*)alg_) < 0 ) { LOG(L_ERR, "DISPATCHER:ds_select_dst: bad algorithm (%d)\n", alg); return -1; } if ((set < 0) || (set >= DS_MAX_SETS)) { LOG(L_ERR, "DISPATCHER:ds_select_dst: bad set offset (%d)\n", set); return -1; } if ((alg < 0) || (alg > 4)) { LOG(L_ERR, "DISPATCHER:ds_select_dst: invalid algorithm\n"); return -1; } if (((*ds_activelist == 0) ? ds_setlen_a[set] : ds_setlen_b[set]) <= 0) { LOG(L_ERR, "DISPATCHER:ds_select_dst: empty destination set\n"); return -1; } if (msg->dst_uri.s != NULL || msg->dst_uri.len > 0) { if (msg->dst_uri.s) pkg_free(msg->dst_uri.s); msg->dst_uri.s = NULL; msg->dst_uri.len = 0; } /* get hash */ hash = 0; switch (alg) { /* see bottom for case '0' */ case 1: /* hash from uri */ if (ds_hash_fromuri(msg, &hash) != 0) { if (ds_hash_callid(msg, &hash) != 0) { LOG(L_ERR, "DISPATCHER:ds_select_dst: cannot determine from uri hash\n"); return -1; } } break; case 2: /* hash to uri */ if (ds_hash_touri(msg, &hash) != 0) { if (ds_hash_callid(msg, &hash) != 0) { LOG(L_ERR, "DISPATCHER:ds_select_dst: cannot determine from uri hash\n"); return -1; } } break; case 3: /* hash Request uri */ if (ds_hash_ruri(msg, &hash) != 0) { if (ds_hash_callid(msg, &hash) != 0) { LOG(L_ERR, "DISPATCHER:ds_select_dst: cannot determine from uri hash\n"); return -1; } } break; case 4: /* Call ID hash, shifted right once to skip low bit * This should allow for even distribution when using * Call ID hash twice (i.e. fe + be) */ if (ds_hash_callid(msg, &hash) != 0) { LOG(L_ERR, "DISPATCHER:ds_select_dst: cannot determine callid hash\n"); hash = 0; /* bad default, just to be sure */ return -1; } hash = hash >> 4; /* should be enough for even more backends */ break; case 0: /* hash call id */ /* fall-through */ default: if (ds_hash_callid(msg, &hash) != 0) { LOG(L_ERR, "DISPATCHER:ds_select_dst: cannot determine callid hash\n"); hash = 0; /* bad default, just to be sure */ return -1; } break; /* make gcc happy */ } DBG("DISPATCHER:ds_select_dst: hash: [%u]\n", hash); /* node list offset from hash */ if (*ds_activelist == 0) { hash = hash % ds_setlen_a[set]; uri.s = ds_setp_a[set][hash]; uri.len = strlen(ds_setp_a[set][hash]); } else { hash = hash % ds_setlen_b[set]; uri.s = ds_setp_b[set][hash]; uri.len = strlen(ds_setp_b[set][hash]); } if (!set_new) { if (set_dst_uri(msg, &uri) < 0) { LOG(L_ERR, "DISPATCHER:dst_select_dst: Error while setting dst_uri\n"); return -1; } /* dst_uri changed, so it makes sense to re-use the current uri for forking */ ruri_mark_new(); /* re-use uri for serial forking */ DBG("DISPATCHER:ds_select_dst: selected [%d-%d-%d] <%.*s>\n", alg, set, hash, msg->dst_uri.len, msg->dst_uri.s); } else { if (set_new_uri(msg, &uri) < 0) { LOG(L_ERR, "DISPATCHER:dst_select_dst: Error while setting new_uri\n"); return -1; } DBG("DISPATCHER:ds_select_dst: selected [%d-%d-%d] <%.*s>\n", alg, set, hash, msg->new_uri.len, msg->dst_uri.s); } return 1; }
int ds_select_dst_impl(struct sip_msg *msg, char *set, char *alg, int set_new) { int a, s, idx; ds_setidx_p si = NULL; unsigned int hash; if(msg==NULL) { LOG(L_ERR, "DISPATCHER:ds_select_dst: bad parameters\n"); return -1; } if(_ds_list==NULL || _ds_index==NULL) { LOG(L_ERR, "DISPATCHER:ds_select_dst: no destination sets\n"); return -1; } if((force_dst==0) && (msg->dst_uri.s!=NULL || msg->dst_uri.len>0)) { LOG(L_ERR, "DISPATCHER:ds_select_dst: destination already set [%.*s]\n", msg->dst_uri.len, msg->dst_uri.s); return -1; } get_int_fparam(&s, msg, (fparam_t*)set); get_int_fparam(&a, msg, (fparam_t*)alg); /* get the index of the set */ si = _ds_index; while(si) { if(si->id == s) { idx = si->index; break; } si = si->next; } if(si==NULL) { LOG(L_ERR, "DISPATCHER:ds_select_dst: destination set [%d] not found\n",s); return -1; } DBG("DISPATCHER:ds_select_dst: set index [%d]\n", idx); hash = 0; switch(a) { case 0: if(ds_hash_callid(msg, &hash)!=0) { LOG(L_ERR, "DISPATCHER:ds_select_dst: can't get callid hash\n"); return -1; } break; case 1: if(ds_hash_fromuri(msg, &hash)!=0) { LOG(L_ERR, "DISPATCHER:ds_select_dst: can't get From uri hash\n"); return -1; } break; case 2: if(ds_hash_touri(msg, &hash)!=0) { LOG(L_ERR, "DISPATCHER:ds_select_dst: can't get To uri hash\n"); return -1; } break; case 3: if (ds_hash_ruri(msg, &hash)!=0) { LOG(L_ERR, "DISPATCHER:ds_select_dst: can't get ruri hash\n"); return -1; } break; default: LOG(L_WARN, "WARNING: ds_select_dst: algo %d not implemented" " using callid hashing instead...\n", a); hash = 0; } DBG("DISPATCHER:ds_select_dst: alg hash [%u]\n", hash); hash = hash%_ds_list[idx].nr; if (!set_new) { if (set_dst_uri(msg, &_ds_list[idx].dlist[hash].uri) < 0) { LOG(L_ERR, "DISPATCHER:dst_select_dst: Error while setting dst_uri\n"); return -1; } DBG("DISPATCHER:ds_select_dst: selected [%d-%d/%d/%d] <%.*s>\n", a, s, idx, hash, msg->dst_uri.len, msg->dst_uri.s); } else { if (set_new_uri(msg, &_ds_list[idx].dlist[hash].uri) < 0) { LOG(L_ERR, "DISPATCHER:dst_select_dst: Error while setting new_uri\n"); return -1; } DBG("DISPATCHER:ds_select_new: selected [%d-%d/%d/%d] <%.*s>\n", a, s, idx, hash, msg->new_uri.len, msg->new_uri.s); } return 1; }