message_put(message);
}
+/* port MESSAGE_3PTY */
+void EndpointAppPBX::port_3pty(struct port_list *portlist, int message_type, union parameter *param)
+{
+ logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
+
+ struct lcr_msg *message;
+ int rc;
+
+ rc = join_join();
+ message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_3PTY);
+ message->param.threepty.begin = 1;
+ if (rc < 0)
+ message->param.threepty.error = 1;
+ else
+ message->param.threepty.result = 1;
+ message->param.threepty.invoke_id = param->threepty.invoke_id;
+ logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
+ message_put(message);
+}
+
/* port MESSAGE_SUSPEND */
/* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
port_facility(portlist, message_type, param);
break;
+ case MESSAGE_3PTY:
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming 3PTY facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
+ port_3pty(portlist, message_type, param);
+ break;
+
/* PORT sends DTMF message */
case MESSAGE_DTMF: /* dtmf digits received */
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf digit=%c (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->dtmf, e_ext.number, e_callerinfo.id);
/* join calls (look for a join that is on hold (same isdn interface/terminal))
*/
-void EndpointAppPBX::join_join(void)
+int EndpointAppPBX::join_join(void)
{
#ifdef WITH_MISDN
struct lcr_msg *message;
our_join = find_join_id(ea_endpoint->ep_join_id);
if (!our_join) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
if (our_join->j_type != JOIN_TYPE_PBX) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
our_joinpbx = (class JoinPBX *)our_join;
if (!ea_endpoint->ep_portlist) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
if (!e_ext.number[0]) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
if (!our_port) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
if ((our_port->p_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_DSS1) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
our_pdss1 = (class Pdss1 *)our_port;
|| other_port->p_type==PORT_TYPE_DSS1_NT_IN) { /* port is isdn nt-mode */
other_pdss1 = (class Pdss1 *)other_port;
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of type isdn! comparing our portnum=%d with other's portnum=%d hold=%s ces=%d\n", ea_endpoint->ep_serial, our_pdss1->p_m_mISDNport->portnum, other_pdss1->p_m_mISDNport->portnum, (other_pdss1->p_m_hold)?"YES":"NO", other_pdss1->p_m_d_ces);
- if (other_pdss1->p_m_hold /* port is on hold */
+ if (1 //other_pdss1->p_m_hold /* port is on hold */
&& other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
&& other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
break;
}
if (!other_eapp) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn terminal.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port with same terminal found.\n", ea_endpoint->ep_serial);
/* if we have the same join */
if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we and the other have the same join.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
if (!other_join) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
if (other_join->j_type != JOIN_TYPE_PBX) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
other_joinpbx = (class JoinPBX *)other_join;
if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
/* remove relation to endpoint for join on hold */
#else
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no mISDN support anyway.\n", ea_endpoint->ep_serial);
#endif
+
+ return 0;
}
break;
#endif
+ case MESSAGE_3PTY:
+ if (param->threepty.begin)
+ trace_header("Begin3PTY", dir);
+ if (param->threepty.end)
+ trace_header("End3PTY", dir);
+ if (param->threepty.invoke)
+ add_trace("action", NULL, "invoke");
+ if (param->threepty.result)
+ add_trace("action", NULL, "result");
+ if (param->threepty.error)
+ add_trace("action", NULL, "error");
+ add_trace("invoke-id", NULL, "%d", param->threepty.invoke_id);
+ end_trace();
+ break;
+
default:
PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
}
void port_notify(struct port_list *portlist, int message_type, union parameter *param);
void port_progress(struct port_list *portlist, int message_type, union parameter *param);
void port_facility(struct port_list *portlist, int message_type, union parameter *param);
+ void port_3pty(struct port_list *portlist, int message_type, union parameter *param);
void port_suspend(struct port_list *portlist, int message_type, union parameter *param);
void port_resume(struct port_list *portlist, int message_type, union parameter *param);
void port_enablekeypad(struct port_list *portlist, int message_type, union parameter *param);
/* facility function */
void pick_join(char *extension);
- void join_join(void);
+ int join_join(void);
void encrypt_shared(void);
void encrypt_keyex(void);
void encrypt_off(void);
extern "C" {
}
#include <mISDN/q931.h>
+#include <mISDN/suppserv.h>
#ifdef OLD_MT_ASSIGN
extern unsigned int mt_assign_pid;
#endif
/* CC_FACILITY INDICATION */
void Pdss1::facility_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
{
- unsigned char facil[256];
- int facil_len;
+ unsigned char fac_ie[256];
+ struct asn1_parm fac;
+ int fac_len;
struct lcr_msg *message;
l1l2l3_trace_header(p_m_mISDNport, this, L3_FACILITY_IND, DIRECTION_IN);
- dec_ie_facility(l3m, facil, &facil_len);
+ dec_ie_facility(l3m, fac_ie + 1, &fac_len);
+ fac_ie[0] = fac_len;
end_trace();
/* facility */
- if (facil_len<=0)
+ if (fac_len<=0)
return;
+ decodeFac(fac_ie, &fac);
+ switch (fac.comp) {
+ case CompInvoke:
+ switch(fac.u.inv.operationValue) {
+ case Fac_Begin3PTY:
+ message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_3PTY);
+ message->param.threepty.begin = 1;
+ message->param.threepty.invoke = 1;
+ message->param.threepty.invoke_id = fac.u.inv.invokeId;
+ message_put(message);
+ return;
+
+ case Fac_End3PTY:
+ message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_3PTY);
+ message->param.threepty.end = 1;
+ message->param.threepty.invoke = 1;
+ message->param.threepty.invoke_id = fac.u.inv.invokeId;
+ message_put(message);
+ return;
+ default:
+ ;
+ }
+ break;
+ default:
+ ;
+ }
+
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_FACILITY);
- message->param.facilityinfo.len = facil_len;
- memcpy(message->param.facilityinfo.data, facil, facil_len);
+ message->param.facilityinfo.len = fac_len;
+ memcpy(message->param.facilityinfo.data, fac_ie, fac_len);
message_put(message);
}
p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_FACILITY, p_m_d_l3id, l3m);
}
+/* MESSAGE_3PTY */
+void Pdss1::message_3pty(unsigned int epoint_id, int message_id, union parameter *param)
+{
+ l3_msg *l3m;
+ unsigned char fac_ie[256];
+ struct asn1_parm fac;
+
+ /* encode 3PTY facility */
+ memset(&fac, 0, sizeof(fac));
+ fac.Valid = 1;
+ if (param->threepty.result) {
+ fac.comp = CompReturnResult;
+ fac.u.retResult.invokeId = param->threepty.invoke_id;
+ }
+ if (param->threepty.error) {
+ fac.comp = CompReturnError;
+ fac.u.retError.invokeId = param->threepty.invoke_id;
+ fac.u.retError.errorValue = FacError_Gen_InvalidCallState;
+ }
+ fac.u.retResult.operationValuePresent = 1;
+ if (param->threepty.begin)
+ fac.u.retResult.operationValue = Fac_Begin3PTY;
+ if (param->threepty.end)
+ fac.u.retResult.operationValue = Fac_End3PTY;
+ encodeFac(fac_ie, &fac);
+
+ /* sending facility */
+ l3m = create_l3msg();
+ l1l2l3_trace_header(p_m_mISDNport, this, L3_FACILITY_REQ, DIRECTION_OUT);
+ enc_ie_facility(l3m, fac_ie + 2, fac_ie[1]);
+ end_trace();
+ p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_FACILITY, p_m_d_l3id, l3m);
+}
+
/* MESSAGE_NOTIFY */
void Pdss1::message_notify(unsigned int epoint_id, int message_id, union parameter *param)
{
message_facility(epoint_id, message_id, param);
break;
+ case MESSAGE_3PTY: /* begin result message */
+ message_3pty(epoint_id, message_id, param);
+ break;
+
case MESSAGE_OVERLAP: /* more information is needed */
if (p_state!=PORT_STATE_IN_SETUP) {
break;
void message_setup(unsigned int epoint_id, int message_id, union parameter *param);
void message_notify(unsigned int epoint_id, int message_id, union parameter *param);
void message_facility(unsigned int epoint_id, int message_id, union parameter *param);
+ void message_3pty(unsigned int epoint_id, int message_id, union parameter *param);
void message_overlap(unsigned int epoint_id, int message_id, union parameter *param);
void message_proceeding(unsigned int epoint_id, int message_id, union parameter *param);
void message_alerting(unsigned int epoint_id, int message_id, union parameter *param);
unsigned char data[160]; /* 20ms */
};
+struct param_3pty {
+ int begin, end;
+ int invoke, result, error;
+ unsigned char invoke_id;
+};
+
/* structure of message parameter */
union parameter {
struct param_tone tone; /* MESSAGE_TONE */
struct param_newref newref; /* MESSAGE_NEWREF */
unsigned int bridge_id; /* MESSAGE_BRIDGE */
struct param_traffic traffic; /* MESSAGE_TRAFFIC */
+ struct param_3pty threepty; /* MESSAGE_TRAFFIC */
};
enum { /* message flow */
MESSAGE_NEWREF, /* special message to create and inform ref */
MESSAGE_BRIDGE, /* control port bridge */
MESSAGE_TRAFFIC, /* exchange bchannel traffic */
+ MESSAGE_3PTY, /* 3PTY call invoke */
};
#define MESSAGES static const char *messages_txt[] = { \
"MESSAGE_NEWREF", \
"MESSAGE_BRIDGE", \
"MESSAGE_TRAFFIC", \
+ "MESSAGE_3PTY", \
};