X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=socket_server.c;h=2fba2ebaa7d26ea0bc1f6b271c985bc32ee4325d;hp=b67b91fcc1a763fdd4288832017b64a0e91adb32;hb=5463e1b62a39ce417b610584e3d34a8bc30ac15e;hpb=b0bd74e35e935aa976b68c594def4e8d2c22ef95 diff --git a/socket_server.c b/socket_server.c index b67b91f..2fba2eb 100644 --- a/socket_server.c +++ b/socket_server.c @@ -13,6 +13,10 @@ #include #include #include +#ifdef PACKAGE_VERSION +#undef PACKAGE_VERSION +#endif +#include "config.h" char socket_name[128]; @@ -83,6 +87,8 @@ void free_connection(struct admin_list *admin) struct mISDNport *mISDNport; int i, ii; struct admin_list **adminp; + class Port *port, *portnext; + class Premote *remote; /* free remote joins */ if (admin->remote_name[0]) { @@ -125,6 +131,22 @@ void free_connection(struct admin_list *admin) } join = joinnext; } + /* 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_m_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 */ + } + } + port = portnext; + } } if (admin->sock >= 0) { @@ -278,7 +300,7 @@ int admin_route(struct admin_queue **responsep) release: unsched_timer(&apppbx->e_callback_timeout); apppbx->e_action = NULL; - apppbx->release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); + apppbx->release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); start_trace(-1, NULL, numberrize_callerinfo(apppbx->e_callerinfo.id, apppbx->e_callerinfo.ntype, options.national, options.international), @@ -488,7 +510,7 @@ int admin_release(struct admin_queue **responsep, char *message) } unsched_timer(&apppbx->e_callback_timeout); - apppbx->release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); + apppbx->release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); out: /* attach to response chain */ @@ -530,7 +552,7 @@ int admin_call(struct admin_list *admin, struct admin_message *msg) apppbx->e_dialinginfo.sending_complete = 1; apppbx->new_state(PORT_STATE_OUT_SETUP); - apppbx->out_setup(); + apppbx->out_setup(0); return(0); } @@ -538,7 +560,7 @@ int admin_call(struct admin_list *admin, struct admin_message *msg) /* * this function is called for response whenever a call state changes. */ -void admin_call_response(int adminid, int message, const char *connected, int cause, int location, int notify) +void admin_call_response(int adminid, int message, const char *connected, int cause, int location, int notify_progress) { struct admin_list *admin; struct admin_queue *response, **responsep; /* response pointer */ @@ -573,7 +595,7 @@ void admin_call_response(int adminid, int message, const char *connected, int ca SCPY(response->am[0].u.call.callerid, connected); response->am[0].u.call.cause = cause; response->am[0].u.call.location = location; - response->am[0].u.call.notify = notify; + response->am[0].u.call.notify_progress = notify_progress; /* attach to response chain */ *responsep = response; @@ -585,9 +607,13 @@ void admin_call_response(int adminid, int message, const char *connected, int ca /* * 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) { + struct mISDNport *mISDNport; class Join *join; + class JoinRemote *joinremote = NULL; /* make GCC happy */ + class Port *port; + class Premote *remote = NULL; /* make GCC happy */ struct admin_list *temp; /* hello message */ @@ -628,13 +654,44 @@ int admin_message_to_join(struct admin_msg *msg, struct admin_list *admin) return(-1); } - /* new join */ + /* new join. 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); + if (msg->param.newref.mode) { + char name[32]; + /* find remote port */ + mISDNport = mISDNport_first; + while(mISDNport) { + if (mISDNport->ifport->remote && !strcmp(mISDNport->ifport->remote_app, admin->remote_name)) + break; + mISDNport = mISDNport->next; + } + if (!mISDNport) { + union parameter param; + + /* create new join instance */ + join = joinremote = 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); + } + memset(¶m, 0, sizeof(union parameter)); + param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; + param.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL; + admin_message_from_lcr(joinremote->j_remote_id, joinremote->j_remote_ref, MESSAGE_RELEASE, ¶m); + return 0; + } + /* creating port object, transparent until setup with hdlc */ + SPRINT(name, "%s-%s-in", mISDNport->ifport->interface->name, mISDNport->ifport->remote_app); + if (!(remote = new Premote(PORT_TYPE_REMOTE_IN, mISDNport, name, NULL, 0, 0, B_MODE_TRANSPARENT, admin->sock))) + + FATAL("Cannot create Port instance.\n"); + } else { + /* 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); + } } return(0); } @@ -659,36 +716,56 @@ int admin_message_to_join(struct admin_msg *msg, struct admin_list *admin) /* find join instance */ join = join_first; while(join) { - if (join->j_serial == msg->ref) - break; + if (join->j_type == JOIN_TYPE_REMOTE) { + joinremote = (class JoinRemote *)join; + if (joinremote->j_remote_ref == 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); + if (join) { + if (admin->sock != joinremote->j_remote_id) { + PERROR("Ref %d belongs to remote application %s, but not to sending application %s.\n", msg->ref, joinremote->j_remote_name, admin->remote_name); + return(-1); + } + /* send message */ + joinremote->message_remote(msg->type, &msg->param); + return(0); } - /* 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); + /* 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_m_r_ref == msg->ref) + break; + } + port = port->next; } + if (port) { + if (admin->sock != remote->p_m_r_remote_id) { + PERROR("Ref %d belongs to remote application %s, but not to sending application %s.\n", msg->ref, remote->p_m_r_remote_app, admin->remote_name); + return(-1); + } - /* send message */ - ((class JoinRemote *)join)->message_remote(msg->type, &msg->param); + /* send message */ + remote->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 */ @@ -739,6 +816,7 @@ int admin_state(struct admin_queue **responsep) struct interface *interface; struct interface_port *ifport; struct mISDNport *mISDNport; + struct select_channel *selchannel; int i; int num; int anybusy; @@ -766,6 +844,8 @@ int admin_state(struct admin_queue **responsep) interface = interface_first; while(interface) { ifport = interface->ifport; + if (!ifport) + i++; while(ifport) { i++; ifport = ifport->next; @@ -827,6 +907,18 @@ int admin_state(struct admin_queue **responsep) 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; @@ -871,7 +963,40 @@ int admin_state(struct admin_queue **responsep) response->am[num].u.i.slip_rx = mISDNport->slip_rx; /* channels */ response->am[num].u.i.channels = mISDNport->b_num; - /* channel info */ + /* channel selection */ + selchannel = ifport->out_channel; + if (ifport->channel_force) + SCAT(response->am[num].u.i.out_channel, "force"); + while (selchannel) { + if (response->am[num].u.i.out_channel[0]) + SCAT(response->am[num].u.i.out_channel, ","); + switch (selchannel->channel) { + case CHANNEL_NO: + SCAT(response->am[num].u.i.out_channel, "no"); + break; + case CHANNEL_ANY: + SCAT(response->am[num].u.i.out_channel, "any"); + break; + case CHANNEL_FREE: + SCAT(response->am[num].u.i.out_channel, "free"); + break; + default: + SPRINT(strchr(response->am[num].u.i.out_channel, '\0'), "%d", selchannel->channel); + } + selchannel = selchannel->next; + } + selchannel = ifport->in_channel; + while (selchannel) { + switch (selchannel->channel) { + case CHANNEL_FREE: + SCAT(response->am[num].u.i.in_channel, "free"); + break; + default: + SPRINT(strchr(response->am[num].u.i.in_channel, '\0'), "%d", selchannel->channel); + } + selchannel = selchannel->next; + } + /* channel state */ i = 0; anybusy = 0; while(i < mISDNport->b_num) { @@ -1049,7 +1174,7 @@ int admin_state(struct admin_queue **responsep) response->am[num].u.p.state = ADMIN_STATE_IDLE; } /* isdn */ - if ((port->p_type&PORT_CLASS_mISDN_MASK) == PORT_CLASS_mISDN_DSS1) { + if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_DSS1) { response->am[num].u.p.isdn = 1; pdss1 = (class Pdss1 *)port; response->am[num].u.p.isdn_chan = pdss1->p_m_b_channel; @@ -1123,7 +1248,7 @@ int admin_handle_con(struct lcr_fd *fd, unsigned int what, void *instance, int i epoint = find_epoint_id(admin->epointid); if (epoint) { ((class DEFAULT_ENDPOINT_APP *)epoint->ep_app)-> - release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); + release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); } } @@ -1199,7 +1324,7 @@ int admin_handle_con(struct lcr_fd *fd, unsigned int what, void *instance, int i 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; } @@ -1246,3 +1371,24 @@ int admin_handle_con(struct lcr_fd *fd, unsigned int what, void *instance, int i return 0; } +void message_bchannel_to_remote(unsigned int remote_id, unsigned int ref, int type, unsigned int handle, int tx_gain, int rx_gain, char *pipeline, unsigned char *crypt, int crypt_len, int crypt_type, int isloopback) +{ + union parameter param; + + memset(¶m, 0, sizeof(union parameter)); + param.bchannel.isloopback = isloopback; + param.bchannel.type = type; + param.bchannel.handle = handle; + param.bchannel.tx_gain = tx_gain; + param.bchannel.rx_gain = rx_gain; + if (pipeline) + SCPY(param.bchannel.pipeline, pipeline); + if (crypt_len) + memcpy(param.bchannel.crypt, crypt, crypt_len); + param.bchannel.crypt_type = crypt_type; + if (admin_message_from_lcr(remote_id, ref, MESSAGE_BCHANNEL, ¶m)<0) { + PERROR("No socket with remote id %d found, this happens, if the socket is closed before all bchannels are imported.\n", remote_id); + return; + } +} +