/* epoint sends a message to a join * */ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union parameter *param) { class Join *cl; struct join_relation *relation, *reltemp; int num; int new_state; struct lcr_msg *message; // int size, writesize, oldpointer; char *number, *numbers; if (!epoint_id) { PERROR("software error, epoint == NULL\n"); return; } // if (options.deb & DEBUG_JOIN) { // PDEBUG(DEBUG_JOIN, "message %d received from ep%d.\n", message, epoint->ep_serial); // joinpbx_debug(join,"Join::message_epoint"); // } if (options.deb & DEBUG_JOIN) { if (message_type) { cl = join_first; while(cl) { if (cl->j_type == JOIN_TYPE_PBX) joinpbx_debug((class JoinPBX *)cl, "Join::message_epoint{all joins before processing}"); cl = cl->next; } } } /* check relation */ relation = j_relation; while(relation) { if (relation->epoint_id == epoint_id) break; relation = relation->next; } if (!relation) { PDEBUG(DEBUG_JOIN, "no relation back to the endpoint found, ignoring (join=%d, endpoint=%d)\n", j_serial, epoint_id); return; } /* count relations */ num=joinpbx_countrelations(j_serial); /* process party line */ if (message_type == MESSAGE_SETUP) if (param->setup.partyline && !j_partyline) { j_partyline = param->setup.partyline; j_partyline_jingle = param->setup.partyline_jingle; } if (j_partyline) { switch(message_type) { case MESSAGE_SETUP: PDEBUG(DEBUG_JOIN, "respsone with connect in partyline mode.\n"); relation->type = RELATION_TYPE_CONNECT; message = message_create(j_serial, epoint_id, JOIN_TO_EPOINT, MESSAGE_CONNECT); SPRINT(message->param.connectinfo.id, "%d", j_partyline); message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN; message_put(message); trigger_work(&j_updatebridge); if (j_partyline_jingle) play_jingle(1); break; case MESSAGE_AUDIOPATH: PDEBUG(DEBUG_JOIN, "join received channel message: %d.\n", param->audiopath); if (relation->channel_state != param->audiopath) { relation->channel_state = param->audiopath; trigger_work(&j_updatebridge); if (options.deb & DEBUG_JOIN) joinpbx_debug(this, "Join::message_epoint{after setting new channel state}"); } break; /* track notify */ case MESSAGE_NOTIFY: switch(param->notifyinfo.notify) { case INFO_NOTIFY_USER_SUSPENDED: case INFO_NOTIFY_USER_RESUMED: case INFO_NOTIFY_REMOTE_HOLD: case INFO_NOTIFY_REMOTE_RETRIEVAL: case INFO_NOTIFY_CONFERENCE_ESTABLISHED: case INFO_NOTIFY_CONFERENCE_DISCONNECTED: new_state = track_notify(relation->rx_state, param->notifyinfo.notify); if (new_state != relation->rx_state) { relation->rx_state = new_state; trigger_work(&j_updatebridge); if (options.deb & DEBUG_JOIN) joinpbx_debug(this, "Join::message_epoint{after setting new rx state}"); } break; } break; case MESSAGE_DISCONNECT: PDEBUG(DEBUG_JOIN, "releasing after receiving disconnect, because join in partyline mode.\n"); message = message_create(j_serial, epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE); message->param.disconnectinfo.cause = CAUSE_NORMAL; message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; message_put(message); // fall through case MESSAGE_RELEASE: PDEBUG(DEBUG_JOIN, "releasing from join\n"); release(relation, 0, 0); if (j_partyline_jingle) play_jingle(0); break; default: PDEBUG(DEBUG_JOIN, "ignoring message, because join in partyline mode.\n"); } return; } /* process messages */ switch(message_type) { /* process audio path message */ case MESSAGE_AUDIOPATH: PDEBUG(DEBUG_JOIN, "join received channel message: audiopath=%d, current relation's channel_state=%d\n", param->audiopath, relation->channel_state); if (relation->channel_state != param->audiopath) { relation->channel_state = param->audiopath; trigger_work(&j_updatebridge); if (options.deb & DEBUG_JOIN) joinpbx_debug(this, "Join::message_epoint{after setting new channel state}"); } return; /* track notify */ case MESSAGE_NOTIFY: switch(param->notifyinfo.notify) { case INFO_NOTIFY_USER_SUSPENDED: case INFO_NOTIFY_USER_RESUMED: case INFO_NOTIFY_REMOTE_HOLD: case INFO_NOTIFY_REMOTE_RETRIEVAL: case INFO_NOTIFY_CONFERENCE_ESTABLISHED: case INFO_NOTIFY_CONFERENCE_DISCONNECTED: new_state = track_notify(relation->rx_state, param->notifyinfo.notify); if (new_state != relation->rx_state) { relation->rx_state = new_state; trigger_work(&j_updatebridge); if (options.deb & DEBUG_JOIN) joinpbx_debug(this, "Join::message_epoint{after setting new rx state}"); } break; default: /* send notification to all other endpoints */ reltemp = j_relation; while(reltemp) { if (reltemp->epoint_id!=epoint_id && reltemp->epoint_id) { message = message_create(j_serial, reltemp->epoint_id, JOIN_TO_EPOINT, MESSAGE_NOTIFY); memcpy(&message->param, param, sizeof(union parameter)); message_put(message); } reltemp = reltemp->next; } } return; /* relations sends a connect */ case MESSAGE_CONNECT: /* outgoing setup type becomes connected */ if (relation->type == RELATION_TYPE_SETUP) relation->type = RELATION_TYPE_CONNECT; /* release other relations in setup state */ release_again: reltemp = j_relation; while(reltemp) { //printf("connect, checking relation %d\n", reltemp->epoint_id); if (reltemp->type == RELATION_TYPE_SETUP) { //printf("relation %d is of type setup, releasing\n", reltemp->epoint_id); /* send release to endpoint */ message = message_create(j_serial, reltemp->epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE); message->param.disconnectinfo.cause = CAUSE_NONSELECTED; message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; message_put(message); if (release(reltemp, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL)) // dummy cause, should not be used, since calling and connected endpoint still exist afterwards. return; // must return, because join IS destroyed goto release_again; } if (reltemp->type == RELATION_TYPE_CALLING) reltemp->type = RELATION_TYPE_CONNECT; reltemp = reltemp->next; } break; // continue with our message /* release is sent by endpoint */ case MESSAGE_RELEASE: switch(relation->type) { case RELATION_TYPE_SETUP: /* by called */ /* collect cause and send collected cause */ collect_cause(&j_multicause, &j_multilocation, param->disconnectinfo.cause, param->disconnectinfo.location); if (j_multicause) release(relation, j_multilocation, j_multicause); else release(relation, LOCATION_PRIVATE_LOCAL, CAUSE_UNSPECIFIED); break; case RELATION_TYPE_CALLING: /* by calling */ /* remove us, if we don't have a called releation yet */ if (!j_relation->next) { release(j_relation, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); return; // must return, because join IS destroyed } /* in a conf, we don't kill the other members */ if (num > 2 && !joinpbx_onecalling_othersetup(j_relation)) { release(relation, 0, 0); return; } /* remove all relations that are of called type */ release_again2: reltemp = j_relation; while(reltemp) { if (reltemp->type == RELATION_TYPE_SETUP) { /* send release to endpoint */ message = message_create(j_serial, reltemp->epoint_id, JOIN_TO_EPOINT, message_type); memcpy(&message->param, param, sizeof(union parameter)); message_put(message); if (release(reltemp, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL)) return; // must return, because join IS destroyed goto release_again2; } reltemp = reltemp->next; } PERROR("we are still here, this should not happen\n"); break; default: /* by connected */ /* send current cause */ release(relation, param->disconnectinfo.location, param->disconnectinfo.cause); } return; // must return, because join may be destroyed } /* check number of relations */ if (num > 2 && !joinpbx_onecalling_othersetup(j_relation) && message_type != MESSAGE_CONNECT) { PDEBUG(DEBUG_JOIN, "we are in a conference, so we ignore the messages, except MESSAGE_CONNECT.\n"); return; } /* if join has no other relation, we process the setup message */ if (num == 1) { switch(message_type) { case MESSAGE_SETUP: if (param->setup.dialinginfo.itype == INFO_ITYPE_ISDN_EXTENSION) { /* in case of keypad */ numbers = param->setup.dialinginfo.keypad; if (numbers[0]) { while((number = strsep(&numbers, ","))) { if (out_setup(epoint_id, message_type, param, NULL, number)) return; // join destroyed } /* after keypad finish dialing */ break; } /* dialed number */ numbers = param->setup.dialinginfo.id; while((number = strsep(&numbers, ","))) { if (out_setup(epoint_id, message_type, param, number, NULL)) return; // join destroyed } break; } if (out_setup(epoint_id, message_type, param, param->setup.dialinginfo.id, param->setup.dialinginfo.keypad)) return; // join destroyed break; default: PDEBUG(DEBUG_JOIN, "no need to send a message because there is no other endpoint than the calling one.\n"); } } else { /* sending message to other relation(s) */ relation = j_relation; while(relation) { if (relation->epoint_id != epoint_id) { PDEBUG(DEBUG_JOIN, "sending message ep%ld -> ep%ld.\n", epoint_id, relation->epoint_id); message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, message_type); memcpy(&message->param, param, sizeof(union parameter)); message_put(message); PDEBUG(DEBUG_JOIN, "message sent.\n"); } relation = relation->next; } } }
SEXP hitrun(SEXP alpha, SEXP initial, SEXP nbatch, SEXP blen, SEXP nspac, SEXP origin, SEXP basis, SEXP amat, SEXP bvec, SEXP outmat, SEXP debug) { if (! isReal(alpha)) error("argument \"alpha\" must be type double"); if (! isReal(initial)) error("argument \"initial\" must be type double"); if (! isInteger(nbatch)) error("argument \"nbatch\" must be type integer"); if (! isInteger(blen)) error("argument \"blen\" must be type integer"); if (! isInteger(nspac)) error("argument \"nspac\" must be type integer"); if (! isReal(origin)) error("argument \"origin\" must be type double"); if (! isReal(basis)) error("argument \"basis\" must be type double"); if (! isReal(amat)) error("argument \"amat\" must be type double"); if (! isReal(bvec)) error("argument \"bvec\" must be type double"); if (! (isNull(outmat) | isReal(outmat))) error("argument \"outmat\" must be type double or NULL"); if (! isLogical(debug)) error("argument \"debug\" must be logical"); if (! isMatrix(basis)) error("argument \"basis\" must be matrix"); if (! isMatrix(amat)) error("argument \"amat\" must be matrix"); if (! (isNull(outmat) | isMatrix(outmat))) error("argument \"outmat\" must be matrix or NULL"); int dim_oc = LENGTH(alpha); int dim_nc = LENGTH(initial); int ncons = nrows(amat); if (LENGTH(nbatch) != 1) error("argument \"nbatch\" must be scalar"); if (LENGTH(blen) != 1) error("argument \"blen\" must be scalar"); if (LENGTH(nspac) != 1) error("argument \"nspac\" must be scalar"); if (LENGTH(origin) != dim_oc) error("length(origin) != length(alpha)"); if (nrows(basis) != dim_oc) error("nrow(basis) != length(alpha)"); if (ncols(basis) != dim_nc) error("ncol(basis) != length(initial)"); if (ncols(amat) != dim_nc) error("ncol(amat) != length(initial)"); if (LENGTH(bvec) != ncons) error("length(bvec) != nrow(amat)"); if (LENGTH(debug) != 1) error("argument \"debug\" must be scalar"); int dim_out = dim_oc; if (! isNull(outmat)) { dim_out = nrows(outmat); if (ncols(outmat) != dim_oc) error("ncol(outmat) != length(alpha)"); } int int_nbatch = INTEGER(nbatch)[0]; int int_blen = INTEGER(blen)[0]; int int_nspac = INTEGER(nspac)[0]; int int_debug = LOGICAL(debug)[0]; double *dbl_star_alpha = REAL(alpha); double *dbl_star_initial = REAL(initial); double *dbl_star_origin = REAL(origin); double *dbl_star_basis = REAL(basis); double *dbl_star_amat = REAL(amat); double *dbl_star_bvec = REAL(bvec); int has_outmat = isMatrix(outmat); double *dbl_star_outmat = 0; if (has_outmat) dbl_star_outmat = REAL(outmat); if (int_nbatch <= 0) error("argument \"nbatch\" must be positive"); if (int_blen <= 0) error("argument \"blen\" must be positive"); if (int_nspac <= 0) error("argument \"nspac\" must be positive"); check_finite(dbl_star_alpha, dim_oc, "alpha"); check_positive(dbl_star_alpha, dim_oc, "alpha"); check_finite(dbl_star_initial, dim_nc, "initial"); check_finite(dbl_star_origin, dim_oc, "origin"); check_finite(dbl_star_basis, dim_oc * dim_nc, "basis"); check_finite(dbl_star_amat, ncons * dim_nc, "amat"); check_finite(dbl_star_bvec, ncons, "bvec"); if (has_outmat) check_finite(dbl_star_outmat, dim_out * dim_oc, "outmat"); double *state = (double *) R_alloc(dim_nc, sizeof(double)); double *proposal = (double *) R_alloc(dim_nc, sizeof(double)); double *batch_buffer = (double *) R_alloc(dim_out, sizeof(double)); double *out_buffer = (double *) R_alloc(dim_out, sizeof(double)); memcpy(state, dbl_star_initial, dim_nc * sizeof(double)); logh_setup(dbl_star_alpha, dbl_star_origin, dbl_star_basis, dim_oc, dim_nc); double current_log_dens = logh(state); out_setup(dbl_star_origin, dbl_star_basis, dbl_star_outmat, dim_oc, dim_nc, dim_out, has_outmat); SEXP result, resultnames, path, save_initial, save_final; if (! int_debug) { PROTECT(result = allocVector(VECSXP, 3)); PROTECT(resultnames = allocVector(STRSXP, 3)); } else { PROTECT(result = allocVector(VECSXP, 11)); PROTECT(resultnames = allocVector(STRSXP, 11)); } PROTECT(path = allocMatrix(REALSXP, dim_out, int_nbatch)); SET_VECTOR_ELT(result, 0, path); PROTECT(save_initial = duplicate(initial)); SET_VECTOR_ELT(result, 1, save_initial); UNPROTECT(2); SET_STRING_ELT(resultnames, 0, mkChar("batch")); SET_STRING_ELT(resultnames, 1, mkChar("initial")); SET_STRING_ELT(resultnames, 2, mkChar("final")); if (int_debug) { SEXP spath, ppath, zpath, u1path, u2path, s1path, s2path, gpath; int nn = int_nbatch * int_blen * int_nspac; PROTECT(spath = allocMatrix(REALSXP, dim_nc, nn)); SET_VECTOR_ELT(result, 3, spath); PROTECT(ppath = allocMatrix(REALSXP, dim_nc, nn)); SET_VECTOR_ELT(result, 4, ppath); PROTECT(zpath = allocMatrix(REALSXP, dim_nc, nn)); SET_VECTOR_ELT(result, 5, zpath); PROTECT(u1path = allocVector(REALSXP, nn)); SET_VECTOR_ELT(result, 6, u1path); PROTECT(u2path = allocVector(REALSXP, nn)); SET_VECTOR_ELT(result, 7, u2path); PROTECT(s1path = allocVector(REALSXP, nn)); SET_VECTOR_ELT(result, 8, s1path); PROTECT(s2path = allocVector(REALSXP, nn)); SET_VECTOR_ELT(result, 9, s2path); PROTECT(gpath = allocVector(REALSXP, nn)); SET_VECTOR_ELT(result, 10, gpath); UNPROTECT(8); SET_STRING_ELT(resultnames, 3, mkChar("current")); SET_STRING_ELT(resultnames, 4, mkChar("proposal")); SET_STRING_ELT(resultnames, 5, mkChar("z")); SET_STRING_ELT(resultnames, 6, mkChar("u1")); SET_STRING_ELT(resultnames, 7, mkChar("u2")); SET_STRING_ELT(resultnames, 8, mkChar("s1")); SET_STRING_ELT(resultnames, 9, mkChar("s2")); SET_STRING_ELT(resultnames, 10, mkChar("log.green")); } namesgets(result, resultnames); UNPROTECT(1); GetRNGstate(); if (current_log_dens == R_NegInf) error("log unnormalized density -Inf at initial state"); for (int ibatch = 0, k = 0; ibatch < int_nbatch; ibatch++) { for (int i = 0; i < dim_out; i++) batch_buffer[i] = 0.0; for (int jbatch = 0; jbatch < int_blen; jbatch++) { double proposal_log_dens; for (int ispac = 0; ispac < int_nspac; ispac++) { /* Note: should never happen! */ if (current_log_dens == R_NegInf) error("log density -Inf at current state"); double u1 = R_NaReal; double u2 = R_NaReal; double smax = R_NaReal; double smin = R_NaReal; double z[dim_nc]; propose(state, proposal, dbl_star_amat, dbl_star_bvec, dim_nc, ncons, z, &smax, &smin, &u1); proposal_log_dens = logh(proposal); int accept = FALSE; if (proposal_log_dens != R_NegInf) { if (proposal_log_dens >= current_log_dens) { accept = TRUE; } else { double green = exp(proposal_log_dens - current_log_dens); u2 = unif_rand(); accept = u2 < green; } } if (int_debug) { int l = ispac + int_nspac * (jbatch + int_blen * ibatch); int lbase = l * dim_nc; SEXP spath = VECTOR_ELT(result, 3); SEXP ppath = VECTOR_ELT(result, 4); SEXP zpath = VECTOR_ELT(result, 5); SEXP u1path = VECTOR_ELT(result, 6); SEXP u2path = VECTOR_ELT(result, 7); SEXP s1path = VECTOR_ELT(result, 8); SEXP s2path = VECTOR_ELT(result, 9); SEXP gpath = VECTOR_ELT(result, 10); for (int lj = 0; lj < dim_nc; lj++) { REAL(spath)[lbase + lj] = state[lj]; REAL(ppath)[lbase + lj] = proposal[lj]; REAL(zpath)[lbase + lj] = z[lj]; } REAL(u1path)[l] = u1; REAL(u2path)[l] = u2; REAL(s1path)[l] = smin; REAL(s2path)[l] = smax; REAL(gpath)[l] = proposal_log_dens - current_log_dens; } if (accept) { memcpy(state, proposal, dim_nc * sizeof(double)); current_log_dens = proposal_log_dens; } } /* end of inner loop (one iteration) */ outfun(state, out_buffer); for (int j = 0; j < dim_out; j++) batch_buffer[j] += out_buffer[j]; } /* end of middle loop (one batch) */ for (int j = 0; j < dim_out; j++, k++) REAL(path)[k] = batch_buffer[j] / int_blen; } /* end of outer loop */ PutRNGstate(); PROTECT(save_final = allocVector(REALSXP, dim_nc)); memcpy(REAL(save_final), state, dim_nc * sizeof(double)); SET_VECTOR_ELT(result, 2, save_final); UNPROTECT(5); return result; }