From 30224b43e26f8b942da6770ac57eb3e17fcb259e Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sat, 28 Jul 2012 16:24:06 +0200 Subject: [PATCH] Add 3PTY facility to invoke conference call via functional protocol --- apppbx.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++---------- apppbx.h | 3 ++- dss1.cpp | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- dss1.h | 1 + message.h | 9 +++++++ 5 files changed, 141 insertions(+), 20 deletions(-) diff --git a/apppbx.cpp b/apppbx.cpp index 8a8d3e9..b53d5ce 100644 --- a/apppbx.cpp +++ b/apppbx.cpp @@ -2394,6 +2394,26 @@ void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, 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) @@ -2496,6 +2516,11 @@ void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, uni 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); @@ -3535,7 +3560,7 @@ reject: /* 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; @@ -3551,29 +3576,29 @@ void EndpointAppPBX::join_join(void) 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; @@ -3594,7 +3619,7 @@ void EndpointAppPBX::join_join(void) || 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; @@ -3609,28 +3634,28 @@ void EndpointAppPBX::join_join(void) } 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 */ @@ -3691,6 +3716,8 @@ void EndpointAppPBX::join_join(void) #else PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no mISDN support anyway.\n", ea_endpoint->ep_serial); #endif + + return 0; } @@ -4184,6 +4211,21 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign 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); } diff --git a/apppbx.h b/apppbx.h index 58d7ebd..6e4e12d 100644 --- a/apppbx.h +++ b/apppbx.h @@ -211,6 +211,7 @@ class EndpointAppPBX : public EndpointApp 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); @@ -307,7 +308,7 @@ class EndpointAppPBX : public EndpointApp /* 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); diff --git a/dss1.cpp b/dss1.cpp index 6adbf1f..51b43a1 100644 --- a/dss1.cpp +++ b/dss1.cpp @@ -16,6 +16,7 @@ extern "C" { } #include +#include #ifdef OLD_MT_ASSIGN extern unsigned int mt_assign_pid; #endif @@ -1641,21 +1642,50 @@ void Pdss1::resume_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m) /* 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); } @@ -2284,6 +2314,40 @@ void Pdss1::message_facility(unsigned int epoint_id, int message_id, union param 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) { @@ -2806,6 +2870,10 @@ int Pdss1::message_epoint(unsigned int epoint_id, int message_id, union paramete 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; diff --git a/dss1.h b/dss1.h index f2486ab..2f5901d 100644 --- a/dss1.h +++ b/dss1.h @@ -56,6 +56,7 @@ class Pdss1 : public PmISDN 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); diff --git a/message.h b/message.h index 464285f..ab4ca7e 100644 --- a/message.h +++ b/message.h @@ -343,6 +343,12 @@ struct param_traffic { 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 */ @@ -369,6 +375,7 @@ union parameter { 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 */ @@ -423,6 +430,7 @@ enum { /* messages between entities */ 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[] = { \ @@ -459,6 +467,7 @@ enum { /* messages between entities */ "MESSAGE_NEWREF", \ "MESSAGE_BRIDGE", \ "MESSAGE_TRAFFIC", \ + "MESSAGE_3PTY", \ }; -- 2.13.6