static inline int new_t(struct sip_msg *p_msg) { struct cell *new_cell; /* for ACK-dlw-wise matching, we want From-tags */ if (p_msg->REQ_METHOD==METHOD_INVITE && parse_from_header(p_msg)<0) { LOG(L_ERR, "ERROR: new_t: no valid From in INVITE\n"); return E_BAD_REQ; } /* make sure uri will be parsed before cloning */ if (parse_sip_msg_uri(p_msg)<0) { LOG(L_ERR, "ERROR: new_t: uri invalid\n"); return E_BAD_REQ; } /* add new transaction */ new_cell = build_cell( p_msg ) ; if ( !new_cell ){ LOG(L_ERR, "ERROR: new_t: out of mem:\n"); return E_OUT_OF_MEM; } insert_into_hash_table_unsafe( new_cell, p_msg->hash_index ); set_t(new_cell); INIT_REF_UNSAFE(T); /* init pointers to headers needed to construct local requests such as CANCEL/ACK */ init_new_t(new_cell, p_msg); return 1; }
/** * \brief Draws a layer of non-animated regions of tiles on the current map. */ void NonAnimatedRegions::draw_on_map() { // Check all grid cells that overlap the camera. const int num_rows = non_animated_tiles.get_num_rows(); const int num_columns = non_animated_tiles.get_num_columns(); const Rectangle& cell_size(non_animated_tiles.get_cell_size()); const Rectangle& camera_position = map.get_camera_position(); const int row1 = camera_position.get_y() / cell_size.get_height(); const int row2 = (camera_position.get_y() + camera_position.get_height()) / cell_size.get_height(); const int column1 = camera_position.get_x() / cell_size.get_width(); const int column2 = (camera_position.get_x() + camera_position.get_width()) / cell_size.get_width(); if (row1 > row2 || column1 > column2) { // No cell. return; } for (int i = row1; i <= row2; ++i) { if (i < 0 || i >= num_rows) { continue; } for (int j = column1; j <= column2; ++j) { if (j < 0 || j >= num_columns) { continue; } // Make sure this cell is built. int cell_index = i * num_columns + j; if (optimized_tiles_surfaces[cell_index] == NULL) { // Lazily build the cell. build_cell(cell_index); } const Rectangle cell_xy( j * cell_size.get_width(), i * cell_size.get_height() ); const Rectangle dst_position( cell_xy.get_x() - camera_position.get_x(), cell_xy.get_y() - camera_position.get_y() ); optimized_tiles_surfaces[cell_index]->draw( map.get_visible_surface(), dst_position ); } } }
/* * Send a request using data from the dialog structure */ int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp) { struct socket_info* send_sock; union sockaddr_union to_su; struct cell *new_cell; struct retr_buf *request; char* buf; int buf_len; int ret; unsigned int hi; ret=-1; /*** added by dcm * - needed by external ua to send a request within a dlg */ if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0) goto error2; send_sock = uri2sock(dialog->hooks.next_hop, &to_su, PROTO_NONE); if (!send_sock) { ret=ser_error; LOG(L_ERR, "t_uac: no socket found\n"); goto error2; } new_cell = build_cell(0); if (!new_cell) { ret=E_OUT_OF_MEM; LOG(L_ERR, "t_uac: short of cell shmem\n"); goto error2; } new_cell->completion_cb = cb; new_cell->cbp = cbp; /* cbp is installed -- tell error handling bellow not to free it */ cbp = 0; new_cell->is_invite = method->len == INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN) == 0; new_cell->local= 1; set_kr(REQ_FWDED); request = &new_cell->uac[0].request; request->dst.to = to_su; request->dst.send_sock = send_sock; request->dst.proto = send_sock->proto; request->dst.proto_reserved1 = 0; hi=dlg2hash(dialog); LOCK_HASH(hi); insert_into_hash_table_unsafe(new_cell, hi); UNLOCK_HASH(hi); buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len, send_sock); if (!buf) { LOG(L_ERR, "t_uac: Error while building message\n"); ret=E_OUT_OF_MEM; goto error1; } new_cell->method.s = buf; new_cell->method.len = method->len; request->buffer = buf; request->buffer_len = buf_len; new_cell->nr_of_outgoings++; if (SEND_BUFFER(request) == -1) { LOG(L_ERR, "t_uac: Attempt to send to '%.*s' failed\n", dialog->hooks.next_hop->len, dialog->hooks.next_hop->s ); } start_retr(request); return 1; error1: LOCK_HASH(hi); remove_from_hash_table_unsafe(new_cell); UNLOCK_HASH(hi); free_cell(new_cell); error2: /* if we did not install cbp, release it now */ if (cbp) shm_free(cbp); return ret; }
/* * Send a request using data from the dialog structure */ int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp,release_tmcb_param release_func) { union sockaddr_union to_su, new_to_su; struct cell *new_cell; struct cell *backup_cell; struct retr_buf *request; static struct sip_msg *req; struct usr_avp **backup; char *buf, *buf1; int buf_len, buf_len1; int ret, flags, sflag_bk; int backup_route_type; int sip_msg_len; unsigned int hi; struct socket_info *new_send_sock; str h_to, h_from, h_cseq, h_callid; struct proxy_l *proxy, *new_proxy; unsigned short dst_changed; ret=-1; /*** added by dcm * - needed by external ua to send a request within a dlg */ if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0) goto error3; if(dialog->obp.s) dialog->hooks.next_hop = &dialog->obp; LM_DBG("next_hop=<%.*s>\n",dialog->hooks.next_hop->len, dialog->hooks.next_hop->s); /* calculate the socket corresponding to next hop */ proxy = uri2proxy( dialog->hooks.next_hop, dialog->send_sock ? dialog->send_sock->proto : PROTO_NONE ); if (proxy==0) { ret=E_BAD_ADDRESS; goto error3; } /* use the first address */ hostent2su( &to_su, &proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT); /* check/discover the send socket */ if (dialog->send_sock) { /* if already set, the protocol of send sock must have the the same type as the proto required by destination URI */ if (proxy->proto != dialog->send_sock->proto) dialog->send_sock = NULL; } if (dialog->send_sock==NULL) { /* get the send socket */ dialog->send_sock = get_send_socket( NULL/*msg*/, &to_su, proxy->proto); if (!dialog->send_sock) { LM_ERR("no corresponding socket for af %d\n", to_su.s.sa_family); ser_error = E_NO_SOCKET; goto error2; } } LM_DBG("sending socket is %.*s \n", dialog->send_sock->name.len,dialog->send_sock->name.s); /* ***** Create TRANSACTION and all related ***** */ new_cell = build_cell( NULL/*msg*/, 1/*full UAS clone*/); if (!new_cell) { ret=E_OUT_OF_MEM; LM_ERR("short of cell shmem\n"); goto error2; } /* pass the transaction flags from dialog to transaction */ new_cell->flags |= dialog->T_flags; /* add the callback the transaction for LOCAL_COMPLETED event */ flags = TMCB_LOCAL_COMPLETED; /* Add also TMCB_LOCAL_RESPONSE_OUT if provisional replies are desired */ if (pass_provisional_replies || pass_provisional(new_cell)) flags |= TMCB_LOCAL_RESPONSE_OUT; if(cb && insert_tmcb(&(new_cell->tmcb_hl),flags,cb,cbp,release_func)!=1){ ret=E_OUT_OF_MEM; LM_ERR("short of tmcb shmem\n"); goto error2; } if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0) new_cell->flags |= T_IS_INVITE_FLAG; new_cell->flags |= T_IS_LOCAL_FLAG; request = &new_cell->uac[0].request; if (dialog->forced_to_su.s.sa_family == AF_UNSPEC) request->dst.to = to_su; else request->dst.to = dialog->forced_to_su; request->dst.send_sock = dialog->send_sock; request->dst.proto = dialog->send_sock->proto; request->dst.proto_reserved1 = 0; hi=dlg2hash(dialog); LOCK_HASH(hi); insert_into_hash_table_unsafe(new_cell, hi); UNLOCK_HASH(hi); /* copy AVPs into transaction */ new_cell->user_avps = dialog->avps; dialog->avps = NULL; /* ***** Create the message buffer ***** */ buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len); if (!buf) { LM_ERR("failed to build message\n"); ret=E_OUT_OF_MEM; goto error1; } if (local_rlist.a) { LM_DBG("building sip_msg from buffer\n"); req = buf_to_sip_msg(buf, buf_len, dialog); if (req==NULL) { LM_ERR("failed to build sip_msg from buffer\n"); } else { /* set this transaction as active one */ backup_cell = get_t(); set_t( new_cell ); /* set transaction AVP list */ backup = set_avp_list( &new_cell->user_avps ); /* backup script flags */ sflag_bk = getsflags(); /* disable parallel forking */ set_dset_state( 0 /*disable*/); /* run the route */ swap_route_type( backup_route_type, LOCAL_ROUTE); run_top_route( local_rlist.a, req); set_route_type( backup_route_type ); /* transfer current message context back to t */ new_cell->uac[0].br_flags = getb0flags(req); /* restore the prevoius active transaction */ set_t( backup_cell ); set_dset_state( 1 /*enable*/); setsflagsval(sflag_bk); set_avp_list( backup ); /* check for changes - if none, do not regenerate the buffer */ dst_changed = 1; if (req->new_uri.s || req->force_send_socket!=dialog->send_sock || req->dst_uri.len != dialog->hooks.next_hop->len || memcmp(req->dst_uri.s,dialog->hooks.next_hop->s,req->dst_uri.len) || (dst_changed=0)==0 || req->add_rm || req->body_lumps){ new_send_sock = NULL; /* do we also need to change the destination? */ if (dst_changed) { /* calculate the socket corresponding to next hop */ new_proxy = uri2proxy( req->dst_uri.s ? &(req->dst_uri) : &req->new_uri, PROTO_NONE ); if (new_proxy==0) goto abort_update; /* use the first address */ hostent2su( &new_to_su, &new_proxy->host, new_proxy->addr_idx, new_proxy->port ? new_proxy->port:SIP_PORT); /* get the send socket */ new_send_sock = get_send_socket( req, &new_to_su, new_proxy->proto); if (!new_send_sock) { free_proxy( new_proxy ); pkg_free( new_proxy ); LM_ERR("no socket found for the new destination\n"); goto abort_update; } } /* if interface change, we need to re-build the via */ if (new_send_sock && new_send_sock != dialog->send_sock) { LM_DBG("Interface change in local route -> " "rebuilding via\n"); if (!del_lump(req,req->h_via1->name.s - req->buf, req->h_via1->len,0)) { LM_ERR("Failed to remove initial via \n"); goto abort_update; } memcpy(req->add_to_branch_s,req->via1->branch->value.s, req->via1->branch->value.len); req->add_to_branch_len = req->via1->branch->value.len; /* update also info about new destination and send sock */ dialog->send_sock = new_send_sock; free_proxy( proxy ); pkg_free( proxy ); proxy = new_proxy; request->dst.send_sock = new_send_sock; request->dst.proto = new_send_sock->proto; request->dst.proto_reserved1 = 0; /* build the shm buffer now */ set_init_lump_flags(LUMPFLAG_BRANCH); buf1 = build_req_buf_from_sip_req(req, (unsigned int*)&buf_len1, new_send_sock, new_send_sock->proto, MSG_TRANS_SHM_FLAG); reset_init_lump_flags(); del_flaged_lumps( &req->add_rm, LUMPFLAG_BRANCH); } else { LM_DBG("Change in local route -> rebuilding buffer\n"); /* build the shm buffer now */ buf1 = build_req_buf_from_sip_req(req, (unsigned int*)&buf_len1, dialog->send_sock, dialog->send_sock->proto, MSG_TRANS_SHM_FLAG|MSG_TRANS_NOVIA_FLAG); /* now as it used, hide the original VIA header */ del_lump(req,req->h_via1->name.s - req->buf, req->h_via1->len, 0); } if (!buf1) { LM_ERR("no more shm mem\n"); /* keep original buffer */ goto abort_update; } /* update shortcuts */ if(!req->add_rm && !req->new_uri.s) { /* headers are not affected, simply tranlate */ new_cell->from.s = new_cell->from.s - buf + buf1; new_cell->to.s = new_cell->to.s - buf + buf1; new_cell->callid.s = new_cell->callid.s - buf + buf1; new_cell->cseq_n.s = new_cell->cseq_n.s - buf + buf1; } else { /* use heavy artilery :D */ if (extract_ftc_hdrs( buf1, buf_len1, &h_from, &h_to, &h_cseq, &h_callid)!=0 ) { LM_ERR("failed to update shortcut pointers\n"); shm_free(buf1); goto abort_update; } new_cell->from = h_from; new_cell->to = h_to; new_cell->callid = h_callid; new_cell->cseq_n = h_cseq; } /* here we rely on how build_uac_req() builds the first line */ new_cell->uac[0].uri.s = buf1 + req->first_line.u.request.method.len + 1; new_cell->uac[0].uri.len = GET_RURI(req)->len; /* update also info about new destination and send sock */ if (new_send_sock) request->dst.to = new_to_su; shm_free(buf); buf = buf1; buf_len = buf_len1; /* use new buffer */ } else { /* no changes over the message, buffer is already generated, just hide the original VIA for potential further branches */ del_lump(req,req->h_via1->name.s-req->buf,req->h_via1->len,0); } abort_update: /* save the SIP message into transaction */ new_cell->uas.request = sip_msg_cloner( req, &sip_msg_len, 1); if (new_cell->uas.request==NULL) { /* reset any T triggering */ new_cell->on_negative = 0; new_cell->on_reply = 0; } else { new_cell->uas.end_request= ((char*)new_cell->uas.request)+sip_msg_len; } /* no parallel support in UAC transactions */ new_cell->on_branch = 0; free_sip_msg(req); } } /* for DNS based failover, copy the DNS proxy into transaction */ if (!disable_dns_failover) { new_cell->uac[0].proxy = shm_clone_proxy( proxy, 1/*do_free*/); if (new_cell->uac[0].proxy==NULL) LM_ERR("failed to store DNS info -> no DNS based failover\n"); } new_cell->method.s = buf; new_cell->method.len = method->len; request->buffer.s = buf; request->buffer.len = buf_len; new_cell->nr_of_outgoings++; if(last_localT) { *last_localT = new_cell; REF_UNSAFE(new_cell); } if (SEND_BUFFER(request) == -1) { LM_ERR("attempt to send to '%.*s' failed\n", dialog->hooks.next_hop->len, dialog->hooks.next_hop->s); } if (method->len==ACK_LEN && memcmp(method->s, ACK, ACK_LEN)==0 ) { t_release_transaction(new_cell); } else { start_retr(request); } free_proxy( proxy ); pkg_free( proxy ); return 1; error1: LOCK_HASH(hi); remove_from_hash_table_unsafe(new_cell); UNLOCK_HASH(hi); free_cell(new_cell); error2: free_proxy( proxy ); pkg_free( proxy ); error3: return ret; }
/* Initialize the tree based on SPH particle list, using the particle * smoothing lengths to determine the depth of the grid anywhere */ void initialize_the_tree(void) { /* readsnap.c should set up the following: * Ngas = number of SPH gas particles * PG[i].hsml = smoothing length of gas particle i (in struct PG) * PG[i].pos[0,1,2] = x,y,z (respectively) positions of particle i */ int np,i,j,k,in_box_check,N_SUB_ID,nx,ny,nz,n_ID,PID,n_ID_sub,n_cell; int n_subshell_i,n_subshell_f,n_x[3]; extern struct CELL_STRUCT *CELL; if(!(CELL=(struct CELL_STRUCT *) malloc(All.N_gas*((int)(2.0/TREE_FRAC_HSML))*sizeof(struct CELL_STRUCT)))) { fprintf(stderr,"failed to allocate memory.\n"); exit(0); } int CURRENT_CELL_ID = 0; ALL_CELL_COUNTER = 1; for (j=0;j<3;j++) CELL[0].min_x[j] = -1.0*MAX_DISTANCE_FROM0; CELL[0].width = 2.0*MAX_DISTANCE_FROM0; CELL[0].sub_cell_check = 1; CELL[0].parent_ID = -1; for (nx=0;nx<N_SUBCELL;nx++) { for (ny=0;ny<N_SUBCELL;ny++) { for (nz=0;nz<N_SUBCELL;nz++) { n_ID_sub = nx*N_SUBCELL_2 + ny*N_SUBCELL + nz; n_ID = n_ID_sub + ALL_CELL_COUNTER; CELL[n_ID].parent_ID = 0; PID = CELL[n_ID].parent_ID; CELL[PID].sub_cell_IDs[n_ID_sub] = n_ID; CELL[n_ID].width = CELL[PID].width / N_SUBCELL; CELL[n_ID].N_particles_contained = 0; n_x[0] = nx; n_x[1] = ny; n_x[2] = nz; for (j=0;j<3;j++) { CELL[n_ID].min_x[j] = CELL[PID].min_x[j] + CELL[n_ID].width * n_x[j]; } }}} CELL[0].N_particles_contained = 0; /* Alright, so, the first run -- we have box ID 0, the big sucker, and we're inside it right now. Do a run of all the particles -- for each, decide which box it's in (dump that to the ticker for the sub-boxes counting how many particles go in them), check its h_sml, and also make sure it's inside the giant box itself */ for (np=0;np<All.N_gas;np++) { in_box_check = 1; for (j=0;j<3;j++) { n_x[j] = (int)((PG[np].pos[j] - CELL[0].min_x[j])/(CELL[0].width/N_SUBCELL)); if (n_x[j] < 0 || n_x[j] > N_SUBCELL-1) in_box_check = 0; } if (in_box_check != 0) { N_SUB_ID = n_x[0]*N_SUBCELL_2 + n_x[1]*N_SUBCELL + n_x[2]; CELL[0].N_particles_contained += 1; CELL[ALL_CELL_COUNTER + N_SUB_ID].N_particles_contained += 1; } } for (n_cell=ALL_CELL_COUNTER; n_cell<ALL_CELL_COUNTER+N_SUBCELL_3; n_cell++) { CELL[n_cell].hsml_min = 1.0e10; if (CELL[n_cell].N_particles_contained > 0) { if(!(CELL[n_cell].particle_IDs = (int *) malloc(CELL[n_cell].N_particles_contained*sizeof(int)))) { printf("Error allocating particle_IDs for cell %d in tree.c.\n",n_cell); exit(-1); } CELL[n_cell].N_particles_contained = 0; }} for (np=0;np<All.N_gas;np++) { in_box_check = 1; for (j=0;j<3;j++) { n_x[j] = (int)((PG[np].pos[j] - CELL[0].min_x[j])/(CELL[0].width/N_SUBCELL)); if (n_x[j] < 0 || n_x[j] > N_SUBCELL-1) in_box_check = 0; } if (in_box_check != 0) { N_SUB_ID = ALL_CELL_COUNTER + n_x[0]*N_SUBCELL_2 + n_x[1]*N_SUBCELL + n_x[2]; CELL[N_SUB_ID].particle_IDs[CELL[N_SUB_ID].N_particles_contained] = np; CELL[N_SUB_ID].N_particles_contained += 1; if (PG[np].hsml < CELL[N_SUB_ID].hsml_min) CELL[N_SUB_ID].hsml_min = PG[np].hsml; } } n_subshell_i = ALL_CELL_COUNTER; n_subshell_f = ALL_CELL_COUNTER + N_SUBCELL_3; ALL_CELL_COUNTER += N_SUBCELL_3; //printf("Tree opened, building... \n"); for (n_cell=n_subshell_i; n_cell<n_subshell_f; n_cell++) build_cell(n_cell); //printf("Tree constructed, %d total cells \n",ALL_CELL_COUNTER); TOTAL_NUMBER_OF_CELLS = ALL_CELL_COUNTER; return; }
/* The workhorse of the tree-building phase, this loops over itself to build a recursive tree over the grid and sets the gas values in the tree when a small enough scale is reached */ void build_cell(int cell_ID) { int nx,ny,nz,n_x[3],j,np,p_ID,n_ID_sub,n_ID,n_subshell_i,n_subshell_f,in_box_check; CELL[cell_ID].sub_cell_check = 1; if (CELL[cell_ID].N_particles_contained == 0) CELL[cell_ID].sub_cell_check = 0; if (CELL[cell_ID].width <= TREE_FRAC_HSML * CELL[cell_ID].hsml_min) CELL[cell_ID].sub_cell_check = 0; if (CELL[cell_ID].width <= TREE_MIN_SIZE) CELL[cell_ID].sub_cell_check = 0; if (CELL[cell_ID].sub_cell_check == 0) { get_tree_localvals(cell_ID); return; } /* ok, if we've made it this far, we need to build sub-cells for this particular cell. basically, follow the routine for the first set of sub-cells, with a few mods */ /* first set up the basic variables of the new cell */ for (nx=0;nx<N_SUBCELL;nx++) { for (ny=0;ny<N_SUBCELL;ny++) { for (nz=0;nz<N_SUBCELL;nz++) { n_ID_sub = nx*N_SUBCELL_2 + ny*N_SUBCELL + nz; n_ID = n_ID_sub + ALL_CELL_COUNTER; CELL[cell_ID].sub_cell_IDs[n_ID_sub] = n_ID; CELL[n_ID].parent_ID = cell_ID; CELL[n_ID].width = CELL[cell_ID].width / N_SUBCELL; CELL[n_ID].N_particles_contained = 0; n_x[0] = nx; n_x[1] = ny; n_x[2] = nz; for (j=0;j<3;j++) CELL[n_ID].min_x[j] = CELL[cell_ID].min_x[j] + CELL[n_ID].width * n_x[j]; }}} /* now loop over the gas particles in the cell and determine which sub-cells they belong to */ for (np=0; np<CELL[cell_ID].N_particles_contained; np++) { //printf("pidchk = %d %d %d %d \n",np,CELL[cell_ID].N_particles_contained,n_ID,CELL[n_ID].N_particles_contained); p_ID = CELL[cell_ID].particle_IDs[np]; in_box_check = 1; for (j=0;j<3;j++) { n_x[j] = (int)((PG[p_ID].pos[j] - CELL[cell_ID].min_x[j])/(CELL[cell_ID].width/N_SUBCELL)); if (n_x[j] < 0 || n_x[j] > N_SUBCELL-1) in_box_check = 0; } if (in_box_check != 0) { n_ID_sub = n_x[0]*N_SUBCELL_2 + n_x[1]*N_SUBCELL + n_x[2]; n_ID = n_ID_sub + ALL_CELL_COUNTER; CELL[n_ID].N_particles_contained += 1; } } for (n_ID=ALL_CELL_COUNTER; n_ID<ALL_CELL_COUNTER+N_SUBCELL_3; n_ID++) { CELL[n_ID].hsml_min = 1.0e10; if (CELL[n_ID].N_particles_contained > 0) { if(!(CELL[n_ID].particle_IDs = (int *) malloc(CELL[n_ID].N_particles_contained*sizeof(int)))) { printf("Error allocating particle_IDs for cell %d in tree.c.\n",n_ID); exit(-1); } CELL[n_ID].N_particles_contained = 0; } } for (np=0; np<CELL[cell_ID].N_particles_contained; np++) { p_ID = CELL[cell_ID].particle_IDs[np]; in_box_check = 1; for (j=0;j<3;j++) { n_x[j] = (int)((PG[p_ID].pos[j] - CELL[cell_ID].min_x[j])/(CELL[cell_ID].width/N_SUBCELL)); if (n_x[j] < 0 || n_x[j] > N_SUBCELL-1) in_box_check = 0; } if (in_box_check != 0) { n_ID_sub = n_x[0]*N_SUBCELL_2 + n_x[1]*N_SUBCELL + n_x[2]; n_ID = n_ID_sub + ALL_CELL_COUNTER; CELL[n_ID].particle_IDs[CELL[n_ID].N_particles_contained] = p_ID; CELL[n_ID].N_particles_contained += 1; if (PG[p_ID].hsml < CELL[n_ID].hsml_min) CELL[n_ID].hsml_min = PG[p_ID].hsml; }} n_subshell_i = ALL_CELL_COUNTER; n_subshell_f = ALL_CELL_COUNTER + N_SUBCELL_3; ALL_CELL_COUNTER += N_SUBCELL_3; //printf("Cell count = %d \n",ALL_CELL_COUNTER); for (n_ID=n_subshell_i; n_ID<n_subshell_f; n_ID++) build_cell(n_ID); return; }
/** * This function cancels a previously created local invite * transaction. The cancel parameter should NOT have any via (CANCEL is * hop by hop). returns 0 if error return >0 if OK (returns the LABEL of * the cancel).*/ unsigned int t_uac_cancel( str *headers, str *body, unsigned int cancelled_hashIdx, unsigned int cancelled_label, transaction_cb cb, void* cbp) { struct cell *t_invite,*cancel_cell; struct retr_buf *cancel,*invite; unsigned int len,ret; char *buf; ret=0; if(t_lookup_ident(&t_invite,cancelled_hashIdx,cancelled_label)<0){ LM_ERR("failed to t_lookup_ident hash_idx=%d," "label=%d\n", cancelled_hashIdx,cancelled_label); return 0; } /* <sanity_checks> */ if(! is_local(t_invite)) { LM_ERR("tried to cancel a non-local transaction\n"); goto error3; } if(t_invite->uac[0].last_received < 100) { LM_WARN("trying to cancel a transaction not in " "Proceeding state !\n"); goto error3; } if(t_invite->uac[0].last_received > 200) { LM_WARN("trying to cancel a completed transaction !\n"); goto error3; } /* </sanity_checks*/ /* <build_cell> */ if(!(cancel_cell = build_cell(0))){ ret=0; LM_ERR("no more shm memory!\n"); goto error3; } reset_avps(); if(cb && insert_tmcb(&(cancel_cell->tmcb_hl), TMCB_RESPONSE_IN|TMCB_LOCAL_COMPLETED,cb,cbp,0)!=1){ ret=0; LM_ERR("short of tmcb shmem !\n"); goto error2; } /* </build_cell> */ /* <insert_into_hashtable> */ cancel_cell->flags |= T_IS_LOCAL_FLAG; cancel_cell->hash_index=t_invite->hash_index; LOCK_HASH(cancel_cell->hash_index); insert_into_hash_table_unsafe(cancel_cell,cancel_cell->hash_index); ret=cancel_cell->label; cancel_cell->label=t_invite->label; UNLOCK_HASH(cancel_cell->hash_index); /* </insert_into_hashtable> */ /* <prepare_cancel> */ cancel=&cancel_cell->uac[0].request; invite=&t_invite->uac[0].request; cancel->dst.to = invite->dst.to; cancel->dst.send_sock = invite->dst.send_sock; cancel->dst.proto = invite->dst.proto; //cancel->dst.proto_reserved1 = invite->dst.proto_reserved1; if(!(buf = build_uac_cancel(headers,body,t_invite,0,&len, &(cancel->dst)))){ ret=0; LM_ERR("attempt to build a CANCEL failed\n"); goto error1; } cancel->buffer=buf; cancel->buffer_len=len; cancel_cell->method.s = buf; cancel_cell->method.len = 6 /*c-a-n-c-e-l*/; /* </prepare_cancel> */ /* <strart_sending> */ cancel_cell->nr_of_outgoings++; if (SEND_BUFFER(cancel)==-1) { ret=0; LM_ERR("send failed\n"); goto error1; } start_retr(cancel); /* </start_sending> */ return ret; error1: LOCK_HASH(cancel_cell->hash_index); remove_from_hash_table_unsafe(cancel_cell); UNLOCK_HASH(cancel_cell->hash_index); error2: free_cell(cancel_cell); error3: return ret; }
static inline int t_uac_prepare(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp, struct retr_buf **dst_req, struct cell **dst_cell) { struct dest_info dst; struct cell *new_cell; struct retr_buf *request; char* buf; int buf_len, ret, flags; unsigned int hi; int is_ack; #ifdef USE_DNS_FAILOVER struct dns_srv_handle dns_h; #endif ret=-1; hi=0; /* make gcc happy */ /*if (dst_req) *dst_req = NULL;*/ is_ack = (((method->len == 3) && (memcmp("ACK", method->s, 3)==0)) ? 1 : 0); /*** added by dcm * - needed by external ua to send a request within a dlg */ if (w_calculate_hooks(dialog)<0 && !dialog->hooks.next_hop) goto error2; if (!dialog->loc_seq.is_set) { /* this is the first request in the dialog, set cseq to default value now - Miklos */ dialog->loc_seq.value = DEFAULT_CSEQ; dialog->loc_seq.is_set = 1; } DBG("DEBUG:tm:t_uac: next_hop=<%.*s>\n",dialog->hooks.next_hop->len, dialog->hooks.next_hop->s); /* it's a new message, so we will take the default socket */ #ifdef USE_DNS_FAILOVER if (use_dns_failover){ dns_srv_handle_init(&dns_h); if ((uri2dst(&dns_h, &dst, 0, dialog->hooks.next_hop, PROTO_NONE)==0) || (dst.send_sock==0)){ dns_srv_handle_put(&dns_h); ser_error = E_NO_SOCKET; ret=ser_error; LOG(L_ERR, "t_uac: no socket found\n"); goto error2; } dns_srv_handle_put(&dns_h); /* not needed anymore */ }else{ if ((uri2dst(0, &dst, 0, dialog->hooks.next_hop, PROTO_NONE)==0) || (dst.send_sock==0)){ ser_error = E_NO_SOCKET; ret=ser_error; LOG(L_ERR, "t_uac: no socket found\n"); goto error2; } } #else if ((uri2dst(&dst, 0, dialog->hooks.next_hop, PROTO_NONE)==0) || (dst.send_sock==0)){ ser_error = E_NO_SOCKET; ret=ser_error; LOG(L_ERR, "t_uac: no socket found\n"); goto error2; } #endif new_cell = build_cell(0); if (!new_cell) { ret=E_OUT_OF_MEM; LOG(L_ERR, "t_uac: short of cell shmem\n"); goto error2; } /* init timers hack, new_cell->fr_timer and new_cell->fr_inv_timer * must be set, or else the fr will happen immediately * we can't call init_new_t() because we don't have a sip msg * => we'll ignore t_set_fr() or avp timer value and will use directly the * module params fr_inv_timer and fr_timer -- andrei */ new_cell->fr_timeout=fr_timeout; new_cell->fr_inv_timeout=fr_inv_timeout; /* better reset avp list now - anyhow, it's useless from * this point (bogdan) */ reset_avps(); /* add the callback the the transaction for LOCAL_COMPLETED event */ flags = TMCB_LOCAL_COMPLETED; /* Add also TMCB_LOCAL_REPLY_OUT if provisional replies are desired */ if (pass_provisional_replies) flags |= TMCB_LOCAL_RESPONSE_OUT; if(cb && insert_tmcb(&(new_cell->tmcb_hl), flags, cb, cbp)!=1){ ret=E_OUT_OF_MEM; LOG(L_ERR, "t_uac: short of tmcb shmem\n"); goto error2; } if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0) new_cell->flags |= T_IS_INVITE_FLAG; new_cell->flags |= T_IS_LOCAL_FLAG; set_kr(REQ_FWDED); request = &new_cell->uac[0].request; request->dst = dst; if (!is_ack) { hi=dlg2hash(dialog); LOCK_HASH(hi); insert_into_hash_table_unsafe(new_cell, hi); UNLOCK_HASH(hi); } buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len, &dst); if (!buf) { LOG(L_ERR, "t_uac: Error while building message\n"); ret=E_OUT_OF_MEM; goto error1; } new_cell->method.s = buf; new_cell->method.len = method->len; request->buffer = buf; request->buffer_len = buf_len; new_cell->nr_of_outgoings++; if (dst_req) *dst_req = request; if (dst_cell) *dst_cell = new_cell; return 1; error1: if (!is_ack) { LOCK_HASH(hi); remove_from_hash_table_unsafe(new_cell); UNLOCK_HASH(hi); } free_cell(new_cell); error2: return ret; }
/* * Send a request using data from the dialog structure */ int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp) { struct socket_info* send_sock; union sockaddr_union to_su; struct cell *new_cell; struct retr_buf *request; char* buf; int buf_len; int ret; unsigned int hi; ret=-1; /*** added by dcm * - needed by external ua to send a request within a dlg */ if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0) goto error2; DBG("DEBUG:tm:t_uac: next_hop=<%.*s>\n",dialog->hooks.next_hop->len, dialog->hooks.next_hop->s); /* it's a new message, so we will take the default socket */ send_sock = uri2sock(0, dialog->hooks.next_hop, &to_su, PROTO_NONE); if (!send_sock) { ret=ser_error; LOG(L_ERR, "t_uac: no socket found\n"); goto error2; } new_cell = build_cell(0); if (!new_cell) { ret=E_OUT_OF_MEM; LOG(L_ERR, "t_uac: short of cell shmem\n"); goto error2; } /* better reset avp list now - anyhow, it's useless from * this point (bogdan) */ reset_avps(); /* add the callback the the transaction for LOCAL_COMPLETED event */ if(cb && insert_tmcb(&(new_cell->tmcb_hl),TMCB_LOCAL_COMPLETED,cb,cbp)!=1){ ret=E_OUT_OF_MEM; LOG(L_ERR, "t_uac: short of tmcb shmem\n"); goto error2; } if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0) new_cell->flags |= T_IS_INVITE_FLAG; new_cell->flags |= T_IS_LOCAL_FLAG; set_kr(REQ_FWDED); request = &new_cell->uac[0].request; request->dst.to = to_su; request->dst.send_sock = send_sock; request->dst.proto = send_sock->proto; request->dst.proto_reserved1 = 0; hi=dlg2hash(dialog); LOCK_HASH(hi); insert_into_hash_table_unsafe(new_cell, hi); UNLOCK_HASH(hi); buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len, send_sock); if (!buf) { LOG(L_ERR, "t_uac: Error while building message\n"); ret=E_OUT_OF_MEM; goto error1; } new_cell->method.s = buf; new_cell->method.len = method->len; request->buffer = buf; request->buffer_len = buf_len; new_cell->nr_of_outgoings++; if (SEND_BUFFER(request) == -1) { LOG(L_ERR, "t_uac: Attempt to send to '%.*s' failed\n", dialog->hooks.next_hop->len, dialog->hooks.next_hop->s); } start_retr(request); return 1; error1: LOCK_HASH(hi); remove_from_hash_table_unsafe(new_cell); UNLOCK_HASH(hi); free_cell(new_cell); error2: return ret; }
/* WARNING: - dst_cell contains the created cell, but it is un-referenced * (before using it make sure you REF() it first) * - if ACK (method==ACK), a cell will be created but it will not * be added in the hash table (should be either deleted by the * caller) */ static inline int t_uac_prepare(uac_req_t *uac_r, struct retr_buf **dst_req, struct cell **dst_cell) { struct dest_info dst; struct cell *new_cell; struct retr_buf *request; char* buf; int buf_len, ret; unsigned int hi; int is_ack; ticks_t lifetime; #ifdef USE_DNS_FAILOVER struct dns_srv_handle dns_h; #endif long nhtype; #ifdef WITH_EVENT_LOCAL_REQUEST struct cell *backup_t; int backup_branch; unsigned int backup_msgid; static struct sip_msg lreq; char *buf1; int buf_len1; int sflag_bk; int backup_route_type; #endif snd_flags_t snd_flags; tm_xlinks_t backup_xd; tm_xdata_t local_xd; ret=-1; hi=0; /* make gcc happy */ /*if (dst_req) *dst_req = NULL;*/ is_ack = (((uac_r->method->len == 3) && (memcmp("ACK", uac_r->method->s, 3)==0)) ? 1 : 0); /*** added by dcm * - needed by external ua to send a request within a dlg */ if ((nhtype = w_calculate_hooks(uac_r->dialog)) < 0) /* if err's returned, the message is incorrect */ goto error2; if (!uac_r->dialog->loc_seq.is_set) { /* this is the first request in the dialog, set cseq to default value now - Miklos */ uac_r->dialog->loc_seq.value = DEFAULT_CSEQ; uac_r->dialog->loc_seq.is_set = 1; } DBG("DEBUG:tm:t_uac: next_hop=<%.*s>\n",uac_r->dialog->hooks.next_hop->len, uac_r->dialog->hooks.next_hop->s); /* new message => take the dialog send_socket if set, or the default send_socket if not*/ SND_FLAGS_INIT(&snd_flags); #ifdef USE_DNS_FAILOVER if (cfg_get(core, core_cfg, use_dns_failover)){ dns_srv_handle_init(&dns_h); if ((uri2dst2(&dns_h, &dst, uac_r->dialog->send_sock, snd_flags, uac_r->dialog->hooks.next_hop, PROTO_NONE)==0) || (dst.send_sock==0)){ dns_srv_handle_put(&dns_h); ser_error = E_NO_SOCKET; ret=ser_error; LOG(L_ERR, "t_uac: no socket found\n"); goto error2; } dns_srv_handle_put(&dns_h); /* not needed anymore */ }else{ if ((uri2dst2(0, &dst, uac_r->dialog->send_sock, snd_flags, uac_r->dialog->hooks.next_hop, PROTO_NONE)==0) || (dst.send_sock==0)){ ser_error = E_NO_SOCKET; ret=ser_error; LOG(L_ERR, "t_uac: no socket found\n"); goto error2; } } #else /* USE_DNS_FAILOVER */ if ((uri2dst2(&dst, uac_r->dialog->send_sock, snd_flags, uac_r->dialog->hooks.next_hop, PROTO_NONE)==0) || (dst.send_sock==0)){ ser_error = E_NO_SOCKET; ret=ser_error; LOG(L_ERR, "t_uac: no socket found\n"); goto error2; } #endif /* USE_DNS_FAILOVER */ /* build cell sets X/AVP lists to new transaction structure * => bakup in a tmp struct and restore afterwards */ memset(&local_xd, 0, sizeof(tm_xdata_t)); tm_xdata_replace(&local_xd, &backup_xd); new_cell = build_cell(0); tm_xdata_replace(0, &backup_xd); if (!new_cell) { ret=E_OUT_OF_MEM; LOG(L_ERR, "t_uac: short of cell shmem\n"); goto error2; } if (uac_r->method->len==INVITE_LEN && memcmp(uac_r->method->s, INVITE, INVITE_LEN)==0){ new_cell->flags |= T_IS_INVITE_FLAG; new_cell->flags|=T_AUTO_INV_100 & (!cfg_get(tm, tm_cfg, tm_auto_inv_100) -1); #ifdef WITH_AS_SUPPORT if (uac_r->cb_flags & TMCB_DONT_ACK) new_cell->flags |= T_NO_AUTO_ACK; #endif lifetime=cfg_get(tm, tm_cfg, tm_max_inv_lifetime); }else lifetime=cfg_get(tm, tm_cfg, tm_max_noninv_lifetime); new_cell->flags |= T_IS_LOCAL_FLAG; /* init timers hack, new_cell->fr_timer and new_cell->fr_inv_timer * must be set, or else the fr will happen immediately * we can't call init_new_t() because we don't have a sip msg * => we'll ignore t_set_fr() or avp timer value and will use directly the * module params fr_inv_timer and fr_timer -- andrei */ new_cell->fr_timeout=cfg_get(tm, tm_cfg, fr_timeout); new_cell->fr_inv_timeout=cfg_get(tm, tm_cfg, fr_inv_timeout); new_cell->end_of_life=get_ticks_raw()+lifetime; #ifdef TM_DIFF_RT_TIMEOUT /* same as above for retransmission intervals */ new_cell->rt_t1_timeout_ms = cfg_get(tm, tm_cfg, rt_t1_timeout_ms); new_cell->rt_t2_timeout_ms = cfg_get(tm, tm_cfg, rt_t2_timeout_ms); #endif set_kr(REQ_FWDED); request = &new_cell->uac[0].request; request->dst = dst; request->flags |= nhtype; if (!is_ack) { #ifdef TM_DEL_UNREF INIT_REF(new_cell, 1); /* ref'ed only from the hash */ #endif hi=dlg2hash(uac_r->dialog); LOCK_HASH(hi); insert_into_hash_table_unsafe(new_cell, hi); UNLOCK_HASH(hi); } buf = build_uac_req(uac_r->method, uac_r->headers, uac_r->body, uac_r->dialog, 0, new_cell, &buf_len, &dst); if (!buf) { LOG(L_ERR, "t_uac: Error while building message\n"); ret=E_OUT_OF_MEM; goto error1; } #ifdef WITH_EVENT_LOCAL_REQUEST if (unlikely(goto_on_local_req>=0)) { DBG("executing event_route[tm:local-request]\n"); if(likely(build_sip_msg_from_buf(&lreq, buf, buf_len, inc_msg_no()) == 0)) { /* fill some field in sip_msg */ if (unlikely(set_dst_uri(&lreq, uac_r->dialog->hooks.next_hop))) { LM_ERR("failed to set dst_uri"); free_sip_msg(&lreq); } else { struct onsend_info onsnd_info; lreq.force_send_socket = uac_r->dialog->send_sock; lreq.rcv.proto = dst.send_sock->proto; lreq.rcv.src_ip = dst.send_sock->address; lreq.rcv.src_port = dst.send_sock->port_no; lreq.rcv.dst_port = su_getport(&dst.to); su2ip_addr(&lreq.rcv.dst_ip, &dst.to); lreq.rcv.src_su=dst.send_sock->su; lreq.rcv.bind_address=dst.send_sock; #ifdef USE_COMP lreq.rcv.comp=dst.comp; #endif /* USE_COMP */ sflag_bk = getsflags(); tm_xdata_swap(new_cell, &backup_xd, 0); onsnd_info.to=&dst.to; onsnd_info.send_sock=dst.send_sock; onsnd_info.buf=buf; onsnd_info.len=buf_len; p_onsend=&onsnd_info; /* run the route */ backup_route_type = get_route_type(); set_route_type(LOCAL_ROUTE); /* set T to the current transaction */ backup_t=get_t(); backup_branch=get_t_branch(); backup_msgid=global_msg_id; /* fake transaction and message id */ global_msg_id=lreq.id; set_t(new_cell, T_BR_UNDEFINED); run_top_route(event_rt.rlist[goto_on_local_req], &lreq, 0); /* restore original environment */ set_t(backup_t, backup_branch); global_msg_id=backup_msgid; set_route_type( backup_route_type ); p_onsend=0; /* restore original environment */ tm_xdata_swap(new_cell, &backup_xd, 1); setsflagsval(sflag_bk); if (unlikely(lreq.new_uri.s)) { pkg_free(lreq.new_uri.s); lreq.new_uri.s=0; lreq.new_uri.len=0; } if (unlikely(lreq.dst_uri.s)) { pkg_free(lreq.dst_uri.s); lreq.dst_uri.s=0; lreq.dst_uri.len=0; } if (unlikely(lreq.add_rm || lreq.body_lumps)) { LM_DBG("apply new updates to sip msg\n"); buf1 = build_req_buf_from_sip_req(&lreq, (unsigned int*)&buf_len1, &dst, BUILD_NO_LOCAL_VIA|BUILD_NO_VIA1_UPDATE| BUILD_IN_SHM); if (likely(buf1)){ shm_free(buf); buf = buf1; buf_len = buf_len1; /* a possible change of the method is not handled! */ } } lreq.buf=0; /* covers the obsolete DYN_BUF */ free_sip_msg(&lreq); } } } #endif new_cell->method.s = buf; new_cell->method.len = uac_r->method->len; request->buffer = buf; request->buffer_len = buf_len; new_cell->nr_of_outgoings++; /* Register the callbacks after everything is successful and nothing can fail. Otherwise the callback parameter would be freed twise, once from TMCB_DESTROY, and again because of the negative return code. */ if(uac_r->cb && insert_tmcb(&(new_cell->tmcb_hl), uac_r->cb_flags, *(uac_r->cb), uac_r->cbp, NULL)!=1){ ret=E_OUT_OF_MEM; LOG(L_ERR, "t_uac: short of tmcb shmem\n"); goto error1; } if (has_local_reqin_tmcbs()) run_local_reqin_callbacks(new_cell, 0, 0); #ifdef DIALOG_CALLBACKS run_trans_dlg_callbacks(uac_r->dialog, new_cell, request); #endif /* DIALOG_CALLBACKS */ if (dst_req) *dst_req = request; if (dst_cell) *dst_cell = new_cell; else if(is_ack && dst_req==0){ free_cell(new_cell); } return 1; error1: if (!is_ack) { LOCK_HASH(hi); remove_from_hash_table_unsafe(new_cell); UNLOCK_HASH(hi); #ifdef TM_DEL_UNREF UNREF_FREE(new_cell); }else #else } #endif free_cell(new_cell); error2: return ret; }
/* * Send a request using data from the dialog structure */ int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp,release_tmcb_param release_func) { union sockaddr_union to_su; struct cell *new_cell; struct retr_buf *request; static struct sip_msg *req; struct usr_avp **backup; char *buf, *buf1; int buf_len, buf_len1; int ret, flags, sflag_bk; int backup_route_type; unsigned int hi; struct socket_info* send_sock; ret=-1; /*** added by dcm * - needed by external ua to send a request within a dlg */ if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0) goto error2; if(dialog->obp.s) dialog->hooks.next_hop = &dialog->obp; LM_DBG("next_hop=<%.*s>\n",dialog->hooks.next_hop->len, dialog->hooks.next_hop->s); /* calculate the socket corresponding to next hop */ send_sock = uri2sock(0, dialog->hooks.next_hop, &to_su, PROTO_NONE); if (send_sock==0) { ret=ser_error; LM_ERR("no socket found\n"); goto error2; } /* if a send socket defined verify if the same protocol */ if(dialog->send_sock) { if(send_sock->proto != dialog->send_sock->proto) { dialog->send_sock = send_sock; } } else { dialog->send_sock = send_sock; } new_cell = build_cell(0); if (!new_cell) { ret=E_OUT_OF_MEM; LM_ERR("short of cell shmem\n"); goto error2; } /* pass the transaction flags from dialog to transaction */ new_cell->flags |= dialog->T_flags; /* add the callback the transaction for LOCAL_COMPLETED event */ flags = TMCB_LOCAL_COMPLETED; /* Add also TMCB_LOCAL_RESPONSE_OUT if provisional replies are desired */ if (pass_provisional_replies || pass_provisional(new_cell)) flags |= TMCB_LOCAL_RESPONSE_OUT; if(cb && insert_tmcb(&(new_cell->tmcb_hl),flags,cb,cbp,release_func)!=1){ ret=E_OUT_OF_MEM; LM_ERR("short of tmcb shmem\n"); goto error2; } if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0) new_cell->flags |= T_IS_INVITE_FLAG; new_cell->flags |= T_IS_LOCAL_FLAG; request = &new_cell->uac[0].request; request->dst.to = to_su; request->dst.send_sock = dialog->send_sock; request->dst.proto = dialog->send_sock->proto; request->dst.proto_reserved1 = 0; hi=dlg2hash(dialog); LOCK_HASH(hi); insert_into_hash_table_unsafe(new_cell, hi); UNLOCK_HASH(hi); buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len); if (!buf) { LM_ERR("failed to build message\n"); ret=E_OUT_OF_MEM; goto error1; } if (local_rlist.a) { LM_DBG("building sip_msg from buffer\n"); req = buf_to_sip_msg(buf, buf_len, dialog); if (req==NULL) { LM_ERR("failed to build sip_msg from buffer"); } else { /* set transaction AVP list */ backup = set_avp_list( &new_cell->user_avps ); /* backup script flags */ sflag_bk = getsflags(); /* disable parallel forking */ set_dset_state( 0 /*disable*/); /* transfer current message context back to t */ new_cell->uac[0].br_flags = req->flags; /* run the route */ swap_route_type( backup_route_type, LOCAL_ROUTE); run_top_route( local_rlist.a, req); set_route_type( backup_route_type ); set_dset_state( 1 /*enable*/); setsflagsval(sflag_bk); set_avp_list( backup ); /* check for changes - if none, do not regenerate the buffer * we ignore any change on RURI and DSTURI and they should not * be changed -bogdan */ if (req->new_uri.s) { pkg_free(req->new_uri.s); req->new_uri.s=0; req->new_uri.len=0; } if (req->dst_uri.s) { pkg_free(req->dst_uri.s); req->dst_uri.s=0; req->dst_uri.len=0; } if (req->add_rm || req->body_lumps) { LM_DBG("re-building the buffer (sip_msg changed) - lumps are" "%p %p\n",req->add_rm, req->body_lumps); /* build the shm buffer now */ buf1 = build_req_buf_from_sip_req(req,(unsigned int*)&buf_len1, dialog->send_sock, dialog->send_sock->proto, MSG_TRANS_SHM_FLAG|MSG_TRANS_NOVIA_FLAG ); if (!buf1) { LM_ERR("no more shm mem\n"); /* keep original buffer */ } else { shm_free(buf); buf = buf1; buf_len = buf_len1; /* use new buffer */ } } free_sip_msg(req); } } new_cell->method.s = buf; new_cell->method.len = method->len; request->buffer.s = buf; request->buffer.len = buf_len; new_cell->nr_of_outgoings++; if(last_localT) { *last_localT = new_cell; REF_UNSAFE(new_cell); } if (SEND_BUFFER(request) == -1) { LM_ERR("attempt to send to '%.*s' failed\n", dialog->hooks.next_hop->len, dialog->hooks.next_hop->s); } if (method->len==ACK_LEN && memcmp(method->s, ACK, ACK_LEN)==0 ) { t_release_transaction(new_cell); } else { start_retr(request); } return 1; error1: LOCK_HASH(hi); remove_from_hash_table_unsafe(new_cell); UNLOCK_HASH(hi); free_cell(new_cell); error2: return ret; }