/*****************************************************************************\ ** ** ** LCR ** ** ** **---------------------------------------------------------------------------** ** Copyright: Andreas Eversberg ** ** ** ** mISDN remote ** ** ** \*****************************************************************************/ #include "main.h" unsigned int new_remote = 1000; /* * constructor */ Premote::Premote(int type, char *portname, struct port_settings *settings, struct interface *interface, int remote_id) : Port(type, portname, settings, interface) { union parameter param; p_callerinfo.itype = (interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN; p_r_ref = new_remote++; SCPY(p_r_remote_app, interface->remote_app); p_r_tones = (interface->is_tones == IS_YES); p_r_earlyb = (interface->is_earlyb == IS_YES); /* send new ref to remote socket */ memset(¶m, 0, sizeof(union parameter)); if (type == PORT_TYPE_REMOTE_OUT) param.newref.direction = 1; /* new ref from lcr */ p_r_remote_id = remote_id; if (admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_NEWREF, ¶m) < 0) FATAL("No socket with remote application '%s' found, this shall not happen. because we already created one.\n", p_r_remote_app); PDEBUG(DEBUG_PORT, "Created new RemotePort(%s).\n", portname); } /* * destructor */ Premote::~Premote() { PDEBUG(DEBUG_PORT, "Destroyed Remote process(%s).\n", p_name); } /* * endpoint sends messages to the port */ int Premote::message_epoint(unsigned int epoint_id, int message_type, union parameter *param) { struct epoint_list *epointlist; if (Port::message_epoint(epoint_id, message_type, param)) return 1; switch (message_type) { case MESSAGE_SETUP: struct interface *interface; interface = getinterfacebyname(p_interface_name); if (!interface) { PERROR("Cannot find interface %s.\n", p_interface_name); return 0; } /* attach only if not already */ epointlist = p_epointlist; while(epointlist) { if (epointlist->epoint_id == epoint_id) break; epointlist = epointlist->next; } if (!epointlist) epointlist_new(epoint_id); /* set context to pbx */ if (!param->setup.dialinginfo.context[0]) { if (interface->remote_context[0]) SCPY(param->setup.dialinginfo.context, interface->remote_context); else SCPY(param->setup.dialinginfo.context, "lcr"); } memcpy(&p_dialinginfo, ¶m->setup.dialinginfo, sizeof(p_dialinginfo)); memcpy(&p_capainfo, ¶m->setup.capainfo, sizeof(p_capainfo)); memcpy(&p_callerinfo, ¶m->setup.callerinfo, sizeof(p_callerinfo)); memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo)); /* screen */ do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_interface_name); do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_interface_name); do_screen(1, p_redirinfo.id, sizeof(p_redirinfo.id), &p_redirinfo.ntype, &p_redirinfo.present, p_interface_name); memcpy(¶m->setup.callerinfo, &p_callerinfo, sizeof(p_callerinfo)); memcpy(¶m->setup.redirinfo, &p_redirinfo, sizeof(p_redirinfo)); new_state(PORT_STATE_OUT_SETUP); break; case MESSAGE_PROCEEDING: new_state(PORT_STATE_IN_PROCEEDING); break; case MESSAGE_ALERTING: new_state(PORT_STATE_IN_ALERTING); break; case MESSAGE_CONNECT: memcpy(&p_connectinfo, ¶m->connectinfo, sizeof(p_connectinfo)); new_state(PORT_STATE_CONNECT); break; case MESSAGE_DISCONNECT: new_state(PORT_STATE_OUT_DISCONNECT); break; case MESSAGE_RELEASE: new_state(PORT_STATE_RELEASE); break; } /* look for Remote's interface */ if (admin_message_from_lcr(p_r_remote_id, p_r_ref, message_type, param)<0) { PERROR("No socket with remote application '%s' found, this shall not happen. Closing socket shall cause release of all remote ports.\n", p_r_remote_app); return 0; } if (message_type == MESSAGE_RELEASE) { new_state(PORT_STATE_RELEASE); delete this; return 0; } return 0; } void Premote::message_remote(int message_type, union parameter *param) { class Endpoint *epoint; struct lcr_msg *message; struct interface *interface; switch (message_type) { case MESSAGE_TRAFFIC: if (p_dov_rx) dov_rx(param->traffic.data, param->traffic.len); /* record audio */ if (p_record) record(param->traffic.data, param->traffic.len, 0); // from down if (p_tap) tap(param->traffic.data, param->traffic.len, 0); // from down bridge_tx(param->traffic.data, param->traffic.len); if (p_tone_name[0]) { read_audio(param->traffic.data, param->traffic.len); /* record audio */ if (p_record) record(param->traffic.data, param->traffic.len, 1); // from up if (p_tap) tap(param->traffic.data, param->traffic.len, 1); // from up admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_TRAFFIC, param); } else if (p_dov_tx) { /* use receeived traffic to trigger sending DOV */ dov_tx(param->traffic.data, param->traffic.len); admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_TRAFFIC, param); } return; case MESSAGE_SETUP: interface = getinterfacebyname(p_interface_name); if (!interface) { PERROR("Cannot find interface %s.\n", p_interface_name); return; } /* enable audio path */ if (interface->is_tones == IS_YES) { union parameter newparam; memset(&newparam, 0, sizeof(union parameter)); admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_PATTERN, &newparam); newparam.audiopath = 1; admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_AUDIOPATH, &newparam); } /* set source interface */ param->setup.callerinfo.itype = p_callerinfo.itype; SCPY(param->setup.callerinfo.interface, interface->name); /* create endpoint */ if (p_epointlist) FATAL("Incoming call but already got an endpoint.\n"); if (!(epoint = new Endpoint(p_serial, 0))) FATAL("No memory for Endpoint instance\n"); epoint->ep_app = new_endpointapp(epoint, 0, interface->app); //incoming epointlist_new(epoint->ep_serial); memcpy(&p_dialinginfo, ¶m->setup.dialinginfo, sizeof(p_dialinginfo)); memcpy(&p_capainfo, ¶m->setup.capainfo, sizeof(p_capainfo)); memcpy(&p_callerinfo, ¶m->setup.callerinfo, sizeof(p_callerinfo)); memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo)); new_state(PORT_STATE_IN_SETUP); break; case MESSAGE_PROCEEDING: new_state(PORT_STATE_OUT_PROCEEDING); break; case MESSAGE_ALERTING: new_state(PORT_STATE_OUT_ALERTING); break; case MESSAGE_CONNECT: memcpy(&p_connectinfo, ¶m->connectinfo, sizeof(p_connectinfo)); new_state(PORT_STATE_CONNECT); break; case MESSAGE_DISCONNECT: new_state(PORT_STATE_IN_DISCONNECT); break; case MESSAGE_RELEASE: new_state(PORT_STATE_RELEASE); break; } /* cannot just forward, because param is not of container "struct lcr_msg" */ message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, message_type); memcpy(&message->param, param, sizeof(message->param)); message_put(message); if (message_type == MESSAGE_RELEASE) { new_state(PORT_STATE_RELEASE); delete this; return; } } /* receive from remote Port instance */ int Premote::bridge_rx(unsigned char *data, int len) { union parameter newparam; int l; int ret; if ((ret = Port::bridge_rx(data, len))) return ret; /* send tones, if connected, or if early audio is enabled in proceeding/alerting state */ if (p_state != PORT_STATE_CONNECT && !(p_r_earlyb && (p_state == PORT_STATE_OUT_PROCEEDING || p_state == PORT_STATE_OUT_ALERTING)) && !(p_r_tones && (p_state == PORT_STATE_IN_PROCEEDING || p_state == PORT_STATE_IN_ALERTING))) return 0; if (p_tone_name[0]) return 0; memset(&newparam, 0, sizeof(union parameter)); /* split, if exeeds data size */ while(len) { l = (len > (int)sizeof(newparam.traffic.data)) ? sizeof(newparam.traffic.data) : len; newparam.traffic.len = l; len -= l; memcpy(newparam.traffic.data, data, l); data += l; /* record audio */ if (p_record) record(data, len, 1); // from up if (p_tap) tap(data, len, 1); // from up admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_TRAFFIC, &newparam); } return 0; }