X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=admin_server.c;h=117611876402a20d50e89ff71996a975afafe40b;hp=80f2875e6daceb35f67844a9695dc5960cb01bac;hb=5a22e57828617abc14e27814ee918cc63b96fd46;hpb=2ed0fee489c37a6e2d4473f6185ebbe3e746ac11 diff --git a/admin_server.c b/admin_server.c index 80f2875..1176118 100644 --- a/admin_server.c +++ b/admin_server.c @@ -1,11 +1,11 @@ /*****************************************************************************\ ** ** -** PBX4Linux ** +** Linux Call Router ** ** ** **---------------------------------------------------------------------------** ** Copyright: Andreas Eversberg ** ** ** -** Socket link ** +** Socket link server ** ** ** \*****************************************************************************/ @@ -86,11 +86,33 @@ int admin_init(void) /* * free connection + * also releases all asterisk joins */ void free_connection(struct admin_list *admin) { struct admin_queue *response; void *temp; + union parameter param; + class Join *join, *joinnext; + + /* free asterisk joins */ + if (admin->asterisk) + { + join = join_first; + while(join) + { + joinnext = join->next; + if (join->c_type == JOIN_TYPE_ASTERISK) + { + memset(¶m, 0, sizeof(param)); + param.disconnectinfo.cause = CAUSE_OUTOFORDER; + param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; + ((class JoinAsterisk *)join)->message_asterisk(0, MESSAGE_RELEASE, ¶m); + /* join is now destroyed, so we go to next join */ + } + join = joinnext; + } + } if (admin->sock >= 0) { @@ -104,12 +126,12 @@ void free_connection(struct admin_list *admin) //#warning // printf("%x\n", response); temp = response->next; - free(response); + FREE(response, 0); memuse--; response = (struct admin_queue *)temp; } // printf("new2\n", response); - free(admin); + FREE(admin, 0); // printf("new3\n", response); memuse--; } @@ -160,11 +182,8 @@ int admin_interface(struct admin_queue **responsep) err = -1; } /* create state response */ - response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message)); - if (!response) - return(-1); + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); memuse++; - memset(response, 0, sizeof(admin_queue)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_CMD_INTERFACE; @@ -236,9 +255,6 @@ int admin_route(struct admin_queue **responsep) case ACTION_EXTERNAL: apppbx->e_action = &action_external; break; - case ACTION_H323: - apppbx->e_action = &action_h323; - break; case ACTION_CHAN: apppbx->e_action = &action_chan; break; @@ -257,7 +273,15 @@ int admin_route(struct admin_queue **responsep) apppbx->e_callback = 0; apppbx->e_action = NULL; apppbx->release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); - printlog("%3d endpoint ADMIN Kicking due to reload of routing.\n", apppbx->ea_endpoint->ep_serial); + start_trace(0, + NULL, + numberrize_callerinfo(apppbx->e_callerinfo.id, apppbx->e_callerinfo.ntype), + apppbx->e_dialinginfo.id, + DIRECTION_NONE, + CATEGORY_EP, + apppbx->ea_endpoint->ep_serial, + "KICK (reload routing)"); + end_trace(); } apppbx->e_action_timeout = NULL; @@ -269,11 +293,8 @@ int admin_route(struct admin_queue **responsep) response: /* create state response */ - response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message)); - if (!response) - return(-1); + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); memuse++; - memset(response, 0, sizeof(admin_queue)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_CMD_ROUTE; @@ -299,11 +320,8 @@ int admin_dial(struct admin_queue **responsep, char *message) char *p; /* pointer to dialing digits */ /* create state response */ - response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message)); - if (!response) - return(-1); + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); memuse++; - memset(response, 0, sizeof(admin_queue)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_CMD_DIAL; @@ -336,6 +354,114 @@ int admin_dial(struct admin_queue **responsep, char *message) /* + * do tracing + */ +int admin_trace(struct admin_list *admin, struct admin_trace_req *trace) +{ + memcpy(&admin->trace, trace, sizeof(struct admin_trace_req)); + return(0); +} + + +/* + * do blocking + * + * 0 = make port available + * 1 = make port administratively blocked + * 2 = unload port + * the result is returned: + * 0 = port is now available + * 1 = port is now blocked + * 2 = port cannot be loaded or has been unloaded + * -1 = port doesn't exist + */ +int admin_block(struct admin_queue **responsep, int portnum, int block) +{ + struct admin_queue *response; /* response pointer */ + struct interface *interface; + struct interface_port *ifport; + + /* create block response */ + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); + memuse++; + response->num = 1; + /* message */ + response->am[0].message = ADMIN_RESPONSE_CMD_BLOCK; + response->am[0].u.x.portnum = portnum; + + /* search for port */ + interface = interface_first; + while(interface) + { + ifport = interface->ifport; + while(ifport) + { + if (ifport->portnum == portnum) + break; + ifport = ifport->next; + } + if (ifport) + break; + interface = interface->next; + } + /* not found, we return -1 */ + if (!ifport) + { + response->am[0].u.x.block = -1; + response->am[0].u.x.error = 1; + SPRINT(response->am[0].u.x.message, "Port %d does not exist.", portnum); + goto out; + } + + /* no interface */ + if (!ifport->mISDNport) + { + /* not loaded anyway */ + if (block >= 2) + { + response->am[0].u.x.block = 2; + goto out; + } + + /* try loading interface */ + ifport->block = block; + load_port(ifport); + + /* port cannot load */ + if (ifport->block >= 2) + { + response->am[0].u.x.block = 2; + response->am[0].u.x.error = 1; + SPRINT(response->am[0].u.x.message, "Port %d will not load.", portnum); + goto out; + } + + /* port loaded */ + response->am[0].u.x.block = ifport->block; + goto out; + } + + /* if we shall unload interface */ + if (block >= 2) + { + mISDNport_close(ifport->mISDNport); + ifport->mISDNport = 0; + ifport->block = 2; + goto out; + } + + /* port new blocking state */ + ifport->block = response->am[0].u.x.block = block; + + out: + /* attach to response chain */ + *responsep = response; + responsep = &response->next; + return(0); +} + + +/* * do release */ int admin_release(struct admin_queue **responsep, char *message) @@ -345,11 +471,8 @@ int admin_release(struct admin_queue **responsep, char *message) class EndpointAppPBX *apppbx; /* create state response */ - response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message)); - if (!response) - return(-1); + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); memuse++; - memset(response, 0, sizeof(admin_queue)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_CMD_RELEASE; @@ -388,14 +511,10 @@ int admin_call(struct admin_list *admin, struct admin_message *msg) class Endpoint *epoint; class EndpointAppPBX *apppbx; - if (!(epoint = new Endpoint(0,0))) - return(-1); - - if (!(epoint->ep_app = apppbx = new DEFAULT_ENDPOINT_APP(epoint))) - { - PERROR("no memory for application\n"); - exit(-1); - } + if (!(epoint = new Endpoint(0, 0, 0))) + FATAL("No memory for Endpoint instance\n"); + if (!(epoint->ep_app = apppbx = new DEFAULT_ENDPOINT_APP(epoint))) + FATAL("No memory for Endpoint Application instance\n"); apppbx->e_adminid = admin->sockserial; admin->epointid = epoint->ep_serial; SCPY(apppbx->e_callerinfo.id, nationalize_callerinfo(msg->u.call.callerid, &apppbx->e_callerinfo.ntype)); @@ -412,7 +531,7 @@ int admin_call(struct admin_list *admin, struct admin_message *msg) apppbx->e_capainfo.bearer_info1 = msg->u.call.bc_info1; apppbx->e_capainfo.hlc = msg->u.call.hlc; apppbx->e_capainfo.exthlc = msg->u.call.exthlc; - SCPY(apppbx->e_dialinginfo.number, msg->u.call.dialing); + SCPY(apppbx->e_dialinginfo.id, msg->u.call.dialing); SCPY(apppbx->e_dialinginfo.interfaces, msg->u.call.interface); apppbx->e_dialinginfo.sending_complete = 1; @@ -453,11 +572,8 @@ void admin_call_response(int adminid, int message, char *connected, int cause, i } /* create state response */ - response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message)); - if (!response) - return; + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); memuse++; - memset(response, 0, sizeof(admin_queue)); response->num = 1; /* message */ response->am[0].message = message; @@ -475,6 +591,116 @@ void admin_call_response(int adminid, int message, char *connected, int cause, i /* + * send data to the asterisk join instance + */ +int admin_message_to_join(struct admin_msg *msg) +{ + class Join *join; + struct admin_list *admin; + + /* dummy callref means: asterisk is here */ + if (msg->type == MESSAGE_HELLO) + { + /* look for second asterisk */ + admin = admin_list; + while(admin) + { + if (admin->asterisk) + break; + admin = admin->next; + } + if (admin) + { + PERROR("Asterisk connects twice??? (ignoring)\n"); + return(-1); + } + /* set asterisk socket instance */ + admin->asterisk = 1; + } + + /* find join instance */ + join = join_first; + while(join) + { + if (join->c_serial == msg->ref) + break; + join = join->next; + } + + /* create join instance if not existing */ + if (!join) + { + if (msg->ref < 2000000000) + { + PERROR("Asterisk sends us unknown ref %d below 2000000000.\n", msg->ref); + return(-1); + } + + /* create new join instance */ + join = new JoinAsterisk(0); // must have no serial, because no endpoint is connected + if (!join) + FATAL("No memory for Asterisk join instance\n"); + } + + /* send message */ + if (join->c_type != JOIN_TYPE_ASTERISK) + FATAL("join instance %d must be of type join Asterisk\n", join->c_serial); + ((class JoinAsterisk *)join)->message_asterisk(msg->ref, msg->type, &msg->param); + + return(0); +} + + +/* + * this function is called for every message to asterisk + */ +int admin_message_from_join(unsigned long ref, int message_type, union parameter *param) +{ + struct admin_list *admin; + struct admin_queue *response, **responsep; /* response pointer */ + + /* searching for admin id + * maybe there is no asterisk instance + */ + admin = admin_list; + while(admin) + { + if (admin->asterisk) + break; + admin = admin->next; + } + /* no asterisk connected */ + if (!admin) + return(-1); + + /* seek to end of response list */ + response = admin->response; + responsep = &admin->response; + while(response) + { + responsep = &response->next; + response = response->next; + } + + /* create state response */ + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); + memuse++; + response->num = 1; + + /* message */ + response->am[0].u.msg.type = message_type; + response->am[0].u.msg.ref = ref; + memcpy(&response->am[0].u.msg.param, param, sizeof(union parameter)); + + /* attach to response chain */ + *responsep = response; + responsep = &response->next; + + return(0); +} + + +/* * do state debugging */ int admin_state(struct admin_queue **responsep) @@ -482,8 +708,10 @@ int admin_state(struct admin_queue **responsep) class Port *port; class EndpointAppPBX *apppbx; - class Call *call; + class Join *join; class Pdss1 *pdss1; + struct interface *interface; + struct interface_port *ifport; struct mISDNport *mISDNport; int i; int num; @@ -491,11 +719,8 @@ int admin_state(struct admin_queue **responsep) struct admin_queue *response; /* create state response */ - response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message)); - if (!response) - return(-1); + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); memuse++; - memset(response, 0, sizeof(admin_queue)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_STATE; @@ -506,23 +731,28 @@ int admin_state(struct admin_queue **responsep) /* log file */ SCPY(response->am[0].u.s.logfile, options.log); /* interface count */ - mISDNport = mISDNport_first; i = 0; - while(mISDNport) + interface = interface_first; + while(interface) { - i++; - mISDNport = mISDNport->next; + ifport = interface->ifport; + while(ifport) + { + i++; + ifport = ifport->next; + } + interface = interface->next; } response->am[0].u.s.interfaces = i; - /* call count */ - call = call_first; + /* join count */ + join = join_first; i = 0; - while(call) + while(join) { i++; - call = call->next; + join = join->next; } - response->am[0].u.s.calls = i; + response->am[0].u.s.joins = i; /* apppbx count */ apppbx = apppbx_first; i = 0; @@ -533,8 +763,8 @@ int admin_state(struct admin_queue **responsep) } response->am[0].u.s.epoints = i; /* port count */ - port = port_first; i = 0; + port = port_first; while(port) { i++; @@ -546,68 +776,80 @@ int admin_state(struct admin_queue **responsep) responsep = &response->next; /* create response for all interfaces */ - num = (response->am[0].u.s.interfaces)+(response->am[0].u.s.calls)+(response->am[0].u.s.epoints)+(response->am[0].u.s.ports); - response = (struct admin_queue *)malloc(sizeof(admin_queue)+(num*sizeof(admin_message))); - if (!response) - return(-1); + num = (response->am[0].u.s.interfaces)+(response->am[0].u.s.joins)+(response->am[0].u.s.epoints)+(response->am[0].u.s.ports); + if (num == 0) + return(0); + response = (struct admin_queue *)MALLOC(sizeof(admin_queue)+(num*sizeof(admin_message))); memuse++; - memset(response, 0, sizeof(admin_queue)+(num*sizeof(admin_queue))); response->num = num; *responsep = response; responsep = &response->next; - mISDNport = mISDNport_first; + interface = interface_first; num = 0; - while(mISDNport) + while(interface) { - /* message */ - response->am[num].message = ADMIN_RESPONSE_S_INTERFACE; - /* portnum */ - response->am[num].u.i.portnum = mISDNport->portnum; - /* interface */ - SCPY(response->am[num].u.i.interface_name, mISDNport->interface_name); - /* iftype */ - response->am[num].u.i.iftype = mISDNport->iftype; - /* ptp */ - response->am[num].u.i.ptp = mISDNport->ptp; - /* ntmode */ - response->am[num].u.i.ntmode = mISDNport->ntmode; - /* pri */ - response->am[num].u.i.pri = mISDNport->pri; - /* use */ - response->am[num].u.i.use = mISDNport->use; - /* l1link */ - response->am[num].u.i.l1link = mISDNport->l1link; - /* l2link */ - response->am[num].u.i.l2link = mISDNport->l2link; - /* channels */ - response->am[num].u.i.channels = mISDNport->b_num; - /* channel info */ - i = 0; - anybusy = 0; - while(i < mISDNport->b_num) + ifport = interface->ifport; + while(ifport) { - response->am[num].u.i.busy[i] = mISDNport->b_state[i]; - if (mISDNport->b_port[i]) - response->am[num].u.i.port[i] = mISDNport->b_port[i]->p_serial; - i++; + /* 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 = ifport->portnum; + /* iftype */ + response->am[num].u.i.extension = interface->extension; + /* block */ + response->am[num].u.i.block = ifport->block; + if (ifport->mISDNport) + { + mISDNport = ifport->mISDNport; + + /* ptp */ + response->am[num].u.i.ptp = mISDNport->ptp; + /* ntmode */ + response->am[num].u.i.ntmode = mISDNport->ntmode; + /* pri */ + response->am[num].u.i.pri = mISDNport->pri; + /* use */ + response->am[num].u.i.use = mISDNport->use; + /* l1link */ + response->am[num].u.i.l1link = mISDNport->l1link; + /* l2link */ + response->am[num].u.i.l2link = mISDNport->l2link; + /* channels */ + response->am[num].u.i.channels = mISDNport->b_num; + /* channel info */ + 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]) + response->am[num].u.i.port[i] = mISDNport->b_port[i]->p_serial; + i++; + } + } + num++; + + ifport = ifport->next; } - mISDNport = mISDNport->next; - num++; + interface = interface->next; } - /* create response for all calls */ - call = call_first; - while(call) + /* create response for all joins */ + join = join_first; + while(join) { /* message */ - response->am[num].message = ADMIN_RESPONSE_S_CALL; + response->am[num].message = ADMIN_RESPONSE_S_JOIN; /* serial */ - response->am[num].u.c.serial = call->c_serial; + response->am[num].u.j.serial = join->c_serial; /* partyline */ - if (call->c_type == CALL_TYPE_PBX) - response->am[num].u.c.partyline = ((class CallPBX *)call)->c_partyline; + if (join->c_type == JOIN_TYPE_PBX) + response->am[num].u.j.partyline = ((class JoinPBX *)join)->c_partyline; /* */ - call = call->next; + join = join->next; num++; } @@ -619,8 +861,8 @@ int admin_state(struct admin_queue **responsep) response->am[num].message = ADMIN_RESPONSE_S_EPOINT; /* serial */ response->am[num].u.e.serial = apppbx->ea_endpoint->ep_serial; - /* call */ - response->am[num].u.e.call = apppbx->ea_endpoint->ep_call_id; + /* join */ + response->am[num].u.e.join = apppbx->ea_endpoint->ep_join_id; /* rx notification */ response->am[num].u.e.rx_state = apppbx->e_rx_state; /* tx notification */ @@ -665,11 +907,11 @@ int admin_state(struct admin_queue **responsep) response->am[num].u.e.state = ADMIN_STATE_IDLE; } /* terminal */ - SCPY(response->am[num].u.e.terminal, apppbx->e_terminal); + SCPY(response->am[num].u.e.terminal, apppbx->e_ext.number); /* callerid */ SCPY(response->am[num].u.e.callerid, apppbx->e_callerinfo.id); /* dialing */ - SCPY(response->am[num].u.e.dialing, apppbx->e_dialinginfo.number); + SCPY(response->am[num].u.e.dialing, apppbx->e_dialinginfo.id); /* action string */ if (apppbx->e_action) SCPY(response->am[num].u.e.action, action_defs[apppbx->e_action->index].name); @@ -779,26 +1021,21 @@ int admin_handle(void) { work = 1; /* insert new socket */ - admin = (struct admin_list *)malloc(sizeof(struct admin_list)); - if (admin) + admin = (struct admin_list *)MALLOC(sizeof(struct admin_list)); + if (ioctl(new_sock, FIONBIO, (unsigned char *)(&on)) >= 0) { - if (ioctl(new_sock, FIONBIO, (unsigned char *)(&on)) >= 0) - { //#warning // PERROR("DEBUG incomming socket %d, serial=%d\n", new_sock, sockserial); - memuse++; - fhuse++; - memset(admin, 0, sizeof(struct admin_list)); - admin->sockserial = sockserial++; - admin->next = admin_list; - admin_list = admin; - admin->sock = new_sock; - } else { - close(new_sock); - free(admin); - } - } else + memuse++; + fhuse++; + admin->sockserial = sockserial++; + admin->next = admin_list; + admin_list = admin; + admin->sock = new_sock; + } else { close(new_sock); + FREE(admin, sizeof(struct admin_list)); + } } else { if (errno != EWOULDBLOCK) @@ -912,11 +1149,31 @@ int admin_handle(void) if (admin_state(&admin->response) < 0) { PERROR("Failed to create state response for socket %d.\n", admin->sock); - response_error: - *adminp = admin->next; - free_connection(admin); - admin = *adminp; - continue; + goto response_error; + } + break; + + case ADMIN_TRACE_REQUEST: + if (admin_trace(admin, &msg.u.trace_req) < 0) + { + PERROR("Failed to create trace response for socket %d.\n", admin->sock); + goto response_error; + } + break; + + case ADMIN_REQUEST_CMD_BLOCK: + if (admin_block(&admin->response, msg.u.x.portnum, msg.u.x.block) < 0) + { + PERROR("Failed to create block response for socket %d.\n", admin->sock); + goto response_error; + } + break; + + case ADMIN_MESSAGE: + if (admin_message_to_join(&msg.u.msg) < 0) + { + PERROR("Failed to deliver message for socket %d.\n", admin->sock); + goto response_error; } #if 0 #warning DEBUGGING @@ -935,10 +1192,14 @@ int admin_handle(void) break; case ADMIN_CALL_SETUP: - if (admin_call(admin, &msg)) + if (admin_call(admin, &msg) < 0) { PERROR("Failed to create call for socket %d.\n", admin->sock); - goto response_error; + response_error: + *adminp = admin->next; + free_connection(admin); + admin = *adminp; + continue; } break; @@ -976,7 +1237,7 @@ int admin_handle(void) { temp = admin->response; admin->response = admin->response->next; - free(temp); + FREE(temp, 0); memuse--; } }