X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=admin_server.c;h=6b0647b243c8fa3221860a816060672a904e5193;hp=1bb07af19a060572e264f1e74c3cdd7953a7e1be;hb=cbe9d412a37e75b61cc74e8a65b0293923eb5160;hpb=2746009aca7e00678ad6f5f64da8b208ab635d60 diff --git a/admin_server.c b/admin_server.c index 1bb07af..6b0647b 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 ** ** ** \*****************************************************************************/ @@ -33,7 +33,7 @@ char *socket_name = SOCKET_NAME; int sock = -1; struct sockaddr_un sock_address; -struct admin_list *admin_list = NULL; +struct admin_list *admin_first = NULL; /* * initialize admin socket @@ -86,11 +86,33 @@ int admin_init(void) /* * 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; + + /* free remote joins */ + if (admin->remote_name[0]) + { + 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; + } + } 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--; } @@ -122,7 +144,7 @@ void admin_cleanup(void) { struct admin_list *admin, *next;; - admin = admin_list; + admin = admin_first; while(admin) { //printf("clean\n"); @@ -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)+sizeof(admin_message)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_CMD_INTERFACE; @@ -236,8 +255,8 @@ int admin_route(struct admin_queue **responsep) case ACTION_EXTERNAL: apppbx->e_action = &action_external; break; - case ACTION_CHAN: - apppbx->e_action = &action_chan; + case ACTION_REMOTE: + apppbx->e_action = &action_remote; break; case ACTION_VBOX_RECORD: apppbx->e_action = &action_vbox; @@ -274,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)+sizeof(admin_message)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_CMD_ROUTE; @@ -304,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)+sizeof(admin_message)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_CMD_DIAL; @@ -369,11 +382,8 @@ int admin_block(struct admin_queue **responsep, int portnum, int block) struct interface_port *ifport; /* create block 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)+sizeof(admin_message)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_CMD_BLOCK; @@ -461,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)+sizeof(admin_message)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_CMD_RELEASE; @@ -504,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))) + 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)); @@ -549,7 +552,7 @@ void admin_call_response(int adminid, int message, char *connected, int cause, i /* searching for admin id * maybe there is no admin instance, because the calling port was not * initiated by admin_call */ - admin = admin_list; + admin = admin_first; while(admin) { if (adminid == admin->sockserial) @@ -569,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)+sizeof(admin_message)); response->num = 1; /* message */ response->am[0].message = message; @@ -591,6 +591,157 @@ void admin_call_response(int adminid, int message, char *connected, int cause, i /* + * send data to the remote socket join instance + */ +int admin_message_to_join(struct admin_msg *msg, char *remote_name, int sock_id) +{ + class Join *join; + struct admin_list *admin; + + /* hello message */ + if (msg->type == MESSAGE_HELLO) + { + if (remote_name[0]) + { + PERROR("Remote application repeats hello message.\n"); + return(-1); + } + /* look for second application */ + admin = admin_first; + while(admin) + { + if (!strcmp(admin->remote_name, msg->param.hello.application)) + break; + admin = admin->next; + } + if (admin) + { + PERROR("Remote application connects twice??? (ignoring)\n"); + return(-1); + } + /* set remote socket instance */ + SCPY(remote_name, msg->param.hello.application); + return(0); + } + + /* check we have no application name */ + if (remote_name[0]) + { + PERROR("Remote application did not send us a hello message.\n"); + return(-1); + } + + /* new join */ + if (msg->type == MESSAGE_NEWREF) + { + /* create new join instance */ + join = new JoinRemote(0, remote_name, sock_id); // must have no serial, because no endpoint is connected + if (!join) + FATAL("No memory for remote join instance\n"); + return(0); + } + + /* 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) + { + /* no ref, but address */ + message_bchannel_from_join(NULL, msg->param.bchannel.type, msg->param.bchannel.addr); + 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) + { + PERROR("No join found with serial %d.\n", msg->ref); + 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 (sock_id != ((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, remote_name); + return(-1); + } + + /* send message */ + ((class JoinRemote *)join)->message_remote(msg->type, &msg->param); + + return(0); +} + + +/* + * this function is called for every message to remote socket + */ +int admin_message_from_join(int remote_id, 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 given remote application + */ + admin = admin_first; + while(admin) + { + if (admin->remote_name[0] && admin->sock==remote_id) + break; + admin = admin->next; + } + /* no given remote application 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) @@ -598,7 +749,7 @@ 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; @@ -607,13 +758,11 @@ int admin_state(struct admin_queue **responsep) int num; int anybusy; struct admin_queue *response; + struct admin_list *admin; /* 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)+sizeof(admin_message)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_STATE; @@ -637,15 +786,25 @@ int admin_state(struct admin_queue **responsep) interface = interface->next; } response->am[0].u.s.interfaces = i; - /* call count */ - call = call_first; + /* remote connection count */ + i = 0; + admin = admin_first; + while(admin) + { + if (admin->remote_name[0]) + i++; + admin = admin->next; + } + response->am[0].u.s.remotes = i; + /* 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; @@ -669,14 +828,11 @@ 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); + 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))); - if (!response) - return(-1); + response = (struct admin_queue *)MALLOC(sizeof(admin_queue)+(num*sizeof(admin_message))); memuse++; - memset(response, 0, sizeof(admin_queue)+(num*sizeof(admin_message))); response->num = num; *responsep = response; responsep = &response->next; @@ -733,19 +889,38 @@ int admin_state(struct admin_queue **responsep) interface = interface->next; } - /* create response for all calls */ - call = call_first; - while(call) + /* create response for all remotes */ + admin = admin_first; + while(admin) + { + if (admin->remote_name[0]) + { + /* message */ + response->am[num].message = ADMIN_RESPONSE_S_REMOTE; + /* name */ + SCPY(response->am[num].u.r.name, admin->remote_name); + /* */ + num++; + } + admin = admin->next; + } + + /* 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->j_serial; /* partyline */ - if (call->c_type == CALL_TYPE_PBX) - response->am[num].u.c.partyline = ((class CallPBX *)call)->c_partyline; + 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); /* */ - call = call->next; + join = join->next; num++; } @@ -757,8 +932,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 */ @@ -917,26 +1092,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_first; + admin_first = admin; + admin->sock = new_sock; + } else { close(new_sock); + FREE(admin, sizeof(struct admin_list)); + } } else { if (errno != EWOULDBLOCK) @@ -948,8 +1118,8 @@ int admin_handle(void) } /* loop all current socket connections */ - admin = admin_list; - adminp = &admin_list; + admin = admin_first; + adminp = &admin_first; while(admin) { /* read command */ @@ -992,7 +1162,7 @@ int admin_handle(void) *adminp = admin->next; free_connection(admin); admin = *adminp; -//PERROR("DEBUG (admin_list=%x)\n", admin_list); +//PERROR("DEBUG (admin_first=%x)\n", admin_first); continue; } if (len != sizeof(msg)) @@ -1070,15 +1240,12 @@ int admin_handle(void) } break; -#warning interface tbd -#if 0 case ADMIN_MESSAGE: - if (admin_message(&admin->response) < 0) + if (admin_message_to_join(&msg.u.msg, admin->remote_name, admin->sock) < 0) { - PERROR("Failed to create message response for socket %d.\n", admin->sock); + PERROR("Failed to deliver message for socket %d.\n", admin->sock); goto response_error; } -#endif #if 0 #warning DEBUGGING { @@ -1141,7 +1308,7 @@ int admin_handle(void) { temp = admin->response; admin->response = admin->response->next; - free(temp); + FREE(temp, 0); memuse--; } }