X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=admin_server.c;h=6292e125a3fc840c8ef38ccb6adb7b46d84316d9;hp=756376f9a6054bb34b6579a3f44bedb5e594301a;hb=701b046a45c2c79cc6d07ac3a4f84f499f7ed376;hpb=e9daaa4ef7ee895e6a8610ebb2166cc99c891a4e diff --git a/admin_server.c b/admin_server.c index 756376f..6292e12 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[0]) + { + join = join_first; + while(join) + { + joinnext = join->next; + if (join->j_type==JOIN_TYPE_REMOTE && !strcmp(((class JoinRemote *)join)->j_remote, admin->remote)) + { + memset(¶m, 0, sizeof(param)); + param.disconnectinfo.cause = CAUSE_OUTOFORDER; + param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; + ((class JoinRemote *)join)->message_remote(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--; } @@ -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)); 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; @@ -256,12 +275,13 @@ int admin_route(struct admin_queue **responsep) apppbx->release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); start_trace(0, NULL, - nationalize(apppbx->e_callerinfo.id, apppbx->e_callerinfo.ntype), - apppbx->e_dialinginfo.number, + numberrize_callerinfo(apppbx->e_callerinfo.id, apppbx->e_callerinfo.ntype), + apppbx->e_dialinginfo.id, DIRECTION_NONE, CATEGORY_EP, - apppbx->e_serial, + apppbx->ea_endpoint->ep_serial, "KICK (reload routing)"); + end_trace(); } apppbx->e_action_timeout = NULL; @@ -273,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; @@ -303,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; @@ -340,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) @@ -349,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; @@ -392,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)); @@ -416,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; @@ -437,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) @@ -457,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; @@ -479,6 +591,141 @@ 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) +{ + class Join *join; + struct admin_list *admin; + + /* hello message */ + if (msg->type == MESSAGE_HELLO) + { + if (remote[0]) + { + PERROR("Remote application repeats hello message.\n"); + return(-1); + } + /* look for second application */ + admin = admin_first; + while(admin) + { + if (!strcmp(admin->remote, msg->param.hello.application)) + break; + admin = admin->next; + } + if (admin) + { + PERROR("Remote application connects twice??? (ignoring)\n"); + return(-1); + } + /* set asterisk socket instance */ + SCPY(remote, msg->param.hello.application); + return(0); + } + + /* check we already have no application name */ + if (!remote[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); // must have no serial, because no endpoint is connected + if (!join) + FATAL("No memory for remote join 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; + } + + /* 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 (!!strcmp(remote, ((class JoinRemote *)join)->j_remote)) + { + PERROR("Ref %d belongs to remote application %s, but not to sending application %s.\n", msg->ref, ((class JoinRemote *)join)->j_remote, remote); + return(-1); + } + + /* send message */ + ((class JoinRemote *)join)->message_remote(msg->ref, msg->type, &msg->param); + + return(0); +} + + +/* + * this function is called for every message to remote socket + */ +int admin_message_from_join(char *remote, 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[0] && !strcmp(admin->remote, remote)) + 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) @@ -486,20 +733,20 @@ 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; 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)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_STATE; @@ -510,23 +757,38 @@ 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; + /* remote connection count */ + i = 0; + admin = admin_first; + while(admin) + { + if (admin->remote[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; @@ -537,8 +799,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++; @@ -550,68 +812,99 @@ 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 remotes */ + admin = admin_first; + while(admin) + { + if (admin->remote[0]) + { + /* message */ + response->am[num].message = ADMIN_RESPONSE_S_REMOTE; + /* name */ + SCPY(response->am[num].u.r.name, admin->remote); + /* */ + 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); /* */ - call = call->next; + join = join->next; num++; } @@ -623,8 +916,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 */ @@ -673,7 +966,7 @@ int admin_state(struct admin_queue **responsep) /* 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); @@ -783,26 +1076,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) @@ -814,8 +1102,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 */ @@ -858,7 +1146,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)) @@ -918,15 +1206,29 @@ int admin_handle(void) PERROR("Failed to create state response for socket %d.\n", admin->sock); goto response_error; } - case ADMIN_REQUEST_MESSAGE: - if (admin_message(&admin->response) < 0) + break; + + case ADMIN_TRACE_REQUEST: + if (admin_trace(admin, &msg.u.trace_req) < 0) { - PERROR("Failed to create message response for socket %d.\n", admin->sock); - response_error: - *adminp = admin->next; - free_connection(admin); - admin = *adminp; - continue; + 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, admin->remote) < 0) + { + PERROR("Failed to deliver message for socket %d.\n", admin->sock); + goto response_error; } #if 0 #warning DEBUGGING @@ -945,10 +1247,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; @@ -986,7 +1292,7 @@ int admin_handle(void) { temp = admin->response; admin->response = admin->response->next; - free(temp); + FREE(temp, 0); memuse--; } }