Annotation of embedaddon/miniupnpd/miniupnpc-libevent/upnpc-libevent.c, revision 1.1

1.1     ! misho       1: /* $Id: upnpc-libevent.c,v 1.11 2014/12/02 13:33:42 nanard Exp $ */
        !             2: /* miniupnpc-libevent
        !             3:  * Copyright (c) 2008-2014, Thomas BERNARD <miniupnp@free.fr>
        !             4:  * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
        !             5:  *
        !             6:  * Permission to use, copy, modify, and/or distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
        !            17: 
        !            18: #include <stdio.h>
        !            19: #include <string.h>
        !            20: #include <signal.h>
        !            21: #include <unistd.h>
        !            22: #include <sys/socket.h>
        !            23: #include <netinet/in.h>
        !            24: #include <arpa/inet.h>
        !            25: 
        !            26: #include "miniupnpc-libevent.h"
        !            27: 
        !            28: static struct event_base *base = NULL;
        !            29: static char local_address[32];
        !            30: 
        !            31: static void sighandler(int signal)
        !            32: {
        !            33:        (void)signal;
        !            34:        /*printf("signal %d\n", signal);*/
        !            35:        if(base != NULL)
        !            36:                event_base_loopbreak(base);
        !            37: }
        !            38: 
        !            39: /* ready callback */
        !            40: static void ready(int code, upnpc_t * p, upnpc_device_t * d, void * data)
        !            41: {
        !            42:        (void)data; (void)p;
        !            43: 
        !            44:        if(code == 200) {
        !            45:                printf("READY ! %d\n", code);
        !            46:                printf("  root_desc_location='%s'\n", d->root_desc_location);
        !            47:                /* 1st request */
        !            48: #ifdef ENABLE_UPNP_EVENTS
        !            49:                upnpc_event_subscribe(d);
        !            50: #else
        !            51:                upnpc_get_status_info(d);
        !            52: #endif /* ENABLE_UPNP_EVENTS */
        !            53:        } else {
        !            54:                printf("DISCOVER ERROR : %d\n", code);
        !            55:                switch(code) {
        !            56:                case UPNPC_ERR_NO_DEVICE_FOUND:
        !            57:                        printf("UPNPC_ERR_NO_DEVICE_FOUND\n");
        !            58:                        break;
        !            59:                case UPNPC_ERR_ROOT_DESC_ERROR:
        !            60:                        printf("UPNPC_ERR_ROOT_DESC_ERROR\n");
        !            61:                        break;
        !            62:                case 404:
        !            63:                        printf("Root desc not found (404)\n");
        !            64:                        break;
        !            65:                default:
        !            66:                        printf("unknown error\n");
        !            67:                }
        !            68:        }
        !            69: }
        !            70: 
        !            71: static enum {
        !            72:        EGetStatusInfo = 0,
        !            73:        EGetExtIp,
        !            74:        EGetMaxRate,
        !            75:        EAddPortMapping,
        !            76:        EDeletePortMapping,
        !            77:        EFinished
        !            78:        } state = EGetStatusInfo;
        !            79: 
        !            80: /* soap callback */
        !            81: static void soap(int code, upnpc_t * p, upnpc_device_t * d, void * data)
        !            82: {
        !            83:        (void)data; (void)p;
        !            84: 
        !            85:        printf("SOAP ! %d\n", code);
        !            86:        if(code == 200) {
        !            87:                switch(state) {
        !            88:                case EGetStatusInfo:
        !            89:                        printf("ConnectionStatus=%s\n", GetValueFromNameValueList(&d->soap_response_data, "NewConnectionStatus"));
        !            90:                        printf("LastConnectionError=%s\n", GetValueFromNameValueList(&d->soap_response_data, "NewLastConnectionError"));
        !            91:                        printf("Uptime=%s\n", GetValueFromNameValueList(&d->soap_response_data, "NewUptime"));
        !            92:                        upnpc_get_external_ip_address(d);
        !            93:                        state = EGetExtIp;
        !            94:                        break;
        !            95:                case EGetExtIp:
        !            96:                        printf("ExternalIpAddress=%s\n", GetValueFromNameValueList(&d->soap_response_data, "NewExternalIPAddress"));
        !            97:                        upnpc_get_link_layer_max_rate(d);
        !            98:                        state = EGetMaxRate;
        !            99:                        break;
        !           100:                case EGetMaxRate:
        !           101:                        printf("DownStream MaxBitRate = %s\t", GetValueFromNameValueList(&d->soap_response_data, "NewLayer1DownstreamMaxBitRate"));
        !           102:                        upnpc_add_port_mapping(d, NULL, 60001, 60002, local_address, "TCP", "test port mapping", 0);
        !           103:                        printf("UpStream MaxBitRate = %s\n", GetValueFromNameValueList(&d->soap_response_data, "NewLayer1UpstreamMaxBitRate"));
        !           104:                        state = EAddPortMapping;
        !           105:                        break;
        !           106:                case EAddPortMapping:
        !           107:                        printf("AddPortMapping OK!\n");
        !           108:                        upnpc_delete_port_mapping(d, NULL, 60001, "TCP");
        !           109:                        state = EDeletePortMapping;
        !           110:                        break;
        !           111:                case EDeletePortMapping:
        !           112:                        printf("DeletePortMapping OK!\n");
        !           113:                        state = EFinished;
        !           114:                        break;
        !           115:                default:
        !           116:                        printf("EFinished : breaking\n");
        !           117:                        event_base_loopbreak(base);
        !           118:                }
        !           119:        } else {
        !           120:                printf("SOAP error :\n");
        !           121:                printf("  faultcode='%s'\n", GetValueFromNameValueList(&d->soap_response_data, "faultcode"));
        !           122:                printf("  faultstring='%s'\n", GetValueFromNameValueList(&d->soap_response_data, "faultstring"));
        !           123:                printf("  errorCode=%s\n", GetValueFromNameValueList(&d->soap_response_data, "errorCode"));
        !           124:                printf("  errorDescription='%s'\n", GetValueFromNameValueList(&d->soap_response_data, "errorDescription"));
        !           125:                event_base_loopbreak(base);
        !           126:        }
        !           127: }
        !           128: 
        !           129: #ifdef ENABLE_UPNP_EVENTS
        !           130: /* event callback */
        !           131: static void event_callback(upnpc_t * p, upnpc_device_t * d, void * data,
        !           132:                            const char * service_id, const char * property_name, const char * property_value)
        !           133: {
        !           134:        (void)p; (void)d; (void)data;
        !           135:        printf("PROPERTY VALUE CHANGE (service=%s): %s=%s\n", service_id, property_name, property_value);
        !           136: }
        !           137: #endif /* ENABLE_UPNP_EVENTS */
        !           138: 
        !           139: /* use a UDP "connection" to 8.8.8.8
        !           140:  * to retrieve local address */
        !           141: int find_local_address(void)
        !           142: {
        !           143:        int s;
        !           144:        struct sockaddr_in local, remote;
        !           145:        socklen_t len;
        !           146: 
        !           147:        s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        !           148:        if(s < 0) {
        !           149:                perror("socket");
        !           150:                return -1;
        !           151:        }
        !           152: 
        !           153:        memset(&local, 0, sizeof(local));
        !           154:        memset(&remote, 0, sizeof(remote));
        !           155:        /* bind to local port 4567 */
        !           156:        local.sin_family = AF_INET;
        !           157:        local.sin_port = htons(4567);
        !           158:        local.sin_addr.s_addr = htonl(INADDR_ANY);
        !           159:        if(bind(s, (struct sockaddr *)&local, sizeof(local)) < 0) {
        !           160:                perror("bind");
        !           161:                return -1;
        !           162:        }
        !           163:        /* "connect" google's DNS server at 8.8.8.8 port 4567 */
        !           164:        remote.sin_family = AF_INET;
        !           165:        remote.sin_port = htons(4567);
        !           166:        remote.sin_addr.s_addr = inet_addr("8.8.8.8");
        !           167:        if(connect(s, (struct sockaddr *)&remote, sizeof(remote)) < 0) {
        !           168:                perror("connect");
        !           169:                return -1;
        !           170:        }
        !           171:        len = sizeof(local);
        !           172:        if(getsockname(s, (struct sockaddr *)&local, &len) < 0) {
        !           173:                perror("getsockname");
        !           174:                return -1;
        !           175:        }
        !           176:        if(inet_ntop(AF_INET, &(local.sin_addr), local_address, sizeof(local_address)) == NULL) {
        !           177:                perror("inet_ntop");
        !           178:                return -1;
        !           179:        }
        !           180:        printf("local address : %s\n", local_address);
        !           181:        close(s);
        !           182:        return 0;
        !           183: }
        !           184: 
        !           185: /* program entry point */
        !           186: 
        !           187: int main(int argc, char * * argv)
        !           188: {
        !           189:        struct sigaction sa;
        !           190:        upnpc_t upnp;
        !           191:        char * multicast_if = NULL;
        !           192: 
        !           193:        if(argc > 1) {
        !           194:                multicast_if = argv[1];
        !           195:        }
        !           196: 
        !           197:        memset(&sa, 0, sizeof(struct sigaction));
        !           198:        sa.sa_handler = sighandler;
        !           199:        if(sigaction(SIGINT, &sa, NULL) < 0) {
        !           200:                perror("sigaction");
        !           201:        }
        !           202: 
        !           203:        if(find_local_address() < 0) {
        !           204:                fprintf(stderr, "failed to get local address\n");
        !           205:                return 1;
        !           206:        }
        !           207: #ifdef DEBUG
        !           208:        event_enable_debug_mode();
        !           209: #if LIBEVENT_VERSION_NUMBER >= 0x02010100
        !           210:        event_enable_debug_logging(EVENT_DBG_ALL);      /* Libevent 2.1.1 */
        !           211: #endif /* LIBEVENT_VERSION_NUMBER >= 0x02010100 */
        !           212: #endif /* DEBUG */
        !           213:        printf("Using libevent %s\n", event_get_version());
        !           214:        if(LIBEVENT_VERSION_NUMBER != event_get_version_number()) {
        !           215:                fprintf(stderr, "WARNING build using libevent %s", LIBEVENT_VERSION);
        !           216:        }
        !           217: 
        !           218:        base = event_base_new();
        !           219:        if(base == NULL) {
        !           220:                fprintf(stderr, "event_base_new() failed\n");
        !           221:                return 1;
        !           222:        }
        !           223: #ifdef DEBUG
        !           224:        printf("Using Libevent with backend method %s.\n",
        !           225:         event_base_get_method(base));
        !           226: #endif /* DEBUG */
        !           227: 
        !           228:        if(upnpc_init(&upnp, base, multicast_if, ready, soap, &upnp) != UPNPC_OK) {
        !           229:                fprintf(stderr, "upnpc_init() failed\n");
        !           230:                return 1;
        !           231:        }
        !           232:        upnpc_set_local_address(&upnp, local_address, 50000);
        !           233: #ifdef ENABLE_UPNP_EVENTS
        !           234:        upnpc_set_event_callback(&upnp, event_callback);
        !           235: #endif /* ENABLE_UPNP_EVENTS */
        !           236:        if(upnpc_start(&upnp) != UPNPC_OK) {
        !           237:                fprintf(stderr, "upnp_start() failed\n");
        !           238:                return 1;
        !           239:        }
        !           240: 
        !           241:        event_base_dispatch(base);      /* TODO : check return value */
        !           242:        printf("finishing...\n");
        !           243: 
        !           244:        upnpc_finalize(&upnp);
        !           245:        event_base_free(base);
        !           246: 
        !           247: #if LIBEVENT_VERSION_NUMBER >= 0x02010100
        !           248:        libevent_global_shutdown();     /* Libevent 2.1.1 */
        !           249: #endif
        !           250:        return 0;
        !           251: }
        !           252: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>