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>