utils: Add convenience function for setting fd flags
[asterisk/asterisk.git] / res / res_pktccops.c
index f16c695..156c49d 100644 (file)
 
 /*** MODULEINFO
         <defaultenabled>no</defaultenabled>
+       <support_level>extended</support_level>
  ***/
 
 #include "asterisk.h"
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <fcntl.h>
@@ -339,7 +338,7 @@ static int cops_getmsg (int sfd, struct copsmsg *recmsg)
        recmsg->length = ntohl(*((uint32_t *) (buf + 4)));
        /* Eg KA msg*/
        if (recmsg->clienttype != 0x8008 ) {
-               if (!(recmsg->msg = malloc(recmsg->length - COPS_HEADER_SIZE))) {
+               if (!(recmsg->msg = ast_malloc(recmsg->length - COPS_HEADER_SIZE))) {
                        return -1;
                }
                lent = recv(sfd, recmsg->msg, recmsg->length - COPS_HEADER_SIZE, MSG_DONTWAIT);
@@ -352,12 +351,12 @@ static int cops_getmsg (int sfd, struct copsmsg *recmsg)
                while (len < recmsg->length) {
                        if (len == COPS_HEADER_SIZE) {
                                /* 1st round */
-                               if (!(recmsg->object = malloc(sizeof(struct pktcobj)))) {
+                               if (!(recmsg->object = ast_malloc(sizeof(struct pktcobj)))) {
                                        return -1;
                                }
                                pobject = recmsg->object;
                        } else {
-                               if (!(pobject->next = malloc(sizeof(struct pktcobj)))) {
+                               if (!(pobject->next = ast_malloc(sizeof(struct pktcobj)))) {
                                        return -1;
                                }
                                pobject = pobject->next;
@@ -372,7 +371,7 @@ static int cops_getmsg (int sfd, struct copsmsg *recmsg)
                        pobject->length = ntohs(*ubuf);
                        pobject->cnum = *(buf + 2);
                        pobject->ctype = *(buf + 3);
-                       if (!(pobject->contents = malloc(pobject->length - COPS_OBJECT_HEADER_SIZE))) {
+                       if (!(pobject->contents = ast_malloc(pobject->length - COPS_OBJECT_HEADER_SIZE))) {
                                return -1;
                        }
                        lent = recv(sfd, pobject->contents, pobject->length - COPS_OBJECT_HEADER_SIZE, MSG_DONTWAIT);
@@ -396,12 +395,12 @@ static int cops_sendmsg (int sfd, struct copsmsg * sendmsg)
                return -1;
        }
 
-       ast_debug(3, "COPS: sending opcode: %i len: %i\n", sendmsg->opcode, sendmsg->length);
+       ast_debug(3, "COPS: sending opcode: %i len: %u\n", sendmsg->opcode, sendmsg->length);
        if (sendmsg->length < COPS_HEADER_SIZE) {
                ast_log(LOG_WARNING, "COPS: invalid msg size!!!\n");
                return -1;
        }
-       if (!(buf = malloc((size_t) sendmsg->length))) {
+       if (!(buf = ast_malloc((size_t) sendmsg->length))) {
                return -1;
        }
        *buf = sendmsg->verflag ;
@@ -417,16 +416,16 @@ static int cops_sendmsg (int sfd, struct copsmsg * sendmsg)
                while(pobject != NULL) {
                        ast_debug(3, "COPS: Sending Object : cnum: %i ctype %i len: %i\n", pobject->cnum, pobject->ctype, pobject->length);
                        if (sendmsg->length < bufpos + pobject->length) {
-                               ast_log(LOG_WARNING, "COPS: Invalid msg size len: %i objectlen: %i\n", sendmsg->length, pobject->length);
-                               free(buf);
+                               ast_log(LOG_WARNING, "COPS: Invalid msg size len: %u objectlen: %i\n", sendmsg->length, pobject->length);
+                               ast_free(buf);
                                return -1;
                        }
                        *(uint16_t *) (buf + bufpos) = htons(pobject->length);
                        *(buf + bufpos + 2) = pobject->cnum;
                        *(buf + bufpos + 3) = pobject->ctype;
                        if (sendmsg->length < pobject->length + bufpos) {
-                               ast_log(LOG_WARNING, "COPS: Error sum of object len more the msg len %i < %i\n", sendmsg->length, pobject->length + bufpos);
-                               free(buf);
+                               ast_log(LOG_WARNING, "COPS: Error sum of object len more the msg len %u < %i\n", sendmsg->length, pobject->length + bufpos);
+                               ast_free(buf);
                                return -1;
                        }
                        memcpy((buf + bufpos + 4), pobject->contents, pobject->length - 4);
@@ -443,18 +442,18 @@ static int cops_sendmsg (int sfd, struct copsmsg * sendmsg)
 #endif
        if (send(sfd, buf, sendmsg->length, SENDFLAGS) == -1) {
                ast_log(LOG_WARNING, "COPS: Send failed errno=%i\n", errno);
-               free(buf);
+               ast_free(buf);
                return -2;
        }
 #undef SENDFLAGS
-       free(buf);
+       ast_free(buf);
        return 0;
 }
 
 static void cops_freemsg(struct copsmsg *p)
 {
        struct pktcobj *pnext;
-       free(p->msg);
+       ast_free(p->msg);
        p->msg = NULL;
        while (p->object != NULL) {
                        pnext = p->object->next;
@@ -554,8 +553,8 @@ static struct cops_gate *cops_gate_cmd(int cmd, struct cops_cmts *cmts,
        
        gate->in_transaction = time(NULL);
 
-       if (!(gateset = malloc(sizeof(struct copsmsg)))) {
-               free(gateset);
+       if (!(gateset = ast_malloc(sizeof(struct copsmsg)))) {
+               ast_free(gateset);
                return NULL;
        }
        gateset->msg = NULL;
@@ -564,67 +563,67 @@ static struct cops_gate *cops_gate_cmd(int cmd, struct cops_cmts *cmts,
        gateset->clienttype = 0x8008; /* =PacketCable */
        
        /* Handle object */
-       gateset->object = malloc(sizeof(struct pktcobj));
+       gateset->object = ast_malloc(sizeof(struct pktcobj));
        if (!gateset->object) {
                cops_freemsg(gateset);
-               free(gateset);
+               ast_free(gateset);
                return NULL;
        }
        gateset->object->length = COPS_OBJECT_HEADER_SIZE + 4;
        gateset->object->cnum = 1; /* Handle */
        gateset->object->ctype = 1; /* client */
-       if (!(gateset->object->contents = malloc(sizeof(uint32_t)))) {
+       if (!(gateset->object->contents = ast_malloc(sizeof(uint32_t)))) {
                cops_freemsg(gateset);
-               free(gateset);
+               ast_free(gateset);
                return NULL;
        }
        *((uint32_t *) gateset->object->contents) = htonl(cmts->handle);
 
        /* Context Object */
-       if (!(gateset->object->next = malloc(sizeof(struct pktcobj)))) {
+       if (!(gateset->object->next = ast_malloc(sizeof(struct pktcobj)))) {
                cops_freemsg(gateset);
-               free(gateset);
+               ast_free(gateset);
                return NULL;
        }
        gateset->object->next->length = COPS_OBJECT_HEADER_SIZE + 4;
        gateset->object->next->cnum = 2; /* Context */
        gateset->object->next->ctype = 1; /* Context */
-       if (!(gateset->object->next->contents = malloc(sizeof(uint32_t)))) {
+       if (!(gateset->object->next->contents = ast_malloc(sizeof(uint32_t)))) {
                cops_freemsg(gateset);
-               free(gateset);
+               ast_free(gateset);
                return NULL;
        }
        *((uint32_t *) gateset->object->next->contents) = htonl(0x00080000); /* R-Type = 8 configuration request, M-Type = 0 */
 
        /* Decision Object: Flags */
-       if (!(gateset->object->next->next = malloc(sizeof(struct pktcobj)))) {
+       if (!(gateset->object->next->next = ast_malloc(sizeof(struct pktcobj)))) {
                cops_freemsg(gateset);
-               free(gateset);
+               ast_free(gateset);
                return NULL;
        }
        gateset->object->next->next->length = COPS_OBJECT_HEADER_SIZE + 4;
        gateset->object->next->next->cnum = 6; /* Decision */
        gateset->object->next->next->ctype = 1; /* Flags */
-       if (!(gateset->object->next->next->contents = malloc(sizeof(uint32_t)))) {
+       if (!(gateset->object->next->next->contents = ast_malloc(sizeof(uint32_t)))) {
                cops_freemsg(gateset);
-               free(gateset);
+               ast_free(gateset);
                return NULL;
        }
        *((uint32_t *) gateset->object->next->next->contents) = htonl(0x00010001); /* Install, Trigger Error */
 
        /* Decision Object: Data */
-       if (!(gateset->object->next->next->next = malloc(sizeof(struct pktcobj)))) {
+       if (!(gateset->object->next->next->next = ast_malloc(sizeof(struct pktcobj)))) {
                cops_freemsg(gateset);
-               free(gateset);
+               ast_free(gateset);
                return NULL;
        }
        gateset->object->next->next->next->length = COPS_OBJECT_HEADER_SIZE + ((cmd != GATE_INFO && cmd != GATE_DEL) ? GATE_SET_OBJ_SIZE : GATE_INFO_OBJ_SIZE) + ((cmd == GATE_SET_HAVE_GATEID) ? GATEID_OBJ_SIZE : 0);
        gateset->object->next->next->next->cnum = 6; /* Decision */
        gateset->object->next->next->next->ctype = 4; /* Decision Data */
-       gateset->object->next->next->next->contents = malloc(((cmd != GATE_INFO && cmd != GATE_DEL) ? GATE_SET_OBJ_SIZE : GATE_INFO_OBJ_SIZE) + ((cmd == GATE_SET_HAVE_GATEID) ? GATEID_OBJ_SIZE : 0));
+       gateset->object->next->next->next->contents = ast_malloc(((cmd != GATE_INFO && cmd != GATE_DEL) ? GATE_SET_OBJ_SIZE : GATE_INFO_OBJ_SIZE) + ((cmd == GATE_SET_HAVE_GATEID) ? GATEID_OBJ_SIZE : 0));
        if (!gateset->object->next->next->next->contents) {
                cops_freemsg(gateset);
-               free(gateset);
+               ast_free(gateset);
                return NULL;
        }
        gateset->object->next->next->next->next = NULL;
@@ -643,13 +642,13 @@ static struct cops_gate *cops_gate_cmd(int cmd, struct cops_cmts *cmts,
        }
        cops_sendmsg(cmts->sfd, gateset);
        cops_freemsg(gateset);
-       free(gateset);
+       ast_free(gateset);
        return gate;
 }
 
 static int cops_connect(char *host, char *port)
 {
-       int s, sfd = -1, flags;
+       int s, sfd = -1;
        struct addrinfo hints;
        struct addrinfo *rp;
        struct addrinfo *result;
@@ -675,10 +674,9 @@ static int cops_connect(char *host, char *port)
                if (sfd == -1) {
                        ast_log(LOG_WARNING, "Failed socket\n");
                }
-               flags = fcntl(sfd, F_GETFL);
-               fcntl(sfd, F_SETFL, flags | O_NONBLOCK);
+               ast_fd_set_flags(sfd, O_NONBLOCK);
 #ifdef HAVE_SO_NOSIGPIPE
-               setsockopt(sfd, SO_SOCKET, SO_NOSIGPIPE, &trueval, sizeof(trueval));
+               setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, &trueval, sizeof(trueval));
 #endif
                connect(sfd, rp->ai_addr, rp->ai_addrlen);
                if (sfd == -1) {
@@ -703,9 +701,8 @@ static void *do_pktccops(void *data)
        int res, nfds, len;
        struct copsmsg *recmsg, *sendmsg;
        struct copsmsg recmsgb, sendmsgb;
-       fd_set rfds;
-       struct timeval tv;
-       struct pktcobj *pobject;        
+       struct pollfd *pfds = NULL, *tmp;
+       struct pktcobj *pobject;
        struct cops_cmts *cmts;
        struct cops_gate *gate;
        char *sobjp;
@@ -719,15 +716,14 @@ static void *do_pktccops(void *data)
        ast_debug(3, "COPS: thread started\n");
 
        for (;;) {
-               tv.tv_sec = 1;
-               tv.tv_usec = 0;
-               FD_ZERO(&rfds);
+               ast_free(pfds);
+               pfds = NULL;
                nfds = 0;
                AST_LIST_LOCK(&cmts_list);
                AST_LIST_TRAVERSE(&cmts_list, cmts, list) {
                        if (last_exec != time(NULL)) {
                                if (cmts->state == 2 && cmts->katimer + cmts->keepalive < time(NULL)) {
-                                       ast_log(LOG_WARNING, "KA timer (%is) expired cmts: %s\n",  cmts->keepalive, cmts->name);
+                                       ast_log(LOG_WARNING, "KA timer (%us) expired cmts: %s\n",  cmts->keepalive, cmts->name);
                                        cmts->state = 0;
                                        cmts->katimer = -1;
                                        close(cmts->sfd);
@@ -735,15 +731,27 @@ static void *do_pktccops(void *data)
                                }
                        }
                        if (cmts->sfd > 0) {
-                               FD_SET(cmts->sfd, &rfds);
-                               if (cmts->sfd > nfds) nfds = cmts->sfd;
+                               if (!(tmp = ast_realloc(pfds, (nfds + 1) * sizeof(*pfds)))) {
+                                       continue;
+                               }
+                               pfds = tmp;
+                               pfds[nfds].fd = cmts->sfd;
+                               pfds[nfds].events = POLLIN;
+                               pfds[nfds].revents = 0;
+                               nfds++;
                        } else {
                                cmts->sfd = cops_connect(cmts->host, cmts->port);
                                if (cmts->sfd > 0) {
                                        cmts->state = 1;
                                        if (cmts->sfd > 0) {
-                                               FD_SET(cmts->sfd, &rfds);
-                                               if (cmts->sfd > nfds) nfds = cmts->sfd;
+                                               if (!(tmp = ast_realloc(pfds, (nfds + 1) * sizeof(*pfds)))) {
+                                                       continue;
+                                               }
+                                               pfds = tmp;
+                                               pfds[nfds].fd = cmts->sfd;
+                                               pfds[nfds].events = POLLIN;
+                                               pfds[nfds].revents = 0;
+                                               nfds++;
                                        }
                                }
                        }
@@ -781,21 +789,23 @@ static void *do_pktccops(void *data)
                if (pktcreload == 2) {
                        pktcreload = 0;
                }
-               if ((res = select(nfds + 1, &rfds, NULL, NULL, &tv))) {
+               if ((res = ast_poll(pfds, nfds, 1000))) {
                        AST_LIST_LOCK(&cmts_list);
                        AST_LIST_TRAVERSE(&cmts_list, cmts, list) {
-                               if (FD_ISSET(cmts->sfd, &rfds)) {
+                               int idx;
+                               if ((idx = ast_poll_fd_index(pfds, nfds, cmts->sfd)) > -1 && (pfds[idx].revents & POLLIN)) {
                                        len = cops_getmsg(cmts->sfd, recmsg);
                                        if (len > 0) {
-                                               ast_debug(3, "COPS: got from %s:\n Header: versflag=0x%.2x opcode=%i clienttype=0x%.4x msglength=%i\n",
-                                                       cmts->name, recmsg->verflag, recmsg->opcode, recmsg->clienttype, recmsg->length);
+                                               ast_debug(3, "COPS: got from %s:\n Header: versflag=0x%02hhx opcode=%i clienttype=0x%04hx msglength=%u\n",
+                                                       cmts->name, recmsg->verflag,
+                                                       recmsg->opcode, recmsg->clienttype, recmsg->length);
                                                if (recmsg->object != NULL) {
                                                        pobject = recmsg->object;
                                                        while (pobject != NULL) {
                                                                ast_debug(3, " OBJECT: length=%i cnum=%i ctype=%i\n", pobject->length, pobject->cnum, pobject->ctype);
                                                                if (recmsg->opcode == 1 && pobject->cnum == 1 && pobject->ctype == 1 ) {
                                                                        cmts->handle = ntohl(*((uint32_t *) pobject->contents));
-                                                                       ast_debug(3, "    REQ client handle: %i\n", cmts->handle);
+                                                                       ast_debug(3, "    REQ client handle: %u\n", cmts->handle);
                                                                        cmts->state = 2;
                                                                        cmts->katimer = time(NULL);
                                                                } else if (pobject->cnum == 9 && pobject->ctype == 1) {
@@ -811,7 +821,7 @@ static void *do_pktccops(void *data)
                                                                        while (sobjp < (pobject->contents + pobject->length - 4)) {
                                                                                sobjlen = ntohs(*((uint16_t *) sobjp));
                                                                                snst = ntohs(*((uint16_t *) (sobjp + 2)));
-                                                                               ast_debug(3, "   S-Num S-type: 0x%.4x len: %i\n", snst, sobjlen);
+                                                                               ast_debug(3, "   S-Num S-type: 0x%.4x len: %i\n", (unsigned)snst, sobjlen);
                                                                                if (snst == 0x0101 ) {
                                                                                        recvtrid = ntohs(*((uint16_t *) (sobjp + 4)));
                                                                                        scommand = ntohs(*((uint16_t *) (sobjp + 6)));                                  
@@ -831,7 +841,7 @@ static void *do_pktccops(void *data)
                                                                                } else if (snst == 0x0d01) {
                                                                                        reason = ntohs(*((uint16_t *) (sobjp + 4)));
                                                                                        subreason = ntohs(*((uint16_t *) (sobjp + 6)));
-                                                                                       ast_debug(3, "      Reason: %u Subreason: %u\n", reason, subreason);
+                                                                                       ast_debug(3, "      Reason: %d Subreason: %d\n", reason, subreason);
                                                                                }
                                                                                sobjp += sobjlen;
                                                                                if (!sobjlen)
@@ -916,11 +926,11 @@ static void *do_pktccops(void *data)
                                                        sendmsg->opcode = 7; /* Client Accept */
                                                        sendmsg->clienttype = 0x8008; /* =PacketCable */
                                                        sendmsg->length = COPS_HEADER_SIZE + COPS_OBJECT_HEADER_SIZE + 4;
-                                                       sendmsg->object = malloc(sizeof(struct pktcobj));
+                                                       sendmsg->object = ast_malloc(sizeof(struct pktcobj));
                                                        sendmsg->object->length = 4 + COPS_OBJECT_HEADER_SIZE;
                                                        sendmsg->object->cnum = 10; /* keppalive timer*/
                                                        sendmsg->object->ctype = 1;
-                                                       sendmsg->object->contents = malloc(sizeof(uint32_t));
+                                                       sendmsg->object->contents = ast_malloc(sizeof(uint32_t));
                                                        *((uint32_t *) sendmsg->object->contents) = htonl(cmts->keepalive & 0x0000ffff);
                                                        sendmsg->object->next = NULL;
                                                        cops_sendmsg(cmts->sfd, sendmsg);
@@ -967,7 +977,7 @@ static void *do_pktccops(void *data)
                                                close(cmts->sfd);
                                        }
                                        AST_LIST_REMOVE_CURRENT(list);
-                                       free(cmts);
+                                       ast_free(cmts);
                                }
                        }
                        AST_LIST_TRAVERSE_SAFE_END;
@@ -1017,7 +1027,7 @@ static int load_pktccops_config(void)
        struct cops_cmts *cmts;
        struct cops_ippool *new_ippool;
        const char *host, *cat, *port;
-       int sfd, update;
+       int update;
        int res = 0;
        uint16_t t1_temp, t7_temp, t8_temp;
        uint32_t keepalive_temp;
@@ -1051,7 +1061,6 @@ static int load_pktccops_config(void)
                        /* Defaults */
                        host = NULL;
                        port = NULL;
-                       sfd = 0;
                        t1_temp = t1;
                        t7_temp = t7;
                        t8_temp = t8;
@@ -1321,7 +1330,6 @@ static char *pktccops_gateset(struct ast_cli_entry *e, int cmd, struct ast_cli_a
        unsigned int an,bn,cn,dn;
        uint32_t mta, ssip;
        struct cops_cmts *cmts;
-       struct cops_gate *gate;
 
        switch (cmd) {
        case CLI_INIT:
@@ -1337,7 +1345,7 @@ static char *pktccops_gateset(struct ast_cli_entry *e, int cmd, struct ast_cli_a
        if (a->argc < 9)
                return CLI_SHOWUSAGE;
 
-       if (!strncmp(a->argv[2], "null", sizeof(a->argv[2]))) {
+       if (!strcmp(a->argv[2], "null")) {
                cmts = NULL;
        } else {
                AST_LIST_LOCK(&cmts_list);
@@ -1368,7 +1376,7 @@ static char *pktccops_gateset(struct ast_cli_entry *e, int cmd, struct ast_cli_a
        }
        ssip = an << 24 | bn << 16 | cn << 8 | dn;
 
-       gate = cops_gate_cmd(GATE_SET, cmts, trid, mta, atoi(a->argv[4]), atof(a->argv[5]), atoi(a->argv[6]), ssip, atoi(a->argv[8]), NULL);
+       cops_gate_cmd(GATE_SET, cmts, trid, mta, atoi(a->argv[4]), atof(a->argv[5]), atoi(a->argv[6]), ssip, atoi(a->argv[8]), NULL);
        return CLI_SUCCESS;
 }
 
@@ -1431,13 +1439,13 @@ static void pktccops_unregister_cmtses(void)
                if (cmts->sfd > 0) {
                        close(cmts->sfd);
                }
-               free(cmts);
+               ast_free(cmts);
        }
        AST_LIST_UNLOCK(&cmts_list);
 
        AST_LIST_LOCK(&gate_list);
        while ((gate = AST_LIST_REMOVE_HEAD(&gate_list, list))) {
-               free(gate);
+               ast_free(gate);
        }
        AST_LIST_UNLOCK(&gate_list);
 }
@@ -1447,7 +1455,7 @@ static void pktccops_unregister_ippools(void)
        struct cops_ippool *ippool;
        AST_LIST_LOCK(&ippool_list);
        while ((ippool = AST_LIST_REMOVE_HEAD(&ippool_list, list))) {
-               free(ippool);
+               ast_free(ippool);
        }
        AST_LIST_UNLOCK(&ippool_list);
 }
@@ -1463,6 +1471,10 @@ static int load_module(void)
        }
        ast_cli_register_multiple(cli_pktccops, sizeof(cli_pktccops) / sizeof(struct ast_cli_entry));
        restart_pktc_thread();
+
+       /* For Optional API. */
+       ast_module_shutdown_ref(AST_MODULE_SELF);
+
        return 0;
 }
 
@@ -1500,8 +1512,9 @@ static int reload_module(void)
 }
 
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "PktcCOPS manager for MGCP",
-               .load = load_module,
-               .unload = unload_module,
-               .reload = reload_module,
-              );
+       .support_level = AST_MODULE_SUPPORT_EXTENDED,
+       .load = load_module,
+       .unload = unload_module,
+       .reload = reload_module,
+);