Annotation of embedaddon/miniupnpd/miniupnpc-libevent/upnpc-libevent.c, revision 1.1.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>