#include <sys/socket.h>
#include <sys/un.h>
#include <curses.h>
+#ifdef PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#endif
#include "config.h"
/*
* free connection
- * also releases all remote joins
*/
void free_connection(struct admin_list *admin)
{
struct admin_queue *response;
void *temp;
union parameter param;
- class Join *join, *joinnext;
- struct mISDNport *mISDNport;
- int i, ii;
+ class Port *port, *portnext;
+ class Premote *remote;
struct admin_list **adminp;
- /* free remote joins */
+ /* free remote ports */
if (admin->remote_name[0]) {
start_trace(-1,
NULL,
"REMOTE APP release");
add_trace("app", "name", "%s", admin->remote_name);
end_trace();
- /* release all exported channels */
- mISDNport = mISDNport_first;
- while(mISDNport) {
- i = 0;
- ii = mISDNport->b_num;
- while(i < ii) {
- if (mISDNport->b_remote_id[i] == admin->sock) {
- mISDNport->b_state[i] = B_STATE_IDLE;
- unsched_timer(&mISDNport->b_timer[i]);
- mISDNport->b_remote_id[i] = 0;
- mISDNport->b_remote_ref[i] = 0;
+ /* release remote port */
+ port = port_first;
+ while(port) {
+ portnext = port->next;
+ if ((port->p_type & PORT_CLASS_MASK) == PORT_CLASS_REMOTE) {
+ remote = (class Premote *) port;
+ if (remote->p_r_remote_id == admin->sock) {
+ memset(¶m, 0, sizeof(param));
+ param.disconnectinfo.cause = CAUSE_OUTOFORDER;
+ param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+ remote->message_remote(MESSAGE_RELEASE, ¶m);
+ /* port is now destroyed, so we go to next join */
}
- i++;
- }
- mISDNport = mISDNport->next;
- }
- /* release join */
- join = join_first;
- while(join) {
- joinnext = join->next;
- if (join->j_type==JOIN_TYPE_REMOTE) if (((class JoinRemote *)join)->j_remote_id == admin->sock) {
- memset(¶m, 0, sizeof(param));
- param.disconnectinfo.cause = CAUSE_OUTOFORDER;
- param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
- ((class JoinRemote *)join)->message_remote(MESSAGE_RELEASE, ¶m);
- /* join is now destroyed, so we go to next join */
}
- join = joinnext;
+ port = portnext;
}
}
case ACTION_EXTERNAL:
apppbx->e_action = &action_external;
break;
- case ACTION_REMOTE:
- apppbx->e_action = &action_remote;
- break;
case ACTION_VBOX_RECORD:
apppbx->e_action = &action_vbox;
break;
goto out;
}
+#ifdef WITH_MISDN
/* no interface */
if (!ifport->mISDNport) {
/* not loaded anyway */
/* try loading interface */
ifport->block = block;
- load_port(ifport);
+ load_mISDN_port(ifport);
/* port cannot load */
if (ifport->block >= 2) {
ifport->block = 2;
goto out;
}
+#endif
/* port new blocking state */
ifport->block = response->am[0].u.x.block = block;
if (!(epoint = new Endpoint(0, 0)))
FATAL("No memory for Endpoint instance\n");
- if (!(epoint->ep_app = apppbx = new DEFAULT_ENDPOINT_APP(epoint, 1))) // outgoing
+ if (!(epoint->ep_app = apppbx = new EndpointAppPBX(epoint, 1))) // outgoing
FATAL("No memory for Endpoint Application instance\n");
apppbx->e_adminid = admin->sockserial;
admin->epointid = epoint->ep_serial;
/*
* send data to the remote socket join instance
*/
-int admin_message_to_join(struct admin_msg *msg, struct admin_list *admin)
+int admin_message_to_lcr(struct admin_msg *msg, struct admin_list *admin)
{
- class Join *join;
+ class Port *port;
+ class Premote *remote = NULL; /* make GCC happy */
+ struct interface *interface;
struct admin_list *temp;
/* hello message */
return(-1);
}
- /* new join */
+ /* new remote instance. the reply (NEWREF assignment) is sent from constructor */
if (msg->type == MESSAGE_NEWREF) {
- /* create new join instance */
- join = new JoinRemote(0, admin->remote_name, admin->sock); // must have no serial, because no endpoint is connected
- if (!join) {
- FATAL("No memory for remote join instance\n");
- return(-1);
+ char name[32];
+ /* find remote port */
+ interface = interface_first;
+ while(interface) {
+ /* interface must match the remote application */
+ if (interface->remote && !strcmp(interface->remote_app, admin->remote_name)) {
+ /* interface must match the name, if given */
+ if (!msg->param.newref.interface[0] || !strcmp(msg->param.newref.interface, interface->name))
+ break;
+ }
+ interface = interface->next;
}
- return(0);
- }
+ if (!interface) {
+ union parameter param;
+ unsigned int ref = new_remote++;
+
+ start_trace(-1,
+ NULL,
+ NULL,
+ NULL,
+ DIRECTION_NONE,
+ 0,
+ 0,
+ "REMOTE APP illegal interface");
+ add_trace("app", "name", "%s", admin->remote_name);
+ add_trace("interface", "name", "%s", msg->param.newref.interface);
+ end_trace();
+ memset(¶m, 0, sizeof(union parameter));
+ param.newref.direction = 0;
+ admin_message_from_lcr(admin->sock, ref, MESSAGE_NEWREF, ¶m);
+ memset(¶m, 0, sizeof(union parameter));
+ param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+ param.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL;
+ admin_message_from_lcr(admin->sock, ref, MESSAGE_RELEASE, ¶m);
+ return 0;
+ }
+ /* creating port object, transparent until setup with hdlc */
+ SPRINT(name, "%s-%s-in", interface->name, interface->remote_app);
+ if (!(remote = new Premote(PORT_TYPE_REMOTE_IN, name, NULL, interface, admin->sock)))
- /* bchannel message
- * no ref given for *_ack */
- if (msg->type == MESSAGE_BCHANNEL)
- if (msg->param.bchannel.type == BCHANNEL_ASSIGN_ACK
- || msg->param.bchannel.type == BCHANNEL_REMOVE_ACK
- || msg->param.bchannel.type == BCHANNEL_RELEASE) {
- /* no ref, but address */
- message_bchannel_from_remote(NULL, msg->param.bchannel.type, msg->param.bchannel.handle);
+ FATAL("Cannot create Port instance.\n");
return(0);
}
-
+
/* check for ref */
if (!msg->ref) {
PERROR("Remote application did not send us a valid ref with a message.\n");
return(-1);
}
- /* find join instance */
- join = join_first;
- while(join) {
- if (join->j_serial == msg->ref)
- break;
- join = join->next;
- }
- if (!join) {
- PDEBUG(DEBUG_LOG, "No join found with serial %d. (May have been already released.)\n", msg->ref);
- return(0);
+ /* find port instance */
+ port = port_first;
+ while(port) {
+ if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_REMOTE) {
+ remote = (class Premote *) port;
+ if (remote->p_r_ref == msg->ref)
+ break;
+ }
+ port = port->next;
}
+ if (port) {
+ if (admin->sock != remote->p_r_remote_id) {
+ PERROR("Ref %d belongs to remote application %s, but not to sending application %s.\n", msg->ref, remote->p_r_remote_app, admin->remote_name);
+ return(-1);
+ }
- /* check application */
- if (join->j_type != JOIN_TYPE_REMOTE) {
- PERROR("Ref %d does not belong to a remote join instance.\n", msg->ref);
- return(-1);
- }
- if (admin->sock != ((class JoinRemote *)join)->j_remote_id) {
- PERROR("Ref %d belongs to remote application %s, but not to sending application %s.\n", msg->ref, ((class JoinRemote *)join)->j_remote_name, admin->remote_name);
- return(-1);
- }
+ /* send message */
+ remote->message_remote(msg->type, &msg->param);
- /* send message */
- ((class JoinRemote *)join)->message_remote(msg->type, &msg->param);
+ return(0);
+ }
+ PDEBUG(DEBUG_LOG, "No remote instance found with ref %d. (May have been already released.)\n", msg->ref);
return(0);
+
}
/*
* this function is called for every message to remote socket
*/
-int admin_message_from_join(int remote_id, unsigned int ref, int message_type, union parameter *param)
+int admin_message_from_lcr(int remote_id, unsigned int ref, int message_type, union parameter *param)
{
struct admin_list *admin;
struct admin_queue **responsep; /* response pointer */
class Port *port;
class EndpointAppPBX *apppbx;
class Join *join;
+#ifdef WITH_MISDN
class Pdss1 *pdss1;
- struct interface *interface;
- struct interface_port *ifport;
struct mISDNport *mISDNport;
struct select_channel *selchannel;
+#endif
+ struct interface *interface;
+ struct interface_port *ifport;
int i;
int num;
- int anybusy;
struct admin_queue *response;
struct admin_list *admin;
struct tm *now_tm;
interface = interface_first;
while(interface) {
ifport = interface->ifport;
+ if (!ifport)
+ i++;
while(ifport) {
i++;
ifport = ifport->next;
num = 0;
while(interface) {
ifport = interface->ifport;
+ if (!ifport) {
+ /* message */
+ response->am[num].message = ADMIN_RESPONSE_S_INTERFACE;
+ /* interface */
+ SCPY(response->am[num].u.i.interface_name, interface->name);
+ /* portnum */
+ response->am[num].u.i.portnum = -100; /* indicate: no ifport */
+ /* iftype */
+ response->am[num].u.i.extension = interface->extension;
+ /* block */
+ num++;
+ }
while(ifport) {
/* message */
response->am[num].message = ADMIN_RESPONSE_S_INTERFACE;
response->am[num].u.i.extension = interface->extension;
/* block */
response->am[num].u.i.block = ifport->block;
+#ifdef WITH_MISDN
if (ifport->mISDNport) {
mISDNport = ifport->mISDNport;
}
/* channel state */
i = 0;
- anybusy = 0;
while(i < mISDNport->b_num) {
response->am[num].u.i.busy[i] = mISDNport->b_state[i];
if (mISDNport->b_port[i])
i++;
}
}
+#endif
num++;
ifport = ifport->next;
/* serial */
response->am[num].u.j.serial = join->j_serial;
/* partyline */
- if (join->j_type == JOIN_TYPE_PBX)
+ if (join->j_type == JOIN_TYPE_PBX) {
response->am[num].u.j.partyline = ((class JoinPBX *)join)->j_partyline;
- /* remote application */
- if (join->j_type == JOIN_TYPE_REMOTE)
- SCPY(response->am[num].u.j.remote, ((class JoinRemote *)join)->j_remote_name);
+ response->am[num].u.j.threepty = ((class JoinPBX *)join)->j_3pty;
+ }
/* */
join = join->next;
num++;
if (apppbx->ea_endpoint->ep_park && apppbx->ea_endpoint->ep_park_len && apppbx->ea_endpoint->ep_park_len<=(int)sizeof(response->am[num].u.e.park_callid))
memcpy(response->am[num].u.e.park_callid, apppbx->ea_endpoint->ep_park_callid, apppbx->ea_endpoint->ep_park_len);
response->am[num].u.e.park_len = apppbx->ea_endpoint->ep_park_len;
+#ifdef WITH_CRYPT
/* crypt */
if (apppbx->e_crypt == CRYPT_ON)
response->am[num].u.e.crypt = 1;
+#endif
/* */
apppbx = apppbx->next;
num++;
default:
response->am[num].u.p.state = ADMIN_STATE_IDLE;
}
+#ifdef WITH_MISDN
/* isdn */
if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_DSS1) {
response->am[num].u.p.isdn = 1;
response->am[num].u.p.isdn_hold = pdss1->p_m_hold;
response->am[num].u.p.isdn_ces = pdss1->p_m_d_ces;
}
+#endif
/* */
port = port->next;
num++;
if (len < 0) {
brokenpipe:
PDEBUG(DEBUG_LOG, "Broken pipe on socket %d. (errno=%d).\n", admin->sock, errno);
- free_connection(admin);
- return 0;
- }
- if (len == 0) {
end:
-
/*release endpoint if exists */
if (admin->epointid) {
epoint = find_epoint_id(admin->epointid);
- if (epoint) {
- ((class DEFAULT_ENDPOINT_APP *)epoint->ep_app)->
+ if (epoint && epoint->ep_app_type == EAPP_TYPE_PBX) {
+ ((class EndpointAppPBX *)epoint->ep_app)->
release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
}
}
free_connection(admin);
return 0;
}
+ if (len == 0)
+ goto end;
if (len != sizeof(msg)) {
PERROR("Short/long read on socket %d. (len=%d != size=%d).\n", admin->sock, len, sizeof(msg));
- free_connection(admin);
- return 0;
+ goto end;
}
/* process socket command */
if (admin->response && msg.message != ADMIN_MESSAGE) {
PERROR("Data from socket %d while sending response.\n", admin->sock);
- free_connection(admin);
- return 0;
+ goto end;
}
switch (msg.message) {
case ADMIN_REQUEST_CMD_INTERFACE:
break;
case ADMIN_MESSAGE:
- if (admin_message_to_join(&msg.u.msg, admin) < 0) {
+ if (admin_message_to_lcr(&msg.u.msg, admin) < 0) {
PERROR("Failed to deliver message for socket %d.\n", admin->sock);
goto response_error;
}
if (admin_call(admin, &msg) < 0) {
PERROR("Failed to create call for socket %d.\n", admin->sock);
response_error:
- free_connection(admin);
- return 0;
+ goto end;
}
break;
default:
PERROR("Invalid message %d from socket %d.\n", msg.message, admin->sock);
- free_connection(admin);
- return 0;
+ goto end;
}
}