Remove third-party code stored in the repo directly

This commit is contained in:
Mike Gelfand
2017-01-01 16:01:00 +03:00
parent 4179a623d5
commit 2de12f50c5
74 changed files with 0 additions and 15801 deletions

View File

@@ -1,133 +0,0 @@
3 May 2014: dht-0.22
* INCOMPATIBLE CHANGE: the callback now takes const arguments.
* Consult the local storage when performing a search, which should
make bootstrapping of tiny DHTs easier. Note that we're still not
performing local stores, since that would require knowing our IP
address.
* Don't attempt to flush the debug stream if debugging is disabled.
This appears to work around a bug in Transmission.
25 July 2011: dht-0.21
* Blacklisting support.
7 July 2011: dht-0.20
* Fix compilation on systems that have memmem but don't define HAVE_MEMMEM.
30 April 2011: dht-0.19
* Fix incorrect parsing of announces. Thanks to cjdelisle.
* Relax rate limiting slightly.
20 January 2011: dht-0.18
* Fix a bug that could cause parse_message to enter an infinite loop
on overflow. Thanks to Jordan Lee.
9 January 2011: dht-0.17:
* Fix a bug that prevented calling dht_init after dht_uninit.
* Remove the "dofree" parameter to dht_uninit.
23 December 2010: dht-0.16:
* Change the interface to allow sharing of the UDP socket e.g. with uTP.
1 July 2010: dht-0.15
* Port to Windows, for the needs of Transmission.
25 March 2010: dht-0.14
* Fixed ordering of entries in parameter dictionaries.
15 December 2009: dht-0.13
* Implemented protection against incorrect addresses in the DHT.
* Tweaked neighborhood maintenance to wake up less often.
11 December 2009: dht-0.12
* Fixed slightly incorrect formatting of DHT messages.
* Fixed incorrect debugging message.
22 November 2009: dht-0.11
* Implemented IPv6 support (BEP-32).
* Fixed a bug which could cause us to never mark a search as finished.
* Fixed a bug that could cause us to send incomplete lists in response to
find_nodes.
* Limit the number of hashes that we're willing to track.
* Made bucket maintenance slightly more aggressive.
* Produce on-the-wire error messages to give a hint to the other side.
* Added a bunch of options to dht-example to make it useful as
a bootstrap node.
* Send version "JC\0\0" when using dht-example.
18 October 2009: dht-0.10
* Send nodes even when sending values. This is a violation of the
protocol, but I have been assured that it doesn't break any deployed
implementation. This is also what both libtorrent and uTorrent do.
* Give up immediately on a search peer when no token was provided. This
is a very reasonable extension to the protocol, and certainly doesn't
break anything.
* Parse heterogeneous values lists correctly. This is mandated by BEP 32.
20 September 2009: dht-0.9
* Fixed incorrect computation of number of nodes.
* Made the initial bucket split eagerly (speeds up bootstrapping).
* Fixed initial filling of search buckets (speeds up searches).
28 July 2009: dht-0.8
* Fixed a crash when expiring the first search on the list.
* Fixed freeing of the search list when uniniting with dofree = 1.
24 June 2009: dht-0.7
* Removed the fixed limit on the number of concurrent searches, we now
use a linked list.
* Fixed build on FreeBSD (thanks to Humihara and Charles Kerr).
22 May 2009: dht-0.6
* Fixed a buffer overflow (when reading) in parse_message.
* Fixed slightly inacurrate metric computation when searching.
* Removed a slightly inaccurate shortcut when responding to find_nodes.
* Relaxed the rate-limiting parameters to 4 requests per second.
19 May 2009: dht-0.5
* Made reading of /dev/urandom a function provided by the user.
* Implemented the ``v'' extension that identifies node implementations.
18 May 2009: dht-0.4
* Fixed the handling of tokens in announce_peer messages.
* Implemented backtracking during search when nodes turn out to be dead.
17 May 2009: dht-0.3
* Fixed a number of incorrectly formatted messages.
* Changed reply to find_peers to spread the load more uniformly.
* Fixed a bug that could cause premature splitting.
* Implemented rate limiting.
* Changed some time constants to be less chatty.
* When determining if a bucket is fresh enough, we now only take replies
into account.
* dht_get_nodes now returns nodes starting with our own bucket.
* Tweaked the memory allocation strategy for stored peers.
17 May 2009: dht-0.2
* Fixed a crash in dht_uninit.
* Added support for saving the list of known-good nodes.
* Changed the interface of dht_nodes to provide the number of nodes that
recently sent incoming requests.
13 May 2009: dht-0.1
* Initial public release.

View File

@@ -1,19 +0,0 @@
Copyright (c) 2009, 2010 by Juliusz Chroboczek
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1,6 +0,0 @@
AM_CFLAGS = @PTHREAD_CFLAGS@
noinst_LIBRARIES = libdht.a
libdht_a_SOURCES = dht.c
noinst_HEADERS = dht.h
EXTRA_DIST = CHANGES dht-example.c LICENCE README

198
third-party/dht/README vendored
View File

@@ -1,198 +0,0 @@
The files dht.c and dht.h implement the variant of the Kademlia Distributed
Hash Table (DHT) used in the Bittorrent network (``mainline'' variant).
The file dht-example.c is a stand-alone program that participates in the
DHT. Another example is a patch against Transmission, which you might or
might not be able to find somewhere.
The code is designed to work well in both event-driven and threaded code.
The caller, which is either an event-loop or a dedicated thread, must
periodically call the function dht_periodic. In addition, it must call
dht_periodic whenever any data has arrived from the network.
All functions return -1 in case of failure, in which case errno is set, or
a positive value in case of success.
Initialisation
**************
* dht_init
This must be called before using the library. You pass it a bound IPv4
datagram socket, a bound IPv6 datagram socket, and your node id, a 20-octet
array that should be globally unique.
If you're on a multi-homed host, you should bind the sockets to one of your
addresses.
Node ids must be well distributed, so you cannot just use your Bittorrent
id; you should either generate a truly random value (using plenty of
entropy), or at least take the SHA-1 of something. However, it is a good
idea to keep the id stable, so you may want to store it in stable storage
at client shutdown.
* dht_uninit
This may be called at the end of the session.
Bootstrapping
*************
The DHT needs to be taught a small number of contacts to begin functioning.
You can hard-wire a small number of stable nodes in your application, but
this obviously fails to scale. You may save the list of known good nodes
at shutdown, and restore it at restart. You may also grab nodes from
torrent files (the nodes field), and you may exchange contacts with other
Bittorrent peers using the PORT extension.
* dht_ping
This is the main bootstrapping primitive. You pass it an address at which
you believe that a DHT node may be living, and a query will be sent. If
a node replies, and if there is space in the routing table, it will be
inserted.
* dht_insert_node
This is a softer bootstrapping method, which doesn't actually send
a query -- it only stores the node in the routing table for later use. It
is a good idea to use that when e.g. restoring your routing table from
disk.
Note that dht_insert_node requires that you supply a node id. If the id
turns out to be wrong, the DHT will eventually recover; still, inserting
massive amounts of incorrect information into your routing table is
certainly not a good idea.
An additionaly difficulty with dht_insert_node is that, for various
reasons, a Kademlia routing table cannot absorb nodes faster than a certain
rate. Dumping a large number of nodes into a table using dht_insert_node
will probably cause most of these nodes to be discarded straight away.
(The tolerable rate is difficult to estimate; it is probably on the order
of one node every few seconds per node already in the table divided by 8,
for some suitable value of 8.)
Doing some work
***************
* dht_periodic
This function should be called by your main loop periodically, and also
whenever data is available on the socket. The time after which
dht_periodic should be called if no data is available is returned in the
parameter tosleep. (You do not need to be particularly accurate; actually,
it is a good idea to be late by a random value.)
The parameters buf, buflen, from and fromlen optionally carry a received
message. If buflen is 0, then no message was received.
Dht_periodic also takes a callback, which will be called whenever something
interesting happens (see below).
* dht_search
This schedules a search for information about the info-hash specified in
id. If port is not 0, it specifies the TCP port on which the current peer
is listening; in that case, when the search is complete it will be announced
to the network. The port is in host order, beware if you got it from
a struct sockaddr_in.
In either case, data is passed to the callback function as soon as it is
available, possibly in multiple pieces. The callback function will
additionally be called when the search is complete.
Up to DHT_MAX_SEARCHES (1024) searches can be in progress at a given time;
any more, and dht_search will return -1. If you specify a new search for
the same info hash as a search still in progress, the previous search is
combined with the new one -- you will only receive a completion indication
once.
Information queries
*******************
* dht_nodes
This returns the number of known good, dubious and cached nodes in our
routing table. This can be used to decide whether it's reasonable to start
a search; a search is likely to be successful as long as we have a few good
nodes; however, in order to avoid overloading your bootstrap nodes, you may
want to wait until good is at least 4 and good + doubtful is at least 30 or
so.
It also includes the number of nodes that recently send us an unsolicited
request; this can be used to determine if the UDP port used for the DHT is
firewalled.
If you want to display a single figure to the user, you should display
good + doubtful, which is the total number of nodes in your routing table.
Some clients try to estimate the total number of nodes, but this doesn't
make much sense -- since the result is exponential in the number of nodes
in the routing table, small variations in the latter cause huge jumps in
the former.
* dht_get_nodes
This retrieves the list of known good nodes, starting with the nodes in our
own bucket. It is a good idea to save the list of known good nodes at
shutdown, and ping them at startup.
* dht_dump_tables
* dht_debug
These are debugging aids.
Functions provided by you
*************************
* The callback function
The callback function is called with 5 arguments. Closure is simply the
value that you passed to dht_periodic. Event is one of DHT_EVENT_VALUES or
DHT_EVENT_VALUES6, which indicates that we have new values, or
DHT_EVENT_SEARCH_DONE or DHT_EVENT_SEARCH_DONE6, which indicates that
a search has completed. In either case, info_hash is set to the info-hash
of the search.
In the case of DHT_EVENT_VALUES, data is a list of nodes in ``compact''
format -- 6 or 18 bytes per node. Its length in bytes is in data_len.
* dht_blacklisted
This is a function that takes an IP address and returns true if this
address should be silently ignored. Do not use this feature unless you
really must -- Kademlia supposes transitive reachability.
* dht_hash
This should compute a reasonably strong cryptographic hash of the passed
values. It should map cleanly to your favourite crypto toolkit's MD5 or
SHA-1 function.
* dht_random_bytes
This should fill the supplied buffer with true random bytes.
Final notes
***********
* NAT
Nothing works well across NATs, but Kademlia is somewhat less impacted than
many other protocols. The implementation takes care to distinguish between
unidirectional and bidirectional reachability, and NATed nodes will
eventually fall out from other nodes' routing tables.
While there is no periodic pinging in this implementation, maintaining
a full routing table requires slightly more than one packet exchange per
minute, even in a completely idle network; this should be sufficient to
make most full cone NATs happy.
* Missing functionality
Some of the code has had very little testing. If it breaks, you get to
keep both pieces.
Juliusz Chroboczek
<jch@pps.jussieu.fr>

View File

@@ -1,480 +0,0 @@
/* This example code was written by Juliusz Chroboczek.
You are free to cut'n'paste from it to your heart's content. */
/* For crypt */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/signal.h>
#include "dht.h"
#define MAX_BOOTSTRAP_NODES 20
static struct sockaddr_storage bootstrap_nodes[MAX_BOOTSTRAP_NODES];
static int num_bootstrap_nodes = 0;
static volatile sig_atomic_t dumping = 0, searching = 0, exiting = 0;
static void
sigdump(int signo)
{
dumping = 1;
}
static void
sigtest(int signo)
{
searching = 1;
}
static void
sigexit(int signo)
{
exiting = 1;
}
static void
init_signals(void)
{
struct sigaction sa;
sigset_t ss;
sigemptyset(&ss);
sa.sa_handler = sigdump;
sa.sa_mask = ss;
sa.sa_flags = 0;
sigaction(SIGUSR1, &sa, NULL);
sigemptyset(&ss);
sa.sa_handler = sigtest;
sa.sa_mask = ss;
sa.sa_flags = 0;
sigaction(SIGUSR2, &sa, NULL);
sigemptyset(&ss);
sa.sa_handler = sigexit;
sa.sa_mask = ss;
sa.sa_flags = 0;
sigaction(SIGINT, &sa, NULL);
}
const unsigned char hash[20] = {
0x54, 0x57, 0x87, 0x89, 0xdf, 0xc4, 0x23, 0xee, 0xf6, 0x03,
0x1f, 0x81, 0x94, 0xa9, 0x3a, 0x16, 0x98, 0x8b, 0x72, 0x7b
};
/* The call-back function is called by the DHT whenever something
interesting happens. Right now, it only happens when we get a new value or
when a search completes, but this may be extended in future versions. */
static void
callback(void *closure,
int event,
const unsigned char *info_hash,
const void *data, size_t data_len)
{
if(event == DHT_EVENT_SEARCH_DONE)
printf("Search done.\n");
else if(event == DHT_EVENT_VALUES)
printf("Received %d values.\n", (int)(data_len / 6));
}
static unsigned char buf[4096];
int
main(int argc, char **argv)
{
int i, rc, fd;
int s = -1, s6 = -1, port;
int have_id = 0;
unsigned char myid[20];
time_t tosleep = 0;
char *id_file = "dht-example.id";
int opt;
int quiet = 0, ipv4 = 1, ipv6 = 1;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
struct sockaddr_storage from;
socklen_t fromlen;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
while(1) {
opt = getopt(argc, argv, "q46b:i:");
if(opt < 0)
break;
switch(opt) {
case 'q': quiet = 1; break;
case '4': ipv6 = 0; break;
case '6': ipv4 = 0; break;
case 'b': {
char buf[16];
int rc;
rc = inet_pton(AF_INET, optarg, buf);
if(rc == 1) {
memcpy(&sin.sin_addr, buf, 4);
break;
}
rc = inet_pton(AF_INET6, optarg, buf);
if(rc == 1) {
memcpy(&sin6.sin6_addr, buf, 16);
break;
}
goto usage;
}
break;
case 'i':
id_file = optarg;
break;
default:
goto usage;
}
}
/* Ids need to be distributed evenly, so you cannot just use your
bittorrent id. Either generate it randomly, or take the SHA-1 of
something. */
fd = open(id_file, O_RDONLY);
if(fd >= 0) {
rc = read(fd, myid, 20);
if(rc == 20)
have_id = 1;
close(fd);
}
fd = open("/dev/urandom", O_RDONLY);
if(fd < 0) {
perror("open(random)");
exit(1);
}
if(!have_id) {
int ofd;
rc = read(fd, myid, 20);
if(rc < 0) {
perror("read(random)");
exit(1);
}
have_id = 1;
close(fd);
ofd = open(id_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if(ofd >= 0) {
rc = write(ofd, myid, 20);
if(rc < 20)
unlink(id_file);
close(ofd);
}
}
{
unsigned seed;
read(fd, &seed, sizeof(seed));
srandom(seed);
}
close(fd);
if(argc < 2)
goto usage;
i = optind;
if(argc < i + 1)
goto usage;
port = atoi(argv[i++]);
if(port <= 0 || port >= 0x10000)
goto usage;
while(i < argc) {
struct addrinfo hints, *info, *infop;
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM;
if(!ipv6)
hints.ai_family = AF_INET;
else if(!ipv4)
hints.ai_family = AF_INET6;
else
hints.ai_family = 0;
rc = getaddrinfo(argv[i], argv[i + 1], &hints, &info);
if(rc != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rc));
exit(1);
}
i++;
if(i >= argc)
goto usage;
infop = info;
while(infop) {
memcpy(&bootstrap_nodes[num_bootstrap_nodes],
infop->ai_addr, infop->ai_addrlen);
infop = infop->ai_next;
num_bootstrap_nodes++;
}
freeaddrinfo(info);
i++;
}
/* If you set dht_debug to a stream, every action taken by the DHT will
be logged. */
if(!quiet)
dht_debug = stdout;
/* We need an IPv4 and an IPv6 socket, bound to a stable port. Rumour
has it that uTorrent works better when it is the same as your
Bittorrent port. */
if(ipv4) {
s = socket(PF_INET, SOCK_DGRAM, 0);
if(s < 0) {
perror("socket(IPv4)");
}
}
if(ipv6) {
s6 = socket(PF_INET6, SOCK_DGRAM, 0);
if(s6 < 0) {
perror("socket(IPv6)");
}
}
if(s < 0 && s6 < 0) {
fprintf(stderr, "Eek!");
exit(1);
}
if(s >= 0) {
sin.sin_port = htons(port);
rc = bind(s, (struct sockaddr*)&sin, sizeof(sin));
if(rc < 0) {
perror("bind(IPv4)");
exit(1);
}
}
if(s6 >= 0) {
int rc;
int val = 1;
rc = setsockopt(s6, IPPROTO_IPV6, IPV6_V6ONLY,
(char *)&val, sizeof(val));
if(rc < 0) {
perror("setsockopt(IPV6_V6ONLY)");
exit(1);
}
/* BEP-32 mandates that we should bind this socket to one of our
global IPv6 addresses. In this simple example, this only
happens if the user used the -b flag. */
sin6.sin6_port = htons(port);
rc = bind(s6, (struct sockaddr*)&sin6, sizeof(sin6));
if(rc < 0) {
perror("bind(IPv6)");
exit(1);
}
}
/* Init the dht. This sets the socket into non-blocking mode. */
rc = dht_init(s, s6, myid, (unsigned char*)"JC\0\0");
if(rc < 0) {
perror("dht_init");
exit(1);
}
init_signals();
/* For bootstrapping, we need an initial list of nodes. This could be
hard-wired, but can also be obtained from the nodes key of a torrent
file, or from the PORT bittorrent message.
Dht_ping_node is the brutal way of bootstrapping -- it actually
sends a message to the peer. If you're going to bootstrap from
a massive number of nodes (for example because you're restoring from
a dump) and you already know their ids, it's better to use
dht_insert_node. If the ids are incorrect, the DHT will recover. */
for(i = 0; i < num_bootstrap_nodes; i++) {
dht_ping_node((struct sockaddr*)&bootstrap_nodes[i],
sizeof(bootstrap_nodes[i]));
usleep(random() % 100000);
}
while(1) {
struct timeval tv;
fd_set readfds;
tv.tv_sec = tosleep;
tv.tv_usec = random() % 1000000;
FD_ZERO(&readfds);
if(s >= 0)
FD_SET(s, &readfds);
if(s6 >= 0)
FD_SET(s6, &readfds);
rc = select(s > s6 ? s + 1 : s6 + 1, &readfds, NULL, NULL, &tv);
if(rc < 0) {
if(errno != EINTR) {
perror("select");
sleep(1);
}
}
if(exiting)
break;
if(rc > 0) {
fromlen = sizeof(from);
if(s >= 0 && FD_ISSET(s, &readfds))
rc = recvfrom(s, buf, sizeof(buf) - 1, 0,
(struct sockaddr*)&from, &fromlen);
else if(s6 >= 0 && FD_ISSET(s6, &readfds))
rc = recvfrom(s6, buf, sizeof(buf) - 1, 0,
(struct sockaddr*)&from, &fromlen);
else
abort();
}
if(rc > 0) {
buf[rc] = '\0';
rc = dht_periodic(buf, rc, (struct sockaddr*)&from, fromlen,
&tosleep, callback, NULL);
} else {
rc = dht_periodic(NULL, 0, NULL, 0, &tosleep, callback, NULL);
}
if(rc < 0) {
if(errno == EINTR) {
continue;
} else {
perror("dht_periodic");
if(rc == EINVAL || rc == EFAULT)
abort();
tosleep = 1;
}
}
/* This is how you trigger a search for a torrent hash. If port
(the second argument) is non-zero, it also performs an announce.
Since peers expire announced data after 30 minutes, it's a good
idea to reannounce every 28 minutes or so. */
if(searching) {
if(s >= 0)
dht_search(hash, 0, AF_INET, callback, NULL);
if(s6 >= 0)
dht_search(hash, 0, AF_INET6, callback, NULL);
searching = 0;
}
/* For debugging, or idle curiosity. */
if(dumping) {
dht_dump_tables(stdout);
dumping = 0;
}
}
{
struct sockaddr_in sin[500];
struct sockaddr_in6 sin6[500];
int num = 500, num6 = 500;
int i;
i = dht_get_nodes(sin, &num, sin6, &num6);
printf("Found %d (%d + %d) good nodes.\n", i, num, num6);
}
dht_uninit();
return 0;
usage:
printf("Usage: dht-example [-q] [-4] [-6] [-i filename] [-b address]...\n"
" port [address port]...\n");
exit(1);
}
/* Functions called by the DHT. */
int
dht_blacklisted(const struct sockaddr *sa, int salen)
{
return 0;
}
/* We need to provide a reasonably strong cryptographic hashing function.
Here's how we'd do it if we had RSA's MD5 code. */
#if 0
void
dht_hash(void *hash_return, int hash_size,
const void *v1, int len1,
const void *v2, int len2,
const void *v3, int len3)
{
static MD5_CTX ctx;
MD5Init(&ctx);
MD5Update(&ctx, v1, len1);
MD5Update(&ctx, v2, len2);
MD5Update(&ctx, v3, len3);
MD5Final(&ctx);
if(hash_size > 16)
memset((char*)hash_return + 16, 0, hash_size - 16);
memcpy(hash_return, ctx.digest, hash_size > 16 ? 16 : hash_size);
}
#else
/* But for this example, we might as well use something weaker. */
void
dht_hash(void *hash_return, int hash_size,
const void *v1, int len1,
const void *v2, int len2,
const void *v3, int len3)
{
const char *c1 = v1, *c2 = v2, *c3 = v3;
char key[9]; /* crypt is limited to 8 characters */
int i;
memset(key, 0, 9);
#define CRYPT_HAPPY(c) ((c % 0x60) + 0x20)
for(i = 0; i < 2 && i < len1; i++)
key[i] = CRYPT_HAPPY(c1[i]);
for(i = 0; i < 4 && i < len1; i++)
key[2 + i] = CRYPT_HAPPY(c2[i]);
for(i = 0; i < 2 && i < len1; i++)
key[6 + i] = CRYPT_HAPPY(c3[i]);
strncpy(hash_return, crypt(key, "jc"), hash_size);
}
#endif
int
dht_random_bytes(void *buf, size_t size)
{
int fd, rc, save;
fd = open("/dev/urandom", O_RDONLY);
if(fd < 0)
return -1;
rc = read(fd, buf, size);
save = errno;
close(fd);
errno = save;
return rc;
}

2969
third-party/dht/dht.c vendored

File diff suppressed because it is too large Load Diff

58
third-party/dht/dht.h vendored
View File

@@ -1,58 +0,0 @@
/*
Copyright (c) 2009-2011 by Juliusz Chroboczek
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
typedef void
dht_callback(void *closure, int event,
const unsigned char *info_hash,
const void *data, size_t data_len);
#define DHT_EVENT_NONE 0
#define DHT_EVENT_VALUES 1
#define DHT_EVENT_VALUES6 2
#define DHT_EVENT_SEARCH_DONE 3
#define DHT_EVENT_SEARCH_DONE6 4
extern FILE *dht_debug;
int dht_init(int s, int s6, const unsigned char *id, const unsigned char *v);
int dht_insert_node(const unsigned char *id, struct sockaddr *sa, int salen);
int dht_ping_node(struct sockaddr *sa, int salen);
int dht_periodic(const void *buf, size_t buflen,
const struct sockaddr *from, int fromlen,
time_t *tosleep, dht_callback *callback, void *closure);
int dht_search(const unsigned char *id, int port, int af,
dht_callback *callback, void *closure);
int dht_nodes(int af,
int *good_return, int *dubious_return, int *cached_return,
int *incoming_return);
void dht_dump_tables(FILE *f);
int dht_get_nodes(struct sockaddr_in *sin, int *num,
struct sockaddr_in6 *sin6, int *num6);
int dht_uninit(void);
/* This must be provided by the user. */
int dht_blacklisted(const struct sockaddr *sa, int salen);
void dht_hash(void *hash_return, int hash_size,
const void *v1, int len1,
const void *v2, int len2,
const void *v3, int len3);
int dht_random_bytes(void *buf, size_t size);

View File

@@ -1,15 +0,0 @@
libb64: Base64 Encoding/Decoding Routines
======================================
Authors:
-------
Chris Venter chris.venter@gmail.com http://controlaltfire.com
Contributors:
------------
Mario Rugiero
Shlok Datye
Peter K. Lee

View File

@@ -1,33 +0,0 @@
libb64: Base64 Encoding/Decoding Routines
======================================
## Changelog ##
Version 1.2.1 Release
---------------------
Fixed a long-standing bug in src/cdecode.c where value_in was not correctly
checked against the bounds [0..decoding_size)
Thanks to both Mario Rugiero and Shlok Datye for pointing this out.
Added some simple example code to answer some of the most common misconceptions
people have about the library usage.
Version 1.2 Release
-------------------
Removed the b64dec, b64enc, encoder and decoder programs in favour of
a better example, called base64, which encodes and decodes
depending on its arguments.
Created a solution for Microsoft Visual Studio C++ Express 2010
edition, which simply builds the base64 example as a console application.
Version 1.1 Release
-------------------
Modified encode.h to (correctly) read from the iostream argument,
instead of std::cin.
Thanks to Peter K. Lee for the heads-up.
No API changes.
Version 1.0 Release
-------------------
The current content is the changeset.

View File

@@ -1,44 +0,0 @@
libb64: Base64 Encoding/Decoding Routines
======================================
Requirements:
------------
This piece of software has minimal requirements.
I have tested it on the following systems:
- a Linux machine, with the following specs:
(this was the original development machine)
* FedoraCore 4
* kernel v. 2.6.11 (stock FC4 kernel)
* gcc version 4.0.1 20050727 (Red Hat 4.0.1-5)
* glibc-2.3.5-10
* make v. 3.80
* some arb version of makedepend
- Windows XP machine
* MSYS 1.0
* MinGW 5.1.4
* gcc version 3.4.5 (mingw-vista special r3)
- Windows XP machine (same as above)
* Microsoft Visual Studio 2010, Version 10.0.30319.1 RTMRel
Barring any serious screwups on my part, this code should compile and run sweetly
under Cygwin and other systems too. If you DO get it running under some weird arch/os setup,
send me a mail, please.
Compiling:
---------
There is no configure. It would be overkill for something so simple...
Run make in the root directory.
Installing:
----------
Since the current targets are a standalone executable and a static library
(fancy name for archive) with some headers, an install script has not been implemented yet.
Simply copy the executable into your path, and use it.
--
peace out
Chris

View File

@@ -1,29 +0,0 @@
Copyright-Only Dedication (based on United States law)
or Public Domain Certification
The person or persons who have associated work with this document (the
"Dedicator" or "Certifier") hereby either (a) certifies that, to the best of
his knowledge, the work of authorship identified is in the public domain of the
country from which the work is published, or (b) hereby dedicates whatever
copyright the dedicators holds in the work of authorship identified below (the
"Work") to the public domain. A certifier, moreover, dedicates any copyright
interest he may have in the associated work, and for these purposes, is
described as a "dedicator" below.
A certifier has taken reasonable steps to verify the copyright status of this
work. Certifier recognizes that his good faith efforts may not shield him from
liability if in fact the work certified is not in the public domain.
Dedicator makes this dedication for the benefit of the public at large and to
the detriment of the Dedicator's heirs and successors. Dedicator intends this
dedication to be an overt act of relinquishment in perpetuity of all present
and future rights under copyright law, whether vested or contingent, in the
Work. Dedicator understands that such relinquishment of all rights includes
the relinquishment of all rights to enforce (by lawsuit or otherwise) those
copyrights in the Work.
Dedicator recognizes that, once placed in the public domain, the Work may be
freely reproduced, distributed, transmitted, used, modified, built upon, or
otherwise exploited by anyone for any purpose, commercial or non-commercial,
and in any way, including by methods that have not yet been invented or
conceived.

View File

@@ -1,4 +0,0 @@
noinst_LIBRARIES = libb64.a
libb64_a_SOURCES = cdecode.c cencode.c
noinst_HEADERS = b64/cdecode.h b64/cencode.h
EXTRA_DIST = AUTHORS CHANGELOG INSTALL LICENSE README

View File

@@ -1,143 +0,0 @@
b64: Base64 Encoding/Decoding Routines
======================================
Overview:
--------
libb64 is a library of ANSI C routines for fast encoding/decoding data into and
from a base64-encoded format. C++ wrappers are included, as well as the source
code for standalone encoding and decoding executables.
base64 consists of ASCII text, and is therefore a useful encoding for storing
binary data in a text file, such as xml, or sending binary data over text-only
email.
References:
----------
* Wikipedia article:
http://en.wikipedia.org/wiki/Base64
* base64, another implementation of a commandline en/decoder:
http://www.fourmilab.ch/webtools/base64/
Why?
---
I did this because I need an implementation of base64 encoding and decoding,
without any licensing problems. Most OS implementations are released under
either the GNU/GPL, or a BSD-variant, which is not what I require.
Also, the chance to actually use the co-routine implementation in code is rare,
and its use here is fitting. I couldn't pass up the chance.
For more information on this technique, see "Coroutines in C", by Simon Tatham,
which can be found online here:
http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
So then, under which license do I release this code? On to the next section...
License:
-------
This work is released under into the Public Domain.
It basically boils down to this: I put this work in the public domain, and you
can take it and do whatever you want with it.
An example of this "license" is the Creative Commons Public Domain License, a
copy of which can be found in the LICENSE file, and also online at
http://creativecommons.org/licenses/publicdomain/
Commandline Use:
---------------
There is a new executable available, it is simply called base64.
It can encode and decode files, as instructed by the user.
To encode a file:
$ ./base64 -e filea fileb
fileb will now be the base64-encoded version of filea.
To decode a file:
$ ./base64 -d fileb filec
filec will now be identical to filea.
Programming:
-----------
Some C++ wrappers are provided as well, so you don't have to get your hands
dirty. Encoding from standard input to standard output is as simple as
#include <b64/encode.h>
#include <iostream>
int main()
{
base64::encoder E;
E.encode(std::cin, std::cout);
return 0;
}
Both standalone executables and a static library is provided in the package,
Example code:
------------
The 'examples' directory contains some simple example C code, that demonstrates
how to use the C interface of the library.
Implementation:
--------------
It is DAMN fast, if I may say so myself. The C code uses a little trick which
has been used to implement coroutines, of which one can say that this
implementation is an example.
(To see how the libb64 codebase compares with some other BASE64 implementations
available, see the BENCHMARKS file)
The trick involves the fact that a switch-statement may legally cross into
sub-blocks. A very thorough and enlightening essay on co-routines in C, using
this method, can be found in the above mentioned "Coroutines in C", by Simon
Tatham: http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
For example, an RLE decompressing routine, adapted from the article:
1 static int STATE = 0;
2 static int len, c;
3 switch (STATE)
4 {
5 while (1)
6 {
7 c = getchar();
8 if (c == EOF) return EOF;
9 if (c == 0xFF) {
10 len = getchar();
11 c = getchar();
12 while (len--)
13 {
14 STATE = 0;
15 return c;
16 case 0:
17 }
18 } else
19 STATE = 1;
20 return c;
21 case 1:
22 }
23 }
24 }
As can be seen from this example, a coroutine depends on a state variable,
which it sets directly before exiting (lines 14 and 119). The next time the
routine is entered, the switch moves control to the specific point directly
after the previous exit (lines 16 and 21).hands
(As an aside, in the mentioned article the combination of the top-level switch,
the various setting of the state, the return of a value, and the labelling of
the exit point is wrapped in #define macros, making the structure of the
routine even clearer.)
The obvious problem with any such routine is the static keyword.
Any static variables in a function spell doom for multithreaded applications.
Also, in situations where this coroutine is used by more than one other
coroutines, the consistency is disturbed.
What is needed is a structure for storing these variabled, which is passed to
the routine seperately. This obviously breaks the modularity of the function,
since now the caller has to worry about and care for the internal state of the
routine (the callee). This allows for a fast, multithreading-enabled
implementation, which may (obviously) be wrapped in a C++ object for ease of
use.
The base64 encoding and decoding functionality in this package is implemented
in exactly this way, providing both a high-speed high-maintanence C interface,
and a wrapped C++ which is low-maintanence and only slightly less performant.

View File

@@ -1,29 +0,0 @@
/*
cdecode.h - c header for a base64 decoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#ifndef BASE64_CDECODE_H
#define BASE64_CDECODE_H
typedef enum
{
step_a, step_b, step_c, step_d
} base64_decodestep;
typedef struct
{
base64_decodestep step;
char plainchar;
} base64_decodestate;
void base64_init_decodestate(base64_decodestate* state_in);
int base64_decode_value(char value_in);
int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in);
#endif /* BASE64_CDECODE_H */

View File

@@ -1,32 +0,0 @@
/*
cencode.h - c header for a base64 encoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#ifndef BASE64_CENCODE_H
#define BASE64_CENCODE_H
typedef enum
{
step_A, step_B, step_C
} base64_encodestep;
typedef struct
{
base64_encodestep step;
char result;
int stepcount;
} base64_encodestate;
void base64_init_encodestate(base64_encodestate* state_in);
char base64_encode_value(char value_in);
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in);
int base64_encode_blockend(char* code_out, base64_encodestate* state_in);
#endif /* BASE64_CENCODE_H */

View File

@@ -1,88 +0,0 @@
/*
cdecoder.c - c source to a base64 decoding algorithm implementation
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#include <b64/cdecode.h>
int base64_decode_value(char value_in)
{
static const signed char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
static const char decoding_size = sizeof(decoding);
value_in -= 43;
if (value_in < 0 || value_in >= decoding_size) return -1;
return decoding[(int)value_in];
}
void base64_init_decodestate(base64_decodestate* state_in)
{
state_in->step = step_a;
state_in->plainchar = 0;
}
int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in)
{
const char* codechar = code_in;
char* plainchar = plaintext_out;
int fragment;
*plainchar = state_in->plainchar;
switch (state_in->step)
{
while (1)
{
case step_a:
do {
if (codechar == code_in+length_in)
{
state_in->step = step_a;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = base64_decode_value(*codechar++);
} while (fragment < 0);
*plainchar = (fragment & 0x03f) << 2;
case step_b:
do {
if (codechar == code_in+length_in)
{
state_in->step = step_b;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = base64_decode_value(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x030) >> 4;
*plainchar = (fragment & 0x00f) << 4;
case step_c:
do {
if (codechar == code_in+length_in)
{
state_in->step = step_c;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = base64_decode_value(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x03c) >> 2;
*plainchar = (fragment & 0x003) << 6;
case step_d:
do {
if (codechar == code_in+length_in)
{
state_in->step = step_d;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = base64_decode_value(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x03f);
}
}
/* control should not reach here */
return plainchar - plaintext_out;
}

View File

@@ -1,115 +0,0 @@
/*
cencoder.c - c source to a base64 encoding algorithm implementation
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#include <b64/cencode.h>
/*
const int CHARS_PER_LINE = 72;
*/
void base64_init_encodestate(base64_encodestate* state_in)
{
state_in->step = step_A;
state_in->result = 0;
state_in->stepcount = 0;
}
char base64_encode_value(char value_in)
{
static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (value_in > 63) return '=';
return encoding[(int)value_in];
}
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
{
const char* plainchar = plaintext_in;
const char* const plaintextend = plaintext_in + length_in;
char* codechar = code_out;
char result;
char fragment;
result = state_in->result;
switch (state_in->step)
{
while (1)
{
case step_A:
if (plainchar == plaintextend)
{
state_in->result = result;
state_in->step = step_A;
return codechar - code_out;
}
fragment = *plainchar++;
result = (fragment & 0x0fc) >> 2;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x003) << 4;
case step_B:
if (plainchar == plaintextend)
{
state_in->result = result;
state_in->step = step_B;
return codechar - code_out;
}
fragment = *plainchar++;
result |= (fragment & 0x0f0) >> 4;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x00f) << 2;
case step_C:
if (plainchar == plaintextend)
{
state_in->result = result;
state_in->step = step_C;
return codechar - code_out;
}
fragment = *plainchar++;
result |= (fragment & 0x0c0) >> 6;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x03f) >> 0;
*codechar++ = base64_encode_value(result);
/*
++(state_in->stepcount);
if (state_in->stepcount == CHARS_PER_LINE/4)
{
*codechar++ = '\n';
state_in->stepcount = 0;
}
*/
}
}
/* control should not reach here */
return codechar - code_out;
}
int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
{
char* codechar = code_out;
switch (state_in->step)
{
case step_B:
*codechar++ = base64_encode_value(state_in->result);
*codechar++ = '=';
*codechar++ = '=';
break;
case step_C:
*codechar++ = base64_encode_value(state_in->result);
*codechar++ = '=';
break;
case step_A:
break;
}
/*
*codechar++ = '\n';
*/
return codechar - code_out;
}

View File

@@ -1,86 +0,0 @@
$Id: Changelog.txt,v 1.29 2011/08/07 16:59:33 nanard Exp $
2011/08/07:
Patch to build on debian/kFreeBSD.
2011/07/15:
Put 3 clauses BSD licence at the top of source files.
2011/06/18:
--no-undefined => -Wl,--no-undefined
adding a natpmpc.1 man page
2011/05/19:
Small fix in libnatpmpmodule.c thanks to Manuel Mausz
2011/01/03:
Added an argument to initnatpmp() in order to force the gateway to be used
2011/01/01:
fix in make install
2010/05/21:
make install now working under MacOSX (and BSD)
2010/04/12:
cplusplus stuff in natpmp.h
2010/02/02:
Fixed compilation under Mac OS X
2009/12/19:
improve and fix building under Windows.
Project files for MS Visual Studio 2008
More simple (and working) code for Win32.
More checks in the /proc/net/route parsing. Add some comments.
2009/08/04:
improving getgateway.c for windows
2009/07/13:
Adding Haiku code in getgateway.c
2009/06/04:
Adding Python module thanks to David Wu
2009/03/10:
Trying to have windows get gateway working if not using DHCP
2009/02/27:
dont include declspec.h if not under WIN32.
2009/01/23:
Prefixed the libraries name with lib
2008/10/06:
Fixed a memory leak in getdefaultgateway() (USE_SYSCTL_NET_ROUTE)
2008/07/03:
Adding WIN32 code from Robbie Hanson
2008/06/30:
added a Solaris implementation for getgateway().
added a LICENCE file to the distribution
2008/05/29:
Anonymous unions are forbidden in ANSI C. That was causing problems with
non-GCC compilers.
2008/04/28:
introduced strnatpmperr()
improved natpmpc.c sample
make install now install the binary
2007/12/13:
Fixed getgateway.c for working under OS X ;)
Fixed values for NATPMP_PROTOCOL_TCP and NATPMP_PROTOCOL_UDP
2007/12/11:
Fixed getgateway.c for compilation under Mac OS X
2007/12/01:
added some comments in .h
2007/11/30:
implemented almost everything

View File

@@ -1,26 +0,0 @@
Copyright (c) 2007-2011, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,18 +0,0 @@
noinst_LIBRARIES = libnatpmp.a
AM_CFLAGS = @PTHREAD_CFLAGS@ -DENABLE_STRNATPMPERR
libnatpmp_a_SOURCES = \
getgateway.c \
natpmp.c \
wingettimeofday.c
noinst_HEADERS = \
declspec.h \
getgateway.h \
natpmp.h \
wingettimeofday.h
EXTRA_DIST = \
README \
LICENSE

View File

@@ -1,7 +0,0 @@
libnatpmp (c) 2007-2009 Thomas Bernard
contact : miniupnp@free.fr
see http://miniupnp.free.fr/libnatpmp.html
or http://miniupnp.tuxfamily.org/libnatpmp.html
for some documentation and code samples.

View File

@@ -1,15 +0,0 @@
#ifndef __DECLSPEC_H__
#define __DECLSPEC_H__
#if defined(WIN32) && !defined(STATICLIB)
#ifdef NATPMP_EXPORTS
#define LIBSPEC __declspec(dllexport)
#else
#define LIBSPEC __declspec(dllimport)
#endif
#else
#define LIBSPEC
#endif
#endif

View File

@@ -1,568 +0,0 @@
/* $Id: getgateway.c,v 1.22 2011/08/08 21:20:51 nanard Exp $ */
/* libnatpmp
Copyright (c) 2007-2011, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <ctype.h>
#ifndef WIN32
#include <netinet/in.h>
#endif
#if !defined(_MSC_VER)
#include <sys/param.h>
#endif
/* There is no portable method to get the default route gateway.
* So below are four (or five ?) differents functions implementing this.
* Parsing /proc/net/route is for linux.
* sysctl is the way to access such informations on BSD systems.
* Many systems should provide route information through raw PF_ROUTE
* sockets.
* In MS Windows, default gateway is found by looking into the registry
* or by using GetBestRoute(). */
#ifdef __linux__
#define USE_PROC_NET_ROUTE
#undef USE_SOCKET_ROUTE
#undef USE_SYSCTL_NET_ROUTE
#endif
#if defined(BSD) || defined(__FreeBSD_kernel__)
#undef USE_PROC_NET_ROUTE
#define USE_SOCKET_ROUTE
#undef USE_SYSCTL_NET_ROUTE
#endif
#ifdef __APPLE__
#undef USE_PROC_NET_ROUTE
#undef USE_SOCKET_ROUTE
#define USE_SYSCTL_NET_ROUTE
#endif
#if (defined(sun) && defined(__SVR4))
#undef USE_PROC_NET_ROUTE
#define USE_SOCKET_ROUTE
#undef USE_SYSCTL_NET_ROUTE
#endif
#ifdef WIN32
#undef USE_PROC_NET_ROUTE
#undef USE_SOCKET_ROUTE
#undef USE_SYSCTL_NET_ROUTE
//#define USE_WIN32_CODE
#define USE_WIN32_CODE_2
#endif
#ifdef __CYGWIN__
#undef USE_PROC_NET_ROUTE
#undef USE_SOCKET_ROUTE
#undef USE_SYSCTL_NET_ROUTE
#define USE_WIN32_CODE
#include <stdarg.h>
#include <w32api/windef.h>
#include <w32api/winbase.h>
#include <w32api/winreg.h>
#endif
#ifdef __HAIKU__
#include <stdlib.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/sockio.h>
#define USE_HAIKU_CODE
#endif
#ifdef USE_SYSCTL_NET_ROUTE
#include <stdlib.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <net/route.h>
#endif
#ifdef USE_SOCKET_ROUTE
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/route.h>
#endif
#ifdef USE_WIN32_CODE
#include <unknwn.h>
#include <winreg.h>
#define MAX_KEY_LENGTH 255
#define MAX_VALUE_LENGTH 16383
#endif
#ifdef USE_WIN32_CODE_2
#include <windows.h>
#include <iphlpapi.h>
#endif
#include "getgateway.h"
#ifndef WIN32
#define SUCCESS (0)
#define FAILED (-1)
#endif
#ifdef USE_PROC_NET_ROUTE
/*
parse /proc/net/route which is as follow :
Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
wlan0 0001A8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
eth0 0000FEA9 00000000 0001 0 0 0 0000FFFF 0 0 0
wlan0 00000000 0101A8C0 0003 0 0 0 00000000 0 0 0
eth0 00000000 00000000 0001 0 0 1000 00000000 0 0 0
One header line, and then one line by route by route table entry.
*/
int getdefaultgateway(in_addr_t * addr)
{
unsigned long d, g;
char buf[256];
int line = 0;
FILE * f;
char * p;
f = fopen("/proc/net/route", "r");
if(!f)
return FAILED;
while(fgets(buf, sizeof(buf), f)) {
if(line > 0) { /* skip the first line */
p = buf;
/* skip the interface name */
while(*p && !isspace(*p))
p++;
while(*p && isspace(*p))
p++;
if(sscanf(p, "%lx%lx", &d, &g)==2) {
if(d == 0 && g != 0) { /* default */
*addr = g;
fclose(f);
return SUCCESS;
}
}
}
line++;
}
/* default route not found ! */
if(f)
fclose(f);
return FAILED;
}
#endif /* #ifdef USE_PROC_NET_ROUTE */
#ifdef USE_SYSCTL_NET_ROUTE
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
int getdefaultgateway(in_addr_t * addr)
{
#if 0
/* net.route.0.inet.dump.0.0 ? */
int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET,
NET_RT_DUMP, 0, 0/*tableid*/};
#endif
/* net.route.0.inet.flags.gateway */
int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET,
NET_RT_FLAGS, RTF_GATEWAY};
size_t l;
char * buf, * p;
struct rt_msghdr * rt;
struct sockaddr * sa;
struct sockaddr * sa_tab[RTAX_MAX];
int i;
int r = FAILED;
if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) {
return FAILED;
}
if(l>0) {
buf = malloc(l);
if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) {
free(buf);
return FAILED;
}
for(p=buf; p<buf+l; p+=rt->rtm_msglen) {
rt = (struct rt_msghdr *)p;
sa = (struct sockaddr *)(rt + 1);
for(i=0; i<RTAX_MAX; i++) {
if(rt->rtm_addrs & (1 << i)) {
sa_tab[i] = sa;
sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len));
} else {
sa_tab[i] = NULL;
}
}
if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY))
&& sa_tab[RTAX_DST]->sa_family == AF_INET
&& sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) {
if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) {
*addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr;
r = SUCCESS;
}
}
}
free(buf);
}
return r;
}
#endif /* #ifdef USE_SYSCTL_NET_ROUTE */
#ifdef USE_SOCKET_ROUTE
/* Thanks to Darren Kenny for this code */
#define NEXTADDR(w, u) \
if (rtm_addrs & (w)) {\
l = sizeof(struct sockaddr); memmove(cp, &(u), l); cp += l;\
}
#define rtm m_rtmsg.m_rtm
struct {
struct rt_msghdr m_rtm;
char m_space[512];
} m_rtmsg;
int getdefaultgateway(in_addr_t *addr)
{
int s, seq, l, rtm_addrs, i;
pid_t pid;
struct sockaddr so_dst, so_mask;
char *cp = m_rtmsg.m_space;
struct sockaddr *gate = NULL, *sa;
struct rt_msghdr *msg_hdr;
pid = getpid();
seq = 0;
rtm_addrs = RTA_DST | RTA_NETMASK;
memset(&so_dst, 0, sizeof(so_dst));
memset(&so_mask, 0, sizeof(so_mask));
memset(&rtm, 0, sizeof(struct rt_msghdr));
rtm.rtm_type = RTM_GET;
rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
rtm.rtm_version = RTM_VERSION;
rtm.rtm_seq = ++seq;
rtm.rtm_addrs = rtm_addrs;
so_dst.sa_family = AF_INET;
so_mask.sa_family = AF_INET;
NEXTADDR(RTA_DST, so_dst);
NEXTADDR(RTA_NETMASK, so_mask);
rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
s = socket(PF_ROUTE, SOCK_RAW, 0);
if (write(s, (char *)&m_rtmsg, l) < 0) {
close(s);
return FAILED;
}
do {
l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
} while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
close(s);
msg_hdr = &rtm;
cp = ((char *)(msg_hdr + 1));
if (msg_hdr->rtm_addrs) {
for (i = 1; i; i <<= 1)
if (i & msg_hdr->rtm_addrs) {
sa = (struct sockaddr *)cp;
if (i == RTA_GATEWAY )
gate = sa;
cp += sizeof(struct sockaddr);
}
} else {
return FAILED;
}
if (gate != NULL ) {
*addr = ((struct sockaddr_in *)gate)->sin_addr.s_addr;
return SUCCESS;
} else {
return FAILED;
}
}
#endif /* #ifdef USE_SOCKET_ROUTE */
#ifdef USE_WIN32_CODE
LIBSPEC int getdefaultgateway(in_addr_t * addr)
{
HKEY networkCardsKey;
HKEY networkCardKey;
HKEY interfacesKey;
HKEY interfaceKey;
DWORD i = 0;
DWORD numSubKeys = 0;
TCHAR keyName[MAX_KEY_LENGTH];
DWORD keyNameLength = MAX_KEY_LENGTH;
TCHAR keyValue[MAX_VALUE_LENGTH];
DWORD keyValueLength = MAX_VALUE_LENGTH;
DWORD keyValueType = REG_SZ;
TCHAR gatewayValue[MAX_VALUE_LENGTH];
DWORD gatewayValueLength = MAX_VALUE_LENGTH;
DWORD gatewayValueType = REG_MULTI_SZ;
int done = 0;
//const char * networkCardsPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
//const char * interfacesPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
#ifdef UNICODE
LPCTSTR networkCardsPath = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
LPCTSTR interfacesPath = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
#define STR_SERVICENAME L"ServiceName"
#define STR_DHCPDEFAULTGATEWAY L"DhcpDefaultGateway"
#define STR_DEFAULTGATEWAY L"DefaultGateway"
#else
LPCTSTR networkCardsPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
LPCTSTR interfacesPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
#define STR_SERVICENAME "ServiceName"
#define STR_DHCPDEFAULTGATEWAY "DhcpDefaultGateway"
#define STR_DEFAULTGATEWAY "DefaultGateway"
#endif
// The windows registry lists its primary network devices in the following location:
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards
//
// Each network device has its own subfolder, named with an index, with various properties:
// -NetworkCards
// -5
// -Description = Broadcom 802.11n Network Adapter
// -ServiceName = {E35A72F8-5065-4097-8DFE-C7790774EE4D}
// -8
// -Description = Marvell Yukon 88E8058 PCI-E Gigabit Ethernet Controller
// -ServiceName = {86226414-5545-4335-A9D1-5BD7120119AD}
//
// The above service name is the name of a subfolder within:
// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces
//
// There may be more subfolders in this interfaces path than listed in the network cards path above:
// -Interfaces
// -{3a539854-6a70-11db-887c-806e6f6e6963}
// -DhcpIPAddress = 0.0.0.0
// -[more]
// -{E35A72F8-5065-4097-8DFE-C7790774EE4D}
// -DhcpIPAddress = 10.0.1.4
// -DhcpDefaultGateway = 10.0.1.1
// -[more]
// -{86226414-5545-4335-A9D1-5BD7120119AD}
// -DhcpIpAddress = 10.0.1.5
// -DhcpDefaultGateay = 10.0.1.1
// -[more]
//
// In order to extract this information, we enumerate each network card, and extract the ServiceName value.
// This is then used to open the interface subfolder, and attempt to extract a DhcpDefaultGateway value.
// Once one is found, we're done.
//
// It may be possible to simply enumerate the interface folders until we find one with a DhcpDefaultGateway value.
// However, the technique used is the technique most cited on the web, and we assume it to be more correct.
if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predifined key
networkCardsPath, // Name of registry subkey to open
0, // Reserved - must be zero
KEY_READ, // Mask - desired access rights
&networkCardsKey)) // Pointer to output key
{
// Unable to open network cards keys
return -1;
}
if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predefined key
interfacesPath, // Name of registry subkey to open
0, // Reserved - must be zero
KEY_READ, // Mask - desired access rights
&interfacesKey)) // Pointer to output key
{
// Unable to open interfaces key
RegCloseKey(networkCardsKey);
return -1;
}
// Figure out how many subfolders are within the NetworkCards folder
RegQueryInfoKey(networkCardsKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
//printf( "Number of subkeys: %u\n", (unsigned int)numSubKeys);
// Enumrate through each subfolder within the NetworkCards folder
for(i = 0; i < numSubKeys && !done; i++)
{
keyNameLength = MAX_KEY_LENGTH;
if(ERROR_SUCCESS == RegEnumKeyEx(networkCardsKey, // Open registry key
i, // Index of subkey to retrieve
keyName, // Buffer that receives the name of the subkey
&keyNameLength, // Variable that receives the size of the above buffer
NULL, // Reserved - must be NULL
NULL, // Buffer that receives the class string
NULL, // Variable that receives the size of the above buffer
NULL)) // Variable that receives the last write time of subkey
{
if(RegOpenKeyEx(networkCardsKey, keyName, 0, KEY_READ, &networkCardKey) == ERROR_SUCCESS)
{
keyValueLength = MAX_VALUE_LENGTH;
if(ERROR_SUCCESS == RegQueryValueEx(networkCardKey, // Open registry key
STR_SERVICENAME, // Name of key to query
NULL, // Reserved - must be NULL
&keyValueType, // Receives value type
(LPBYTE)keyValue, // Receives value
&keyValueLength)) // Receives value length in bytes
{
// printf("keyValue: %s\n", keyValue);
if(RegOpenKeyEx(interfacesKey, keyValue, 0, KEY_READ, &interfaceKey) == ERROR_SUCCESS)
{
gatewayValueLength = MAX_VALUE_LENGTH;
if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key
STR_DHCPDEFAULTGATEWAY, // Name of key to query
NULL, // Reserved - must be NULL
&gatewayValueType, // Receives value type
(LPBYTE)gatewayValue, // Receives value
&gatewayValueLength)) // Receives value length in bytes
{
// Check to make sure it's a string
if((gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ) && (gatewayValueLength > 1))
{
//printf("gatewayValue: %s\n", gatewayValue);
done = 1;
}
}
else if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key
STR_DEFAULTGATEWAY, // Name of key to query
NULL, // Reserved - must be NULL
&gatewayValueType, // Receives value type
(LPBYTE)gatewayValue,// Receives value
&gatewayValueLength)) // Receives value length in bytes
{
// Check to make sure it's a string
if((gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ) && (gatewayValueLength > 1))
{
//printf("gatewayValue: %s\n", gatewayValue);
done = 1;
}
}
RegCloseKey(interfaceKey);
}
}
RegCloseKey(networkCardKey);
}
}
}
RegCloseKey(interfacesKey);
RegCloseKey(networkCardsKey);
if(done)
{
#if UNICODE
char tmp[32];
for(i = 0; i < 32; i++) {
tmp[i] = (char)gatewayValue[i];
if(!tmp[i])
break;
}
tmp[31] = '\0';
*addr = inet_addr(tmp);
#else
*addr = inet_addr(gatewayValue);
#endif
return 0;
}
return -1;
}
#endif /* #ifdef USE_WIN32_CODE */
#ifdef USE_WIN32_CODE_2
int getdefaultgateway(in_addr_t *addr)
{
MIB_IPFORWARDROW ip_forward;
memset(&ip_forward, 0, sizeof(ip_forward));
if(GetBestRoute(inet_addr("0.0.0.0"), 0, &ip_forward) != NO_ERROR)
return -1;
*addr = ip_forward.dwForwardNextHop;
return 0;
}
#endif /* #ifdef USE_WIN32_CODE_2 */
#ifdef USE_HAIKU_CODE
int getdefaultgateway(in_addr_t *addr)
{
int fd, ret = -1;
struct ifconf config;
void *buffer = NULL;
struct ifreq *interface;
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
return -1;
}
if (ioctl(fd, SIOCGRTSIZE, &config, sizeof(config)) != 0) {
goto fail;
}
if (config.ifc_value < 1) {
goto fail; /* No routes */
}
if ((buffer = malloc(config.ifc_value)) == NULL) {
goto fail;
}
config.ifc_len = config.ifc_value;
config.ifc_buf = buffer;
if (ioctl(fd, SIOCGRTTABLE, &config, sizeof(config)) != 0) {
goto fail;
}
for (interface = buffer;
(uint8_t *)interface < (uint8_t *)buffer + config.ifc_len; ) {
struct route_entry route = interface->ifr_route;
int intfSize;
if (route.flags & (RTF_GATEWAY | RTF_DEFAULT)) {
*addr = ((struct sockaddr_in *)route.gateway)->sin_addr.s_addr;
ret = 0;
break;
}
intfSize = sizeof(route) + IF_NAMESIZE;
if (route.destination != NULL) {
intfSize += route.destination->sa_len;
}
if (route.mask != NULL) {
intfSize += route.mask->sa_len;
}
if (route.gateway != NULL) {
intfSize += route.gateway->sa_len;
}
interface = (struct ifreq *)((uint8_t *)interface + intfSize);
}
fail:
free(buffer);
close(fd);
return ret;
}
#endif /* #ifdef USE_HAIKU_CODE */

View File

@@ -1,49 +0,0 @@
/* $Id: getgateway.h,v 1.5 2011/07/15 08:30:11 nanard Exp $ */
/* libnatpmp
Copyright (c) 2007-2011, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GETGATEWAY_H__
#define __GETGATEWAY_H__
#ifdef WIN32
#if !defined(_MSC_VER)
#include <stdint.h>
#else
typedef unsigned long uint32_t;
typedef unsigned short uint16_t;
#endif
#define in_addr_t uint32_t
#endif
#include "declspec.h"
/* getdefaultgateway() :
* return value :
* 0 : success
* -1 : failure */
LIBSPEC int getdefaultgateway(in_addr_t * addr);
#endif

View File

@@ -1,362 +0,0 @@
/* $Id: natpmp.c,v 1.14 2011/07/15 08:30:11 nanard Exp $ */
/* libnatpmp
Copyright (c) 2007-2011, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef __linux__
#define _BSD_SOURCE 1
#endif
#include <string.h>
#include <time.h>
#if !defined(_MSC_VER)
#include <sys/time.h>
#endif
#ifdef WIN32
#include <errno.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#define EWOULDBLOCK WSAEWOULDBLOCK
#define ECONNREFUSED WSAECONNREFUSED
#include "wingettimeofday.h"
#else
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#define closesocket close
#endif
#include "natpmp.h"
#include "getgateway.h"
LIBSPEC int initnatpmp(natpmp_t * p, int forcegw, in_addr_t forcedgw)
{
#ifdef WIN32
u_long ioctlArg = 1;
#else
int flags;
#endif
struct sockaddr_in addr;
if(!p)
return NATPMP_ERR_INVALIDARGS;
memset(p, 0, sizeof(natpmp_t));
p->s = socket(PF_INET, SOCK_DGRAM, 0);
if(p->s < 0)
return NATPMP_ERR_SOCKETERROR;
#ifdef WIN32
if(ioctlsocket(p->s, FIONBIO, &ioctlArg) == SOCKET_ERROR)
return NATPMP_ERR_FCNTLERROR;
#else
if((flags = fcntl(p->s, F_GETFL, 0)) < 0)
return NATPMP_ERR_FCNTLERROR;
if(fcntl(p->s, F_SETFL, flags | O_NONBLOCK) < 0)
return NATPMP_ERR_FCNTLERROR;
#endif
if(forcegw) {
p->gateway = forcedgw;
} else {
if(getdefaultgateway(&(p->gateway)) < 0)
return NATPMP_ERR_CANNOTGETGATEWAY;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(NATPMP_PORT);
addr.sin_addr.s_addr = p->gateway;
if(connect(p->s, (struct sockaddr *)&addr, sizeof(addr)) < 0)
return NATPMP_ERR_CONNECTERR;
return 0;
}
LIBSPEC int closenatpmp(natpmp_t * p)
{
if(!p)
return NATPMP_ERR_INVALIDARGS;
if(closesocket(p->s) < 0)
return NATPMP_ERR_CLOSEERR;
return 0;
}
int sendpendingrequest(natpmp_t * p)
{
int r;
/* struct sockaddr_in addr;*/
if(!p)
return NATPMP_ERR_INVALIDARGS;
/* memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(NATPMP_PORT);
addr.sin_addr.s_addr = p->gateway;
r = (int)sendto(p->s, p->pending_request, p->pending_request_len, 0,
(struct sockaddr *)&addr, sizeof(addr));*/
r = (int)send(p->s, p->pending_request, p->pending_request_len, 0);
return (r<0) ? NATPMP_ERR_SENDERR : r;
}
int sendnatpmprequest(natpmp_t * p)
{
int n;
if(!p)
return NATPMP_ERR_INVALIDARGS;
/* TODO : check if no request is allready pending */
p->has_pending_request = 1;
p->try_number = 1;
n = sendpendingrequest(p);
gettimeofday(&p->retry_time, NULL); // check errors !
p->retry_time.tv_usec += 250000; /* add 250ms */
if(p->retry_time.tv_usec >= 1000000) {
p->retry_time.tv_usec -= 1000000;
p->retry_time.tv_sec++;
}
return n;
}
LIBSPEC int getnatpmprequesttimeout(natpmp_t * p, struct timeval * timeout)
{
struct timeval now;
if(!p || !timeout)
return NATPMP_ERR_INVALIDARGS;
if(!p->has_pending_request)
return NATPMP_ERR_NOPENDINGREQ;
if(gettimeofday(&now, NULL) < 0)
return NATPMP_ERR_GETTIMEOFDAYERR;
timeout->tv_sec = p->retry_time.tv_sec - now.tv_sec;
timeout->tv_usec = p->retry_time.tv_usec - now.tv_usec;
if(timeout->tv_usec < 0) {
timeout->tv_usec += 1000000;
timeout->tv_sec--;
}
return 0;
}
LIBSPEC int sendpublicaddressrequest(natpmp_t * p)
{
if(!p)
return NATPMP_ERR_INVALIDARGS;
//static const unsigned char request[] = { 0, 0 };
p->pending_request[0] = 0;
p->pending_request[1] = 0;
p->pending_request_len = 2;
// TODO: return 0 instead of sizeof(request) ??
return sendnatpmprequest(p);
}
LIBSPEC int sendnewportmappingrequest(natpmp_t * p, int protocol,
uint16_t privateport, uint16_t publicport,
uint32_t lifetime)
{
if(!p || (protocol!=NATPMP_PROTOCOL_TCP && protocol!=NATPMP_PROTOCOL_UDP))
return NATPMP_ERR_INVALIDARGS;
p->pending_request[0] = 0;
p->pending_request[1] = protocol;
p->pending_request[2] = 0;
p->pending_request[3] = 0;
*((uint16_t *)(p->pending_request + 4)) = htons(privateport);
*((uint16_t *)(p->pending_request + 6)) = htons(publicport);
*((uint32_t *)(p->pending_request + 8)) = htonl(lifetime);
p->pending_request_len = 12;
return sendnatpmprequest(p);
}
LIBSPEC int readnatpmpresponse(natpmp_t * p, natpmpresp_t * response)
{
unsigned char buf[16];
struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
int n;
if(!p)
return NATPMP_ERR_INVALIDARGS;
n = recvfrom(p->s, buf, sizeof(buf), 0,
(struct sockaddr *)&addr, &addrlen);
if(n<0)
switch(errno) {
/*case EAGAIN:*/
case EWOULDBLOCK:
n = NATPMP_TRYAGAIN;
break;
case ECONNREFUSED:
n = NATPMP_ERR_NOGATEWAYSUPPORT;
break;
default:
n = NATPMP_ERR_RECVFROM;
}
/* check that addr is correct (= gateway) */
else if(addr.sin_addr.s_addr != p->gateway)
n = NATPMP_ERR_WRONGPACKETSOURCE;
else {
response->resultcode = ntohs(*((uint16_t *)(buf + 2)));
response->epoch = ntohl(*((uint32_t *)(buf + 4)));
if(buf[0] != 0)
n = NATPMP_ERR_UNSUPPORTEDVERSION;
else if(buf[1] < 128 || buf[1] > 130)
n = NATPMP_ERR_UNSUPPORTEDOPCODE;
else if(response->resultcode != 0) {
switch(response->resultcode) {
case 1:
n = NATPMP_ERR_UNSUPPORTEDVERSION;
break;
case 2:
n = NATPMP_ERR_NOTAUTHORIZED;
break;
case 3:
n = NATPMP_ERR_NETWORKFAILURE;
break;
case 4:
n = NATPMP_ERR_OUTOFRESOURCES;
break;
case 5:
n = NATPMP_ERR_UNSUPPORTEDOPCODE;
break;
default:
n = NATPMP_ERR_UNDEFINEDERROR;
}
} else {
response->type = buf[1] & 0x7f;
if(buf[1] == 128)
//response->publicaddress.addr = *((uint32_t *)(buf + 8));
response->pnu.publicaddress.addr.s_addr = *((uint32_t *)(buf + 8));
else {
response->pnu.newportmapping.privateport = ntohs(*((uint16_t *)(buf + 8)));
response->pnu.newportmapping.mappedpublicport = ntohs(*((uint16_t *)(buf + 10)));
response->pnu.newportmapping.lifetime = ntohl(*((uint32_t *)(buf + 12)));
}
n = 0;
}
}
return n;
}
int readnatpmpresponseorretry(natpmp_t * p, natpmpresp_t * response)
{
int n;
if(!p || !response)
return NATPMP_ERR_INVALIDARGS;
if(!p->has_pending_request)
return NATPMP_ERR_NOPENDINGREQ;
n = readnatpmpresponse(p, response);
if(n<0) {
if(n==NATPMP_TRYAGAIN) {
struct timeval now;
gettimeofday(&now, NULL); // check errors !
if(timercmp(&now, &p->retry_time, >=)) {
int delay, r;
if(p->try_number >= 9) {
return NATPMP_ERR_NOGATEWAYSUPPORT;
}
/*printf("retry! %d\n", p->try_number);*/
delay = 250 * (1<<p->try_number); // ms
/*for(i=0; i<p->try_number; i++)
delay += delay;*/
p->retry_time.tv_sec += (delay / 1000);
p->retry_time.tv_usec += (delay % 1000) * 1000;
if(p->retry_time.tv_usec >= 1000000) {
p->retry_time.tv_usec -= 1000000;
p->retry_time.tv_sec++;
}
p->try_number++;
r = sendpendingrequest(p);
if(r<0)
return r;
}
}
} else {
p->has_pending_request = 0;
}
return n;
}
#ifdef ENABLE_STRNATPMPERR
LIBSPEC const char * strnatpmperr(int r)
{
const char * s;
switch(r) {
case NATPMP_ERR_INVALIDARGS:
s = "invalid arguments";
break;
case NATPMP_ERR_SOCKETERROR:
s = "socket() failed";
break;
case NATPMP_ERR_CANNOTGETGATEWAY:
s = "cannot get default gateway ip address";
break;
case NATPMP_ERR_CLOSEERR:
#ifdef WIN32
s = "closesocket() failed";
#else
s = "close() failed";
#endif
break;
case NATPMP_ERR_RECVFROM:
s = "recvfrom() failed";
break;
case NATPMP_ERR_NOPENDINGREQ:
s = "no pending request";
break;
case NATPMP_ERR_NOGATEWAYSUPPORT:
s = "the gateway does not support nat-pmp";
break;
case NATPMP_ERR_CONNECTERR:
s = "connect() failed";
break;
case NATPMP_ERR_WRONGPACKETSOURCE:
s = "packet not received from the default gateway";
break;
case NATPMP_ERR_SENDERR:
s = "send() failed";
break;
case NATPMP_ERR_FCNTLERROR:
s = "fcntl() failed";
break;
case NATPMP_ERR_GETTIMEOFDAYERR:
s = "gettimeofday() failed";
break;
case NATPMP_ERR_UNSUPPORTEDVERSION:
s = "unsupported nat-pmp version error from server";
break;
case NATPMP_ERR_UNSUPPORTEDOPCODE:
s = "unsupported nat-pmp opcode error from server";
break;
case NATPMP_ERR_UNDEFINEDERROR:
s = "undefined nat-pmp server error";
break;
case NATPMP_ERR_NOTAUTHORIZED:
s = "not authorized";
break;
case NATPMP_ERR_NETWORKFAILURE:
s = "network failure";
break;
case NATPMP_ERR_OUTOFRESOURCES:
s = "nat-pmp server out of resources";
break;
default:
s = "Unknown libnatpmp error";
}
return s;
}
#endif

View File

@@ -1,215 +0,0 @@
/* $Id: natpmp.h,v 1.15 2011/07/15 08:30:11 nanard Exp $ */
/* libnatpmp
Copyright (c) 2007-2011, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __NATPMP_H__
#define __NATPMP_H__
/* NAT-PMP Port as defined by the NAT-PMP draft */
#define NATPMP_PORT (5351)
#include <time.h>
#if !defined(_MSC_VER)
#include <sys/time.h>
#endif
#ifdef WIN32
#include <winsock2.h>
#if !defined(_MSC_VER)
#include <stdint.h>
#else
typedef unsigned long uint32_t;
typedef unsigned short uint16_t;
#endif
#define in_addr_t uint32_t
#include "declspec.h"
#else
#define LIBSPEC
#include <netinet/in.h>
#endif
typedef struct {
int s; /* socket */
in_addr_t gateway; /* default gateway (IPv4) */
int has_pending_request;
unsigned char pending_request[12];
int pending_request_len;
int try_number;
struct timeval retry_time;
} natpmp_t;
typedef struct {
uint16_t type; /* NATPMP_RESPTYPE_* */
uint16_t resultcode; /* NAT-PMP response code */
uint32_t epoch; /* Seconds since start of epoch */
union {
struct {
//in_addr_t addr;
struct in_addr addr;
} publicaddress;
struct {
uint16_t privateport;
uint16_t mappedpublicport;
uint32_t lifetime;
} newportmapping;
} pnu;
} natpmpresp_t;
/* possible values for type field of natpmpresp_t */
#define NATPMP_RESPTYPE_PUBLICADDRESS (0)
#define NATPMP_RESPTYPE_UDPPORTMAPPING (1)
#define NATPMP_RESPTYPE_TCPPORTMAPPING (2)
/* Values to pass to sendnewportmappingrequest() */
#define NATPMP_PROTOCOL_UDP (1)
#define NATPMP_PROTOCOL_TCP (2)
/* return values */
/* NATPMP_ERR_INVALIDARGS : invalid arguments passed to the function */
#define NATPMP_ERR_INVALIDARGS (-1)
/* NATPMP_ERR_SOCKETERROR : socket() failed. check errno for details */
#define NATPMP_ERR_SOCKETERROR (-2)
/* NATPMP_ERR_CANNOTGETGATEWAY : can't get default gateway IP */
#define NATPMP_ERR_CANNOTGETGATEWAY (-3)
/* NATPMP_ERR_CLOSEERR : close() failed. check errno for details */
#define NATPMP_ERR_CLOSEERR (-4)
/* NATPMP_ERR_RECVFROM : recvfrom() failed. check errno for details */
#define NATPMP_ERR_RECVFROM (-5)
/* NATPMP_ERR_NOPENDINGREQ : readnatpmpresponseorretry() called while
* no NAT-PMP request was pending */
#define NATPMP_ERR_NOPENDINGREQ (-6)
/* NATPMP_ERR_NOGATEWAYSUPPORT : the gateway does not support NAT-PMP */
#define NATPMP_ERR_NOGATEWAYSUPPORT (-7)
/* NATPMP_ERR_CONNECTERR : connect() failed. check errno for details */
#define NATPMP_ERR_CONNECTERR (-8)
/* NATPMP_ERR_WRONGPACKETSOURCE : packet not received from the network gateway */
#define NATPMP_ERR_WRONGPACKETSOURCE (-9)
/* NATPMP_ERR_SENDERR : send() failed. check errno for details */
#define NATPMP_ERR_SENDERR (-10)
/* NATPMP_ERR_FCNTLERROR : fcntl() failed. check errno for details */
#define NATPMP_ERR_FCNTLERROR (-11)
/* NATPMP_ERR_GETTIMEOFDAYERR : gettimeofday() failed. check errno for details */
#define NATPMP_ERR_GETTIMEOFDAYERR (-12)
/* */
#define NATPMP_ERR_UNSUPPORTEDVERSION (-14)
#define NATPMP_ERR_UNSUPPORTEDOPCODE (-15)
/* Errors from the server : */
#define NATPMP_ERR_UNDEFINEDERROR (-49)
#define NATPMP_ERR_NOTAUTHORIZED (-51)
#define NATPMP_ERR_NETWORKFAILURE (-52)
#define NATPMP_ERR_OUTOFRESOURCES (-53)
/* NATPMP_TRYAGAIN : no data available for the moment. try again later */
#define NATPMP_TRYAGAIN (-100)
#ifdef __cplusplus
extern "C" {
#endif
/* initnatpmp()
* initialize a natpmp_t object
* With forcegw=1 the gateway is not detected automaticaly.
* Return values :
* 0 = OK
* NATPMP_ERR_INVALIDARGS
* NATPMP_ERR_SOCKETERROR
* NATPMP_ERR_FCNTLERROR
* NATPMP_ERR_CANNOTGETGATEWAY
* NATPMP_ERR_CONNECTERR */
LIBSPEC int initnatpmp(natpmp_t * p, int forcegw, in_addr_t forcedgw);
/* closenatpmp()
* close resources associated with a natpmp_t object
* Return values :
* 0 = OK
* NATPMP_ERR_INVALIDARGS
* NATPMP_ERR_CLOSEERR */
LIBSPEC int closenatpmp(natpmp_t * p);
/* sendpublicaddressrequest()
* send a public address NAT-PMP request to the network gateway
* Return values :
* 2 = OK (size of the request)
* NATPMP_ERR_INVALIDARGS
* NATPMP_ERR_SENDERR */
LIBSPEC int sendpublicaddressrequest(natpmp_t * p);
/* sendnewportmappingrequest()
* send a new port mapping NAT-PMP request to the network gateway
* Arguments :
* protocol is either NATPMP_PROTOCOL_TCP or NATPMP_PROTOCOL_UDP,
* lifetime is in seconds.
* To remove a port mapping, set lifetime to zero.
* To remove all port mappings to the host, set lifetime and both ports
* to zero.
* Return values :
* 12 = OK (size of the request)
* NATPMP_ERR_INVALIDARGS
* NATPMP_ERR_SENDERR */
LIBSPEC int sendnewportmappingrequest(natpmp_t * p, int protocol,
uint16_t privateport, uint16_t publicport,
uint32_t lifetime);
/* getnatpmprequesttimeout()
* fills the timeval structure with the timeout duration of the
* currently pending NAT-PMP request.
* Return values :
* 0 = OK
* NATPMP_ERR_INVALIDARGS
* NATPMP_ERR_GETTIMEOFDAYERR
* NATPMP_ERR_NOPENDINGREQ */
LIBSPEC int getnatpmprequesttimeout(natpmp_t * p, struct timeval * timeout);
/* readnatpmpresponseorretry()
* fills the natpmpresp_t structure if possible
* Return values :
* 0 = OK
* NATPMP_TRYAGAIN
* NATPMP_ERR_INVALIDARGS
* NATPMP_ERR_NOPENDINGREQ
* NATPMP_ERR_NOGATEWAYSUPPORT
* NATPMP_ERR_RECVFROM
* NATPMP_ERR_WRONGPACKETSOURCE
* NATPMP_ERR_UNSUPPORTEDVERSION
* NATPMP_ERR_UNSUPPORTEDOPCODE
* NATPMP_ERR_NOTAUTHORIZED
* NATPMP_ERR_NETWORKFAILURE
* NATPMP_ERR_OUTOFRESOURCES
* NATPMP_ERR_UNSUPPORTEDOPCODE
* NATPMP_ERR_UNDEFINEDERROR */
LIBSPEC int readnatpmpresponseorretry(natpmp_t * p, natpmpresp_t * response);
#ifdef ENABLE_STRNATPMPERR
LIBSPEC const char * strnatpmperr(int t);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,60 +0,0 @@
/* $Id: wingettimeofday.c,v 1.4 2011/07/15 08:30:11 nanard Exp $ */
/* libnatpmp
Copyright (c) 2007-2011, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef WIN32
#if defined(_MSC_VER)
struct timeval {
long tv_sec;
long tv_usec;
};
#else
#include <sys/time.h>
#endif
typedef struct _FILETIME {
unsigned long dwLowDateTime;
unsigned long dwHighDateTime;
} FILETIME;
void __stdcall GetSystemTimeAsFileTime(FILETIME*);
int gettimeofday(struct timeval* p, void* tz /* IGNORED */) {
union {
long long ns100; /*time since 1 Jan 1601 in 100ns units */
FILETIME ft;
} _now;
if(!p)
return -1;
GetSystemTimeAsFileTime( &(_now.ft) );
p->tv_usec =(long)((_now.ns100 / 10LL) % 1000000LL );
p->tv_sec = (long)((_now.ns100-(116444736000000000LL))/10000000LL);
return 0;
}
#endif

View File

@@ -1,39 +0,0 @@
/* $Id: wingettimeofday.h,v 1.2 2011/07/15 08:30:11 nanard Exp $ */
/* libnatpmp
Copyright (c) 2007-2011, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __WINGETTIMEOFDAY_H__
#define __WINGETTIMEOFDAY_H__
#ifdef WIN32
#if defined(_MSC_VER)
#include <time.h>
#else
#include <sys/time.h>
#endif
int gettimeofday(struct timeval* p, void* tz /* IGNORED */);
#endif
#endif

View File

@@ -1,19 +0,0 @@
Copyright (c) 2010 BitTorrent, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1,6 +0,0 @@
AM_CPPFLAGS = -fno-exceptions -fno-rtti -ansi -DPOSIX
noinst_LIBRARIES = libutp.a
libutp_a_SOURCES = utp.cpp utp_utils.cpp
noinst_HEADERS = StdAfx.h templates.h utp_config_example.h utp.h utp_config.h utp_utils.h utypes.h
EXTRA_DIST = LICENSE README.md

View File

@@ -1,66 +0,0 @@
# libutp - The uTorrent Transport Protocol library.
Copyright (c) 2010 BitTorrent, Inc.
uTP is a TCP-like implementation of [LEDBAT][ledbat] documented as a BitTorrent
extension in [BEP-29][bep29]. uTP provides provides reliable, ordered delivery
while maintaining minimum extra delay. It is implemented on top of UDP to be
cross-platform and functional today. As a result, uTP is the primary transport
for uTorrent peer-to-peer connections.
uTP is written in C++, but the external interface is strictly C (ANSI C89).
## The Interface
The uTP socket interface is a bit different from the Berkeley socket API to
avoid the need for our own select() implementation, and to make it easier to
write event-based code with minimal buffering.
When you create a uTP socket, you register a set of callbacks. Most notably, the
on_read callback is a reactive callback which occurs when bytes arrive off the
network. The write side of the socket is proactive, and you call UTP_Write to
indicate the number of bytes you wish to write. As packets are created, the
on_write callback is called for each packet, so you can fill the buffers with
data.
The libutp interface is not thread-safe. It was designed for use in a
single-threaded asyncronous context, although with proper synchronization
it may be used from a multi-threaded environment as well.
See utp.h for more details and other API documentation.
## Examples
See the utp_test and utp_file directories for examples.
## Building
uTP has been known to build on Windows with MSVC and on linux and OS X with gcc.
On Windows, use the MSVC project files (utp.sln, and friends). On other platforms,
building the shared library is as simple as:
make
To build one of the examples, which will statically link in everything it needs
from libutp:
cd utp_test && make
## Packaging and API
The libutp API is considered unstable, and probably always will be. We encourage
you to test with the version of libutp you have, and be mindful when upgrading.
For this reason, it is probably also a good idea to bundle libutp with your
application.
## License
libutp is released under the [MIT][lic] license.
## Related Work
Research and analysis of congestion control mechanisms can be found [here.][survey]
[ledbat]: http://datatracker.ietf.org/wg/ledbat/charter/
[bep29]: http://www.bittorrent.org/beps/bep_0029.html
[lic]: http://www.opensource.org/licenses/mit-license.php
[survey]: http://datatracker.ietf.org/doc/draft-ietf-ledbat-survey/

View File

@@ -1,11 +0,0 @@
#if !defined(AFX_STDAFX_H__C1470942_E9DA_4913_BEF1_9BA7584E595B__INCLUDED_)
#define AFX_STDAFX_H__C1470942_E9DA_4913_BEF1_9BA7584E595B__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// I don't have anything to put here, but some projects use precompiled headers,
// so I include StdAfx.h anyway, so they don't have to edit the files to compile normally.
#endif // !defined(AFX_STDAFX_H__C1470942_E9DA_4913_BEF1_9BA7584E595B__INCLUDED_)

View File

@@ -1,186 +0,0 @@
#ifndef __TEMPLATES_H__
#define __TEMPLATES_H__
#include "utypes.h"
#include <assert.h>
#if defined(POSIX)
/* Allow over-writing FORCEINLINE from makefile because gcc 3.4.4 for buffalo
doesn't seem to support __attribute__((always_inline)) in -O0 build
(strangely, it works in -Os build) */
#ifndef FORCEINLINE
// The always_inline attribute asks gcc to inline the function even if no optimization is being requested.
// This macro should be used exclusive-or with the inline directive (use one or the other but not both)
// since Microsoft uses __forceinline to also mean inline,
// and this code is following a Microsoft compatibility model.
// Just setting the attribute without also specifying the inline directive apparently won't inline the function,
// as evidenced by multiply-defined symbols found at link time.
#define FORCEINLINE inline __attribute__((always_inline))
#endif
#endif
#ifdef __GNUC__
// Used for gcc tool chains accepting but not supporting pragma pack
// See http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html
#define PACKED_ATTRIBUTE __attribute__((__packed__))
#else
#define PACKED_ATTRIBUTE
#endif
#ifdef __GNUC__
#define ALIGNED_ATTRIBUTE(x) __attribute__((aligned (x)))
#else
#define ALIGNED_ATTRIBUTE(x)
#endif
// Utility templates
#undef min
#undef max
template <typename T> static inline T min(T a, T b) { if (a < b) return a; return b; }
template <typename T> static inline T max(T a, T b) { if (a > b) return a; return b; }
template <typename T> static inline T min(T a, T b, T c) { return min(min(a,b),c); }
template <typename T> static inline T max(T a, T b, T c) { return max(max(a,b),c); }
template <typename T> static inline T clamp(T v, T mi, T ma)
{
if (v > ma) v = ma;
if (v < mi) v = mi;
return v;
}
#if (defined(__SVR4) && defined(__sun))
#pragma pack(1)
#else
#pragma pack(push,1)
#endif
namespace aux
{
FORCEINLINE uint16 host_to_network(uint16 i) { return htons(i); }
FORCEINLINE uint32 host_to_network(uint32 i) { return htonl(i); }
FORCEINLINE int32 host_to_network(int32 i) { return htonl(i); }
FORCEINLINE uint16 network_to_host(uint16 i) { return ntohs(i); }
FORCEINLINE uint32 network_to_host(uint32 i) { return ntohl(i); }
FORCEINLINE int32 network_to_host(int32 i) { return ntohl(i); }
}
template <class T>
struct PACKED_ATTRIBUTE big_endian
{
T operator=(T i) { m_integer = aux::host_to_network(i); return i; }
operator T() const { return aux::network_to_host(m_integer); }
private:
T m_integer;
};
typedef big_endian<int32> int32_big;
typedef big_endian<uint32> uint32_big;
typedef big_endian<uint16> uint16_big;
#if (defined(__SVR4) && defined(__sun))
#pragma pack(0)
#else
#pragma pack(pop)
#endif
template<typename T> static inline void zeromem(T *a, size_t count = 1) { memset(a, 0, count * sizeof(T)); }
typedef int SortCompareProc(const void *, const void *);
template<typename T> static FORCEINLINE void QuickSortT(T *base, size_t num, int (*comp)(const T *, const T *)) { qsort(base, num, sizeof(T), (SortCompareProc*)comp); }
// WARNING: The template parameter MUST be a POD type!
template <typename T, size_t minsize = 16> class Array {
protected:
T *mem;
size_t alloc,count;
public:
Array(size_t init) { Init(init); }
Array() { Init(); }
~Array() { Free(); }
void inline Init() { mem = NULL; alloc = count = 0; }
void inline Init(size_t init) { Init(); if (init) Resize(init); }
size_t inline GetCount() const { return count; }
size_t inline GetAlloc() const { return alloc; }
void inline SetCount(size_t c) { count = c; }
inline T& operator[](size_t offset) { assert(offset ==0 || offset<alloc); return mem[offset]; }
inline const T& operator[](size_t offset) const { assert(offset ==0 || offset<alloc); return mem[offset]; }
void inline Resize(size_t a) {
if (a == 0) { free(mem); Init(); }
else { mem = (T*)realloc(mem, (alloc=a) * sizeof(T)); }
}
void Grow() { Resize(::max<size_t>(minsize, alloc * 2)); }
inline size_t Append(const T &t) {
if (count >= alloc) Grow();
size_t r=count++;
mem[r] = t;
return r;
}
T inline &Append() {
if (count >= alloc) Grow();
return mem[count++];
}
void inline Compact() {
Resize(count);
}
void inline Free() {
free(mem);
Init();
}
void inline Clear() {
count = 0;
}
bool inline MoveUpLast(size_t index) {
assert(index < count);
size_t c = --count;
if (index != c) {
mem[index] = mem[c];
return true;
}
return false;
}
bool inline MoveUpLastExist(const T &v) {
return MoveUpLast(LookupElementExist(v));
}
size_t inline LookupElement(const T &v) const {
for(size_t i = 0; i != count; i++)
if (mem[i] == v)
return i;
return (size_t) -1;
}
bool inline HasElement(const T &v) const {
return LookupElement(v) != -1;
}
typedef int SortCompareProc(const T *a, const T *b);
void Sort(SortCompareProc* proc, size_t start, size_t end) {
QuickSortT(&mem[start], end - start, proc);
}
void Sort(SortCompareProc* proc, size_t start) {
Sort(proc, start, count);
}
void Sort(SortCompareProc* proc) {
Sort(proc, 0, count);
}
};
#endif //__TEMPLATES_H__

File diff suppressed because it is too large Load Diff

View File

@@ -1,165 +0,0 @@
#ifndef __UTP_H__
#define __UTP_H__
#include "utypes.h"
#ifdef WIN32
#define _CRT_SECURE_NO_DEPRECATE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
#else
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
struct UTPSocket;
// Used to set sockopt on a uTP socket to set the version of uTP
// to use for outgoing connections. This can only be called before
// the uTP socket is connected
#define SO_UTPVERSION 99
enum {
// socket has reveived syn-ack (notification only for outgoing connection completion)
// this implies writability
UTP_STATE_CONNECT = 1,
// socket is able to send more data
UTP_STATE_WRITABLE = 2,
// connection closed
UTP_STATE_EOF = 3,
// socket is being destroyed, meaning all data has been sent if possible.
// it is not valid to refer to the socket after this state change occurs
UTP_STATE_DESTROYING = 4,
};
// Callbacks called by a uTP socket (register with UTP_SetCallbacks)
// The uTP socket layer calls this when bytes have been received from the network.
typedef void UTPOnReadProc(void *userdata, const byte *bytes, size_t count);
// The uTP socket layer calls this to fill the outgoing buffer with bytes.
// The uTP layer takes responsibility that those bytes will be delivered.
typedef void UTPOnWriteProc(void *userdata, byte *bytes, size_t count);
// The uTP socket layer calls this to retrieve number of bytes currently in read buffer
typedef size_t UTPGetRBSize(void *userdata);
// The uTP socket layer calls this whenever the socket becomes writable.
typedef void UTPOnStateChangeProc(void *userdata, int state);
// The uTP socket layer calls this when an error occurs on the socket.
// These errors currently include ECONNREFUSED, ECONNRESET and ETIMEDOUT, but
// could eventually include any BSD socket error.
typedef void UTPOnErrorProc(void *userdata, int errcode);
// The uTP socket layer calls this to report overhead statistics
typedef void UTPOnOverheadProc(void *userdata, bool send, size_t count, int type);
struct UTPFunctionTable {
UTPOnReadProc *on_read;
UTPOnWriteProc *on_write;
UTPGetRBSize *get_rb_size;
UTPOnStateChangeProc *on_state;
UTPOnErrorProc *on_error;
UTPOnOverheadProc *on_overhead;
};
// The uTP socket layer calls this when a new incoming uTP connection is established
// this implies writability
typedef void UTPGotIncomingConnection(void *userdata, struct UTPSocket* s);
// The uTP socket layer calls this to send UDP packets
typedef void SendToProc(void *userdata, const byte *p, size_t len, const struct sockaddr *to, socklen_t tolen);
// Functions which can be called with a uTP socket
// Create a uTP socket
struct UTPSocket *UTP_Create(SendToProc *send_to_proc, void *send_to_userdata,
const struct sockaddr *addr, socklen_t addrlen);
// Setup the callbacks - must be done before connect or on incoming connection
void UTP_SetCallbacks(struct UTPSocket *socket, struct UTPFunctionTable *func, void *userdata);
// Valid options include SO_SNDBUF, SO_RCVBUF and SO_UTPVERSION
bool UTP_SetSockopt(struct UTPSocket *socket, int opt, int val);
// Try to connect to a specified host.
void UTP_Connect(struct UTPSocket *socket);
// Process a UDP packet from the network. This will process a packet for an existing connection,
// or create a new connection and call incoming_proc. Returns true if the packet was processed
// in some way, false if the packet did not appear to be uTP.
bool UTP_IsIncomingUTP(UTPGotIncomingConnection *incoming_proc,
SendToProc *send_to_proc, void *send_to_userdata,
const byte *buffer, size_t len, const struct sockaddr *to, socklen_t tolen);
// Process an ICMP received UDP packet.
bool UTP_HandleICMP(const byte* buffer, size_t len, const struct sockaddr *to, socklen_t tolen);
// Write bytes to the uTP socket.
// Returns true if the socket is still writable.
bool UTP_Write(struct UTPSocket *socket, size_t count);
// Notify the uTP socket of buffer drain
void UTP_RBDrained(struct UTPSocket *socket);
// Call periodically to process timeouts and other periodic events
void UTP_CheckTimeouts(void);
// Retrieves the peer address of the specified socket, stores this address in the
// sockaddr structure pointed to by the addr argument, and stores the length of this
// address in the object pointed to by the addrlen argument.
void UTP_GetPeerName(struct UTPSocket *socket, struct sockaddr *addr, socklen_t *addrlen);
void UTP_GetDelays(struct UTPSocket *socket, int32 *ours, int32 *theirs, uint32 *age);
size_t UTP_GetPacketSize(struct UTPSocket *socket);
#ifdef _DEBUG
struct UTPStats {
uint64 _nbytes_recv; // total bytes received
uint64 _nbytes_xmit; // total bytes transmitted
uint32 _rexmit; // retransmit counter
uint32 _fastrexmit; // fast retransmit counter
uint32 _nxmit; // transmit counter
uint32 _nrecv; // receive counter (total)
uint32 _nduprecv; // duplicate receive counter
};
// Get stats for UTP socket
void UTP_GetStats(struct UTPSocket *socket, UTPStats *stats);
#endif
// Close the UTP socket.
// It is not valid to issue commands for this socket after it is closed.
// This does not actually destroy the socket until outstanding data is sent, at which
// point the socket will change to the UTP_STATE_DESTROYING state.
void UTP_Close(struct UTPSocket *socket);
struct UTPGlobalStats {
uint32 _nraw_recv[5]; // total packets recieved less than 300/600/1200/MTU bytes fpr all connections (global)
uint32 _nraw_send[5]; // total packets sent less than 300/600/1200/MTU bytes for all connections (global)
};
void UTP_GetGlobalStats(struct UTPGlobalStats *stats);
#ifdef __cplusplus
}
#endif
#endif //__UTP_H__

View File

@@ -1,39 +0,0 @@
#define CCONTROL_TARGET (100 * 1000) // us
#define RATE_CHECK_INTERVAL 10000 // ms
#define DYNAMIC_PACKET_SIZE_ENABLED false
#define DYNAMIC_PACKET_SIZE_FACTOR 2
// This should return the global number of bytes sent, used for determining dynamic
// packet size based on rate
#warning implement this in libtransmission
uint64 UTP_GetGlobalUTPBytesSent(const struct sockaddr *remote, socklen_t remotelen) { return 0; }
enum bandwidth_type_t {
payload_bandwidth, connect_overhead,
close_overhead, ack_overhead,
header_overhead, retransmit_overhead
};
#ifdef WIN32
#define I64u "%I64u"
#else
#define I64u "%Lu"
#endif
#ifdef WIN32
#define snprintf _snprintf
#endif
#define g_log_utp 0
#define g_log_utp_verbose 0
void utp_log(char const* fmt, ...)
{
/*
printf("[%u] ", UTP_GetMilliseconds());
va_list vl;
va_start(vl, fmt);
vprintf(fmt, vl);
va_end(vl);
puts("");
fflush(stdout);
*/
};

View File

@@ -1,26 +0,0 @@
#define CCONTROL_TARGET (100 * 1000) // us
#define RATE_CHECK_INTERVAL 10000 // ms
#define DYNAMIC_PACKET_SIZE_ENABLED false
#define DYNAMIC_PACKET_SIZE_FACTOR 2
// This should return the global number of bytes sent, used for determining dynamic
// packet size based on rate
uint64 UTP_GetGlobalUTPBytesSent(const struct sockaddr *remote, socklen_t remotelen) { return 0; }
enum bandwidth_type_t {
payload_bandwidth, connect_overhead,
close_overhead, ack_overhead,
header_overhead, retransmit_overhead
};
#ifdef WIN32
#define I64u "%I64u"
#else
#define I64u "%Lu"
#endif
#ifdef WIN32
#define snprintf _snprintf
#endif
#define g_log_utp 0
#define g_log_utp_verbose 0
void utp_log(char const* fmt, ...);

View File

@@ -1,210 +0,0 @@
#include "StdAfx.h"
#include "utypes.h"
#include <assert.h>
#include <stdlib.h>
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
typedef ULONGLONG (WINAPI GetTickCount64Proc)(void);
static GetTickCount64Proc *pt2GetTickCount64;
static GetTickCount64Proc *pt2RealGetTickCount;
static uint64 startPerformanceCounter;
static uint64 startGetTickCount;
// MSVC 6 standard doesn't like division with uint64s
static double counterPerMicrosecond;
uint64 UTGetTickCount64()
{
if (pt2GetTickCount64) {
return pt2GetTickCount64();
}
if (pt2RealGetTickCount) {
uint64 v = pt2RealGetTickCount();
// fix return value from GetTickCount
return (DWORD)v | ((v >> 0x18) & 0xFFFFFFFF00000000);
}
return (uint64)GetTickCount();
}
void Time_Initialize()
{
HMODULE kernel32 = GetModuleHandleA("kernel32.dll");
pt2GetTickCount64 = (GetTickCount64Proc*)GetProcAddress(kernel32, "GetTickCount64");
// not a typo. GetTickCount actually returns 64 bits
pt2RealGetTickCount = (GetTickCount64Proc*)GetProcAddress(kernel32, "GetTickCount");
uint64 frequency;
QueryPerformanceCounter((LARGE_INTEGER*)&startPerformanceCounter);
QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);
counterPerMicrosecond = (double)frequency / 1000000.0f;
startGetTickCount = UTGetTickCount64();
}
int64 abs64(int64 x) { return x < 0 ? -x : x; }
static uint64 GetMicroseconds()
{
static bool time_init = false;
if (!time_init) {
time_init = true;
Time_Initialize();
}
uint64 counter;
uint64 tick;
QueryPerformanceCounter((LARGE_INTEGER*) &counter);
tick = UTGetTickCount64();
// unfortunately, QueryPerformanceCounter is not guaranteed
// to be monotonic. Make it so.
int64 ret = (int64)(((int64)counter - (int64)startPerformanceCounter) / counterPerMicrosecond);
// if the QPC clock leaps more than one second off GetTickCount64()
// something is seriously fishy. Adjust QPC to stay monotonic
int64 tick_diff = tick - startGetTickCount;
if (abs64(ret / 100000 - tick_diff / 100) > 10) {
startPerformanceCounter -= (uint64)((int64)(tick_diff * 1000 - ret) * counterPerMicrosecond);
ret = (int64)((counter - startPerformanceCounter) / counterPerMicrosecond);
}
return ret;
}
#else //!WIN32
#include <time.h>
#include <sys/time.h> // Linux needs both time.h and sys/time.h
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#if defined(__APPLE__)
#include <mach/mach_time.h>
static uint64 GetMicroseconds()
{
// http://developer.apple.com/mac/library/qa/qa2004/qa1398.html
// http://www.macresearch.org/tutorial_performance_and_time
static mach_timebase_info_data_t sTimebaseInfo;
static uint64_t start_tick = 0;
uint64_t tick;
// Returns a counter in some fraction of a nanoseconds
tick = mach_absolute_time();
if (sTimebaseInfo.denom == 0) {
// Get the timer ratio to convert mach_absolute_time to nanoseconds
mach_timebase_info(&sTimebaseInfo);
start_tick = tick;
}
// Calculate the elapsed time, convert it to microseconds and return it.
return ((tick - start_tick) * sTimebaseInfo.numer) / (sTimebaseInfo.denom * 1000);
}
#else //!__APPLE__
/* Unfortunately, #ifdef CLOCK_MONOTONIC is not enough to make sure that
POSIX clocks work -- we could be running a recent libc with an ancient
kernel (think OpenWRT). -- jch */
static uint64_t GetMicroseconds()
{
static int have_posix_clocks = -1;
int rc;
#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(CLOCK_MONOTONIC)
if (have_posix_clocks < 0) {
struct timespec ts;
rc = clock_gettime(CLOCK_MONOTONIC, &ts);
if (rc < 0) {
have_posix_clocks = 0;
} else {
have_posix_clocks = 1;
}
}
if (have_posix_clocks) {
struct timespec ts;
rc = clock_gettime(CLOCK_MONOTONIC, &ts);
return uint64(ts.tv_sec) * 1000000 + ts.tv_nsec / 1000;
}
#endif
{
struct timeval tv;
rc = gettimeofday(&tv, NULL);
return uint64(tv.tv_sec) * 1000000 + tv.tv_usec;
}
}
#endif //!__APPLE__
#endif //!WIN32
uint64 UTP_GetMicroseconds()
{
static uint64 offset = 0, previous = 0;
uint64 now = GetMicroseconds() + offset;
if (previous > now) {
/* Eek! */
offset += previous - now;
now = previous;
}
previous = now;
return now;
}
uint32 UTP_GetMilliseconds()
{
return UTP_GetMicroseconds() / 1000;
}
#define ETHERNET_MTU 1500
#define IPV4_HEADER_SIZE 20
#define IPV6_HEADER_SIZE 40
#define UDP_HEADER_SIZE 8
#define GRE_HEADER_SIZE 24
#define PPPOE_HEADER_SIZE 8
#define MPPE_HEADER_SIZE 2
// packets have been observed in the wild that were fragmented
// with a payload of 1416 for the first fragment
// There are reports of routers that have MTU sizes as small as 1392
#define FUDGE_HEADER_SIZE 36
#define TEREDO_MTU 1280
#define UDP_IPV4_OVERHEAD (IPV4_HEADER_SIZE + UDP_HEADER_SIZE)
#define UDP_IPV6_OVERHEAD (IPV6_HEADER_SIZE + UDP_HEADER_SIZE)
#define UDP_TEREDO_OVERHEAD (UDP_IPV4_OVERHEAD + UDP_IPV6_OVERHEAD)
#define UDP_IPV4_MTU (ETHERNET_MTU - IPV4_HEADER_SIZE - UDP_HEADER_SIZE - GRE_HEADER_SIZE - PPPOE_HEADER_SIZE - MPPE_HEADER_SIZE - FUDGE_HEADER_SIZE)
#define UDP_IPV6_MTU (ETHERNET_MTU - IPV6_HEADER_SIZE - UDP_HEADER_SIZE - GRE_HEADER_SIZE - PPPOE_HEADER_SIZE - MPPE_HEADER_SIZE - FUDGE_HEADER_SIZE)
#define UDP_TEREDO_MTU (TEREDO_MTU - IPV6_HEADER_SIZE - UDP_HEADER_SIZE)
uint16 UTP_GetUDPMTU(const struct sockaddr *remote, socklen_t remotelen)
{
// Since we don't know the local address of the interface,
// be conservative and assume all IPv6 connections are Teredo.
return remote->sa_family == AF_INET6 ? UDP_TEREDO_MTU : UDP_IPV4_MTU;
}
uint16 UTP_GetUDPOverhead(const struct sockaddr *remote, socklen_t remotelen)
{
// Since we don't know the local address of the interface,
// be conservative and assume all IPv6 connections are Teredo.
return remote->sa_family == AF_INET6 ? UDP_TEREDO_OVERHEAD : UDP_IPV4_OVERHEAD;
}
uint32 UTP_Random()
{
return rand();
}
void UTP_DelaySample(const struct sockaddr *remote, int sample_ms) {}
size_t UTP_GetPacketSize(const struct sockaddr *remote) { return 1500; }

View File

@@ -1,16 +0,0 @@
// This should return the MTU to the destination
uint16 UTP_GetUDPMTU(const struct sockaddr *remote, socklen_t remotelen);
// This should return the number of bytes of UDP overhead for one packet to the
// destination, for overhead calculation only
uint16 UTP_GetUDPOverhead(const struct sockaddr *remote, socklen_t remotelen);
// This should return monotonically increasing milliseconds, start point does not matter
uint32 UTP_GetMilliseconds();
// This should return monotonically increasing microseconds, start point does not matter
uint64 UTP_GetMicroseconds();
// This should return a random uint32
uint32 UTP_Random();
// This is called every time we have a delay sample is made
void UTP_DelaySample(const struct sockaddr *remote, int sample_ms);
// Should return the max packet size to use when sending to the given address
size_t UTP_GetPacketSize(const struct sockaddr *remote);

View File

@@ -1,42 +0,0 @@
#ifndef __UTYPES_H__
#define __UTYPES_H__
// standard types
typedef unsigned char byte;
typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned short uint16;
typedef signed short int16;
typedef unsigned int uint;
typedef unsigned int uint32;
typedef signed int int32;
#ifdef _MSC_VER
typedef unsigned __int64 uint64;
typedef signed __int64 int64;
#else
typedef unsigned long long uint64;
typedef long long int64;
#endif
/* compile-time assert */
#ifndef CASSERT
#define CASSERT( exp, name ) typedef int is_not_##name [ (exp ) ? 1 : -1 ];
#endif
CASSERT(8 == sizeof(uint64), sizeof_uint64_is_8)
CASSERT(8 == sizeof(int64), sizeof_int64_is_8)
#ifndef INT64_MAX
#define INT64_MAX 0x7fffffffffffffffLL
#endif
// always ANSI
typedef const char * cstr;
typedef char * str;
#ifndef __cplusplus
typedef uint8 bool;
#endif
#endif //__UTYPES_H__

View File

@@ -1,585 +0,0 @@
$Id: Changelog.txt,v 1.193 2014/02/05 17:26:45 nanard Exp $
miniUPnP client Changelog.
2014/02/05:
handle EINPROGRESS after connect()
2014/02/03:
minixml now handle XML comments
VERSION 1.9 : released 2014/01/31
2014/01/31:
added argument remoteHost to UPNP_GetSpecificPortMappingEntry()
increment API_VERSION to 10
2013/12/09:
--help and -h arguments in upnpc.c
2013/10/07:
fixed potential buffer overrun in miniwget.c
Modified UPNP_GetValidIGD() to check for ExternalIpAddress
2013/08/01:
define MAXHOSTNAMELEN if not already done
2013/06/06:
update upnpreplyparse to allow larger values (128 chars instead of 64)
2013/05/14:
Update upnpreplyparse to take into account "empty" elements
validate upnpreplyparse.c code with "make check"
2013/05/03:
Fix Solaris build thanks to Maciej Małecki
2013/04/27:
Fix testminiwget.sh for BSD
2013/03/23:
Fixed Makefile for *BSD
2013/03/11:
Update Makefile to use JNAerator version 0.11
2013/02/11:
Fix testminiwget.sh for use with dash
Use $(DESTDIR) in Makefile
VERSION 1.8 : released 2013/02/06
2012/10/16:
fix testminiwget with no IPv6 support
2012/09/27:
Rename all include guards to not clash with C99
(7.1.3 Reserved identifiers).
2012/08/30:
Added -e option to upnpc program (set description for port mappings)
2012/08/29:
Python 3 support (thanks to Christopher Foo)
2012/08/11:
Fix a memory link in UPNP_GetValidIGD()
Try to handle scope id in link local IPv6 URL under MS Windows
2012/07/20:
Disable HAS_IP_MREQN on DragonFly BSD
2012/06/28:
GetUPNPUrls() now inserts scope into link-local IPv6 addresses
2012/06/23:
More error return checks in upnpc.c
#define MINIUPNPC_GET_SRC_ADDR enables receivedata() to get scope_id
parseURL() now parses IPv6 addresses scope
new parameter for miniwget() : IPv6 address scope
increment API_VERSION to 9
2012/06/20:
fixed CMakeLists.txt
2012/05/29
Improvements in testminiwget.sh
VERSION 1.7 : released 2012/05/24
2012/05/01:
Cleanup settings of CFLAGS in Makefile
Fix signed/unsigned integer comparaisons
2012/04/20:
Allow to specify protocol with TCP or UDP for -A option
2012/04/09:
Only try to fetch XML description once in UPNP_GetValidIGD()
Added -ansi flag to compilation, and fixed C++ comments to ANSI C comments.
2012/04/05:
minor improvements to minihttptestserver.c
2012/03/15:
upnperrors.c returns valid error string for unrecognized error codes
2012/03/08:
make minihttptestserver listen on loopback interface instead of 0.0.0.0
2012/01/25:
Maven installation thanks to Alexey Kuznetsov
2012/01/21:
Replace WIN32 macro by _WIN32
2012/01/19:
Fixes in java wrappers thanks to Alexey Kuznetsov :
https://github.com/axet/miniupnp/tree/fix-javatest/miniupnpc
Make and install .deb packages (python) thanks to Alexey Kuznetsov :
https://github.com/axet/miniupnp/tree/feature-debbuild/miniupnpc
2012/01/07:
The multicast interface can now be specified by name with IPv4.
2012/01/02:
Install man page
2011/11/25:
added header to Port Mappings list in upnpc.c
2011/10/09:
Makefile : make clean now removes jnaerator generated files.
MINIUPNPC_VERSION in miniupnpc.h (updated by make)
2011/09/12:
added rootdescURL to UPNPUrls structure.
VERSION 1.6 : released 2011/07/25
2011/07/25:
Update doc for version 1.6 release
2011/06/18:
Fix for windows in miniwget.c
2011/06/04:
display remote host in port mapping listing
2011/06/03:
Fix in make install : there were missing headers
2011/05/26:
Fix the socket leak in miniwget thanks to Richard Marsh.
Permit to add leaseduration in -a command. Display lease duration.
2011/05/15:
Try both LinkLocal and SiteLocal multicast address for SSDP in IPv6
2011/05/09:
add a test in testminiwget.sh.
more error checking in miniwget.c
2011/05/06:
Adding some tool to test and validate miniwget.c
simplified and debugged miniwget.c
2011/04/11:
moving ReceiveData() to a receivedata.c file.
parsing presentation url
adding IGD v2 WANIPv6FirewallControl commands
2011/04/10:
update of miniupnpcmodule.c
comments in miniwget.c, update in testminiwget
Adding errors codes from IGD v2
new functions in upnpc.c for IGD v2
2011/04/09:
Support for litteral ip v6 address in miniwget
2011/04/08:
Adding support for urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
Updating APIVERSION
Supporting IPV6 in upnpDiscover()
Adding a -6 option to upnpc command line tool
2011/03/18:
miniwget/parseURL() : return an error when url param is null.
fixing GetListOfPortMappings()
2011/03/14:
upnpDiscover() now reporting an error code.
improvements in comments.
2011/03/11:
adding miniupnpcstrings.h.cmake and CMakeLists.txt files.
2011/02/15:
Implementation of GetListOfPortMappings()
2011/02/07:
updates to minixml to support character data starting with spaces
minixml now support CDATA
upnpreplyparse treats <NewPortListing> specificaly
change in simpleUPnPcommand to return the buffer (simplification)
2011/02/06:
Added leaseDuration argument to AddPortMapping()
Starting to implement GetListOfPortMappings()
2011/01/11:
updating wingenminiupnpcstrings.c
2011/01/04:
improving updateminiupnpcstrings.sh
VERSION 1.5 : released 2011/01/01
2010/12/21:
use NO_GETADDRINFO macro to disable the use of getaddrinfo/freeaddrinfo
2010/12/11:
Improvements on getHTTPResponse() code.
2010/12/09:
new code for miniwget that handle Chunked transfer encoding
using getHTTPResponse() in SOAP call code
Adding MANIFEST.in for 'python setup.py bdist_rpm'
2010/11/25:
changes to minissdpc.c to compile under Win32.
see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=729
2010/09/17:
Various improvement to Makefile from Michał Górny
2010/08/05:
Adding the script "external-ip.sh" from Reuben Hawkins
2010/06/09:
update to python module to match modification made on 2010/04/05
update to Java test code to match modification made on 2010/04/05
all UPNP_* function now return an error if the SOAP request failed
at HTTP level.
2010/04/17:
Using GetBestRoute() under win32 in order to find the
right interface to use.
2010/04/12:
Retrying with HTTP/1.1 if HTTP/1.0 failed. see
http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1703
2010/04/07:
avoid returning duplicates in upnpDiscover()
2010/04/05:
Create a connecthostport.h/.c with connecthostport() function
and use it in miniwget and miniupnpc.
Use getnameinfo() instead of inet_ntop or inet_ntoa
Work to make miniupnpc IPV6 compatible...
Add java test code.
Big changes in order to support device having both WANIPConnection
and WANPPPConnection.
2010/04/04:
Use getaddrinfo() instead of gethostbyname() in miniwget.
2010/01/06:
#define _DARWIN_C_SOURCE for Mac OS X
2009/12/19:
Improve MinGW32 build
2009/12/11:
adding a MSVC9 project to build the static library and executable
2009/12/10:
Fixing some compilation stuff for Windows/MinGW
2009/12/07:
adaptations in Makefile and updateminiupnpcstring.sh for AmigaOS
some fixes for Windows when using virtual ethernet adapters (it is the
case with VMWare installed).
2009/12/04:
some fixes for AmigaOS compilation
Changed HTTP version to HTTP/1.0 for Soap too (to prevent chunked
transfer encoding)
2009/12/03:
updating printIDG and testigddescparse.c for debug.
modifications to compile under AmigaOS
adding a testminiwget program
Changed miniwget to advertise itself as HTTP/1.0 to prevent chunked
transfer encoding
2009/11/26:
fixing updateminiupnpcstrings.sh to take into account
which command that does not return an error code.
VERSION 1.4 : released 2009/10/30
2009/10/16:
using Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS in python module.
2009/10/10:
Some fixes for compilation under Solaris
compilation fixes : http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1464
2009/09/21:
fixing the code to ignore EINTR during connect() calls.
2009/08/07:
Set socket timeout for connect()
Some cleanup in miniwget.c
2009/08/04:
remove multiple redirections with -d in upnpc.c
Print textual error code in upnpc.c
Ignore EINTR during the connect() and poll() calls.
2009/07/29:
fix in updateminiupnpcstrings.sh if OS name contains "/"
Sending a correct value for MX: field in SSDP request
2009/07/20:
Change the Makefile to compile under Mac OS X
Fixed a stackoverflow in getDevicesFromMiniSSDPD()
2009/07/09:
Compile under Haiku
generate miniupnpcstrings.h.in from miniupnpcstrings.h
2009/06/04:
patching to compile under CygWin and cross compile for minGW
VERSION 1.3 :
2009/04/17:
updating python module
Use strtoull() when using C99
2009/02/28:
Fixed miniwget.c for compiling under sun
2008/12/18:
cleanup in Makefile (thanks to Paul de Weerd)
minissdpc.c : win32 compatibility
miniupnpc.c : changed xmlns prefix from 'm' to 'u'
Removed NDEBUG (using DEBUG)
2008/10/14:
Added the ExternalHost argument to DeletePortMapping()
2008/10/11:
Added the ExternalHost argument to AddPortMapping()
Put a correct User-Agent: header in HTTP requests.
VERSION 1.2 :
2008/10/07:
Update docs
2008/09/25:
Integrated sameport patch from Dario Meloni : Added a "sameport"
argument to upnpDiscover().
2008/07/18:
small modif to make Clang happy :)
2008/07/17:
#define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV...
2008/07/14:
include declspec.h in installation (to /usr/include/miniupnpc)
VERSION 1.1 :
2008/07/04:
standard options for install/ln instead of gnu-specific stuff.
2008/07/03:
now builds a .dll and .lib with win32. (mingw32)
2008/04/28:
make install now install the binary of the upnpc tool
2008/04/27:
added testupnpigd.py
added error strings for miniupnpc "internal" errors
improved python module error/exception reporting.
2008/04/23:
Completely rewrite igd_desc_parse.c in order to be compatible with
Linksys WAG200G
Added testigddescparse
updated python module
VERSION 1.0 :
2008/02/21:
put some #ifdef DEBUG around DisplayNameValueList()
2008/02/18:
Improved error reporting in upnpcommands.c
UPNP_GetStatusInfo() returns LastConnectionError
2008/02/16:
better error handling in minisoap.c
improving display of "valid IGD found" in upnpc.c
2008/02/03:
Fixing UPNP_GetValidIGD()
improved make install :)
2007/12/22:
Adding upnperrors.c/h to provide a strupnperror() function
used to translate UPnP error codes to string.
2007/12/19:
Fixing getDevicesFromMiniSSDPD()
improved error reporting of UPnP functions
2007/12/18:
It is now possible to specify a different location for MiniSSDPd socket.
working with MiniSSDPd is now more efficient.
python module improved.
2007/12/16:
improving error reporting
2007/12/13:
Try to improve compatibility by using HTTP/1.0 instead of 1.1 and
XML a bit different for SOAP.
2007/11/25:
fixed select() call for linux
2007/11/15:
Added -fPIC to CFLAG for better shared library code.
2007/11/02:
Fixed a potential socket leak in miniwget2()
2007/10/16:
added a parameter to upnpDiscover() in order to allow the use of another
interface than the default multicast interface.
2007/10/12:
Fixed the creation of symbolic link in Makefile
2007/10/08:
Added man page
2007/10/02:
fixed memory bug in GetUPNPUrls()
2007/10/01:
fixes in the Makefile
Added UPNP_GetIGDFromUrl() and adapted the sample program accordingly.
Added SONAME in the shared library to please debian :)
fixed MS Windows compilation (minissdpd is not available under MS Windows).
2007/09/25:
small change to Makefile to be able to install in a different location
(default is /usr)
2007/09/24:
now compiling both shared and static library
2007/09/19:
Cosmetic changes on upnpc.c
2007/09/02:
adapting to new miniSSDPd (release version ?)
2007/08/31:
Usage of miniSSDPd to skip discovery process.
2007/08/27:
fixed python module to allow compilation with Python older than Python 2.4
2007/06/12:
Added a python module.
2007/05/19:
Fixed compilation under MinGW
2007/05/15:
fixed a memory leak in AddPortMapping()
Added testupnpreplyparse executable to check the parsing of
upnp soap messages
minixml now ignore namespace prefixes.
2007/04/26:
upnpc now displays external ip address with -s or -l
2007/04/11:
changed MINIUPNPC_URL_MAXSIZE to 128 to accomodate the "BT Voyager 210"
2007/03/19:
cleanup in miniwget.c
2007/03/01:
Small typo fix...
2007/01/30:
Now parsing the HTTP header from SOAP responses in order to
get content-length value.
2007/01/29:
Fixed the Soap Query to speedup the HTTP request.
added some Win32 DLL stuff...
2007/01/27:
Fixed some WIN32 compatibility issues
2006/12/14:
Added UPNPIGD_IsConnected() function in miniupnp.c/.h
Added UPNP_GetValidIGD() in miniupnp.c/.h
cleaned upnpc.c main(). now using UPNP_GetValidIGD()
2006/12/07:
Version 1.0-RC1 released
2006/12/03:
Minor changes to compile under SunOS/Solaris
2006/11/30:
made a minixml parser validator program
updated minixml to handle attributes correctly
2006/11/22:
Added a -r option to the upnpc sample thanks to Alexander Hubmann.
2006/11/19:
Cleanup code to make it more ANSI C compliant
2006/11/10:
detect and display local lan address.
2006/11/04:
Packets and Bytes Sent/Received are now unsigned int.
2006/11/01:
Bug fix thanks to Giuseppe D'Angelo
2006/10/31:
C++ compatibility for .h files.
Added a way to get ip Address on the LAN used to reach the IGD.
2006/10/25:
Added M-SEARCH to the services in the discovery process.
2006/10/22:
updated the Makefile to use makedepend, added a "make install"
update Makefile
2006/10/20:
fixing the description url parsing thanks to patch sent by
Wayne Dawe.
Fixed/translated some comments.
Implemented a better discover process, first looking
for IGD then for root devices (as some devices only reply to
M-SEARCH for root devices).
2006/09/02:
added freeUPNPDevlist() function.
2006/08/04:
More command line arguments checking
2006/08/01:
Added the .bat file to compile under Win32 with minGW32
2006/07/31:
Fixed the rootdesc parser (igd_desc_parse.c)
2006/07/20:
parseMSEARCHReply() is now returning the ST: line as well
starting changes to detect several UPnP devices on the network
2006/07/19:
using GetCommonLinkProperties to get down/upload bitrate

View File

@@ -1,27 +0,0 @@
MiniUPnPc
Copyright (c) 2005-2011, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,47 +0,0 @@
noinst_LIBRARIES = libminiupnp.a
AM_CFLAGS = @PTHREAD_CFLAGS@ -DNDEBUG -D_GNU_SOURCE
libminiupnp_a_SOURCES = \
connecthostport.c \
igd_desc_parse.c \
minisoap.c \
minissdpc.c \
miniupnpc.c \
miniwget.c \
minixml.c \
portlistingparse.c \
receivedata.c \
upnpcommands.c \
upnpreplyparse.c
noinst_HEADERS = \
bsdqueue.h \
codelength.h \
connecthostport.h \
declspec.h \
igd_desc_parse.h \
minisoap.h \
minissdpc.h \
miniupnpc.h \
miniupnpctypes.h \
miniwget.h \
minixml.h \
portlistingparse.h \
receivedata.h \
upnpcommands.h \
upnpreplyparse.h
EXTRA_DIST = \
README \
LICENSE \
miniupnpcstrings.h.in \
updateminiupnpcstrings.sh
BUILT_SOURCES = \
miniupnpcstrings.h
miniupnpcstrings.h: Makefile
$(srcdir)/updateminiupnpcstrings.sh $(srcdir)/VERSION $(srcdir)/miniupnpcstrings.h.in $@
DISTCLEANFILES = $(builddir)/miniupnpcstrings.h

View File

@@ -1,66 +0,0 @@
Project: miniupnp
Project web page: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
github: https://github.com/miniupnp/miniupnp
freecode: http://freecode.com/projects/miniupnp
Author: Thomas Bernard
Copyright (c) 2005-2012 Thomas Bernard
This software is subject to the conditions detailed in the
LICENSE file provided within this distribution.
For the comfort of Win32 users, bsdqueue.h is included in the distribution.
Its licence is included in the header of the file.
bsdqueue.h is a copy of the sys/queue.h of an OpenBSD system.
* miniUPnP Client - miniUPnPc *
To compile, simply run 'gmake' (could be 'make' on your system).
Under win32, to compile with MinGW, type "mingw32make.bat".
MS Visual C solution and project files are supplied in the msvc/ subdirectory.
The compilation is known to work under linux, FreeBSD,
OpenBSD, MacOS X, AmigaOS and cygwin.
The official AmigaOS4.1 SDK was used for AmigaOS4 and GeekGadgets for AmigaOS3.
upx (http://upx.sourceforge.net) is used to compress the win32 .exe files.
To install the library and headers on the system use :
> su
> make install
> exit
alternatively, to install into a specific location, use :
> INSTALLPREFIX=/usr/local make install
upnpc.c is a sample client using the libminiupnpc.
To use the libminiupnpc in your application, link it with
libminiupnpc.a (or .so) and use the following functions found in miniupnpc.h,
upnpcommands.h and miniwget.h :
- upnpDiscover()
- miniwget()
- parserootdesc()
- GetUPNPUrls()
- UPNP_* (calling UPNP methods)
Note : use #include <miniupnpc/miniupnpc.h> etc... for the includes
and -lminiupnpc for the link
Discovery process is speeded up when MiniSSDPd is running on the machine.
* Python module *
you can build a python module with 'make pythonmodule'
and install it with 'make installpythonmodule'.
setup.py (and setupmingw32.py) are included in the distribution.
Feel free to contact me if you have any problem :
e-mail : miniupnp@free.fr
If you are using libminiupnpc in your application, please
send me an email !
For any question, you can use the web forum :
http://miniupnp.tuxfamily.org/forum/

View File

@@ -1 +0,0 @@
1.7

View File

@@ -1,127 +0,0 @@
$Id: apiversions.txt,v 1.3 2014/01/31 13:14:32 nanard Exp $
Differences in API between miniUPnPc versions
====================== miniUPnPc version 1.9 ======================
API version 10
upnpcommands.h:
added argument remoteHost to UPNP_GetSpecificPortMappingEntry()
miniupnpc.h:
updated macros :
#define MINIUPNPC_VERSION "1.9"
#define MINIUPNPC_API_VERSION 10
====================== miniUPnPc version 1.8 ======================
API version 9
miniupnpc.h:
updated macros :
#define MINIUPNPC_VERSION "1.8"
#define MINIUPNPC_API_VERSION 9
added "unsigned int scope_id;" to struct UPNPDev
added scope_id argument to GetUPNPUrls()
====================== miniUPnPc version 1.7 ======================
API version 8
miniupnpc.h :
add new macros :
#define MINIUPNPC_VERSION "1.7"
#define MINIUPNPC_API_VERSION 8
add rootdescURL to struct UPNPUrls
====================== miniUPnPc version 1.6 ======================
API version 8
Adding support for IPv6.
igd_desc_parse.h :
struct IGDdatas_service :
add char presentationurl[MINIUPNPC_URL_MAXSIZE];
struct IGDdatas :
add struct IGDdatas_service IPv6FC;
miniupnpc.h :
new macros :
#define UPNPDISCOVER_SUCCESS (0)
#define UPNPDISCOVER_UNKNOWN_ERROR (-1)
#define UPNPDISCOVER_SOCKET_ERROR (-101)
#define UPNPDISCOVER_MEMORY_ERROR (-102)
simpleUPnPcommand() prototype changed (but is normaly not used by API users)
add arguments ipv6 and error to upnpDiscover() :
struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock, int sameport,
int ipv6,
int * error);
add controlURL_6FC member to struct UPNPUrls :
struct UPNPUrls {
char * controlURL;
char * ipcondescURL;
char * controlURL_CIF;
char * controlURL_6FC;
};
upnpcommands.h :
add leaseDuration argument to UPNP_AddPortMapping()
add desc, enabled and leaseDuration arguments to UPNP_GetSpecificPortMappingEntry()
add UPNP_GetListOfPortMappings() function (IGDv2)
add IGDv2 IPv6 related functions :
UPNP_GetFirewallStatus()
UPNP_GetOutboundPinholeTimeout()
UPNP_AddPinhole()
UPNP_UpdatePinhole()
UPNP_DeletePinhole()
UPNP_CheckPinholeWorking()
UPNP_GetPinholePackets()
====================== miniUPnPc version 1.5 ======================
API version 5
new function :
int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);
new macro in upnpcommands.h :
#define UPNPCOMMAND_HTTP_ERROR
====================== miniUPnPc version 1.4 ======================
Same API as version 1.3
====================== miniUPnPc version 1.3 ======================
API version 4
Use UNSIGNED_INTEGER type for
UPNP_GetTotalBytesSent(), UPNP_GetTotalBytesReceived(),
UPNP_GetTotalPacketsSent(), UPNP_GetTotalPacketsReceived()
Add remoteHost argument to UPNP_AddPortMapping() and UPNP_DeletePortMapping()
====================== miniUPnPc version 1.2 ======================
API version 3
added sameport argument to upnpDiscover()
struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock, int sameport);
====================== miniUPnPc Version 1.1 ======================
Same API as 1.0
====================== miniUPnPc Version 1.0 ======================
API version 2
struct UPNPDev {
struct UPNPDev * pNext;
char * descURL;
char * st;
char buffer[2];
};
struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock);

View File

@@ -1,531 +0,0 @@
/* $OpenBSD: queue.h,v 1.31 2005/11/25 08:06:25 otto Exp $ */
/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
*/
#ifndef _SYS_QUEUE_H_
#define _SYS_QUEUE_H_
/*
* This file defines five types of data structures: singly-linked lists,
* lists, simple queues, tail queues, and circular queues.
*
*
* A singly-linked list is headed by a single forward pointer. The elements
* are singly linked for minimum space and pointer manipulation overhead at
* the expense of O(n) removal for arbitrary elements. New elements can be
* added to the list after an existing element or at the head of the list.
* Elements being removed from the head of the list should use the explicit
* macro for this purpose for optimum efficiency. A singly-linked list may
* only be traversed in the forward direction. Singly-linked lists are ideal
* for applications with large datasets and few or no removals or for
* implementing a LIFO queue.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may only be traversed in the forward direction.
*
* A simple queue is headed by a pair of pointers, one the head of the
* list and the other to the tail of the list. The elements are singly
* linked to save space, so elements can only be removed from the
* head of the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the
* list. A simple queue may only be traversed in the forward direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
* A circle queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the list.
* A circle queue may be traversed in either direction, but has a more
* complex end of list detection.
*
* For details on the use of these macros, see the queue(3) manual page.
*/
#ifdef QUEUE_MACRO_DEBUG
#define _Q_INVALIDATE(a) (a) = ((void *)-1)
#else
#define _Q_INVALIDATE(a)
#endif
/*
* Singly-linked List definitions.
*/
#define SLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#ifdef SLIST_ENTRY
#undef SLIST_ENTRY
#endif
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
/*
* Singly-linked List access methods.
*/
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_END(head) NULL
#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_FOREACH(var, head, field) \
for((var) = SLIST_FIRST(head); \
(var) != SLIST_END(head); \
(var) = SLIST_NEXT(var, field))
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
for ((varp) = &SLIST_FIRST((head)); \
((var) = *(varp)) != SLIST_END(head); \
(varp) = &SLIST_NEXT((var), field))
/*
* Singly-linked List functions.
*/
#define SLIST_INIT(head) { \
SLIST_FIRST(head) = SLIST_END(head); \
}
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
(elm)->field.sle_next = (slistelm)->field.sle_next; \
(slistelm)->field.sle_next = (elm); \
} while (0)
#define SLIST_INSERT_HEAD(head, elm, field) do { \
(elm)->field.sle_next = (head)->slh_first; \
(head)->slh_first = (elm); \
} while (0)
#define SLIST_REMOVE_NEXT(head, elm, field) do { \
(elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
} while (0)
#define SLIST_REMOVE_HEAD(head, field) do { \
(head)->slh_first = (head)->slh_first->field.sle_next; \
} while (0)
#define SLIST_REMOVE(head, elm, type, field) do { \
if ((head)->slh_first == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \
} else { \
struct type *curelm = (head)->slh_first; \
\
while (curelm->field.sle_next != (elm)) \
curelm = curelm->field.sle_next; \
curelm->field.sle_next = \
curelm->field.sle_next->field.sle_next; \
_Q_INVALIDATE((elm)->field.sle_next); \
} \
} while (0)
/*
* List definitions.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
/*
* List access methods
*/
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_END(head) NULL
#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_FOREACH(var, head, field) \
for((var) = LIST_FIRST(head); \
(var)!= LIST_END(head); \
(var) = LIST_NEXT(var, field))
/*
* List functions.
*/
#define LIST_INIT(head) do { \
LIST_FIRST(head) = LIST_END(head); \
} while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
(listelm)->field.le_next->field.le_prev = \
&(elm)->field.le_next; \
(listelm)->field.le_next = (elm); \
(elm)->field.le_prev = &(listelm)->field.le_next; \
} while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.le_prev = (listelm)->field.le_prev; \
(elm)->field.le_next = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &(elm)->field.le_next; \
} while (0)
#define LIST_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
(head)->lh_first = (elm); \
(elm)->field.le_prev = &(head)->lh_first; \
} while (0)
#define LIST_REMOVE(elm, field) do { \
if ((elm)->field.le_next != NULL) \
(elm)->field.le_next->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = (elm)->field.le_next; \
_Q_INVALIDATE((elm)->field.le_prev); \
_Q_INVALIDATE((elm)->field.le_next); \
} while (0)
#define LIST_REPLACE(elm, elm2, field) do { \
if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
(elm2)->field.le_next->field.le_prev = \
&(elm2)->field.le_next; \
(elm2)->field.le_prev = (elm)->field.le_prev; \
*(elm2)->field.le_prev = (elm2); \
_Q_INVALIDATE((elm)->field.le_prev); \
_Q_INVALIDATE((elm)->field.le_next); \
} while (0)
/*
* Simple queue definitions.
*/
#define SIMPLEQ_HEAD(name, type) \
struct name { \
struct type *sqh_first; /* first element */ \
struct type **sqh_last; /* addr of last next element */ \
}
#define SIMPLEQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).sqh_first }
#define SIMPLEQ_ENTRY(type) \
struct { \
struct type *sqe_next; /* next element */ \
}
/*
* Simple queue access methods.
*/
#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
#define SIMPLEQ_END(head) NULL
#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
#define SIMPLEQ_FOREACH(var, head, field) \
for((var) = SIMPLEQ_FIRST(head); \
(var) != SIMPLEQ_END(head); \
(var) = SIMPLEQ_NEXT(var, field))
/*
* Simple queue functions.
*/
#define SIMPLEQ_INIT(head) do { \
(head)->sqh_first = NULL; \
(head)->sqh_last = &(head)->sqh_first; \
} while (0)
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
(head)->sqh_first = (elm); \
} while (0)
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.sqe_next = NULL; \
*(head)->sqh_last = (elm); \
(head)->sqh_last = &(elm)->field.sqe_next; \
} while (0)
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
(head)->sqh_last = &(elm)->field.sqe_next; \
(listelm)->field.sqe_next = (elm); \
} while (0)
#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
(head)->sqh_last = &(head)->sqh_first; \
} while (0)
/*
* Tail queue definitions.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
}
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
}
/*
* tail queue access methods
*/
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_END(head) NULL
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
/* XXX */
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_EMPTY(head) \
(TAILQ_FIRST(head) == TAILQ_END(head))
#define TAILQ_FOREACH(var, head, field) \
for((var) = TAILQ_FIRST(head); \
(var) != TAILQ_END(head); \
(var) = TAILQ_NEXT(var, field))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for((var) = TAILQ_LAST(head, headname); \
(var) != TAILQ_END(head); \
(var) = TAILQ_PREV(var, headname, field))
/*
* Tail queue functions.
*/
#define TAILQ_INIT(head) do { \
(head)->tqh_first = NULL; \
(head)->tqh_last = &(head)->tqh_first; \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
(head)->tqh_first->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(head)->tqh_first = (elm); \
(elm)->field.tqe_prev = &(head)->tqh_first; \
} while (0)
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.tqe_next = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &(elm)->field.tqe_next; \
} while (0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
(elm)->field.tqe_next->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(listelm)->field.tqe_next = (elm); \
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
} while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
(elm)->field.tqe_next = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
} while (0)
#define TAILQ_REMOVE(head, elm, field) do { \
if (((elm)->field.tqe_next) != NULL) \
(elm)->field.tqe_next->field.tqe_prev = \
(elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
_Q_INVALIDATE((elm)->field.tqe_prev); \
_Q_INVALIDATE((elm)->field.tqe_next); \
} while (0)
#define TAILQ_REPLACE(head, elm, elm2, field) do { \
if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
(elm2)->field.tqe_next->field.tqe_prev = \
&(elm2)->field.tqe_next; \
else \
(head)->tqh_last = &(elm2)->field.tqe_next; \
(elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
*(elm2)->field.tqe_prev = (elm2); \
_Q_INVALIDATE((elm)->field.tqe_prev); \
_Q_INVALIDATE((elm)->field.tqe_next); \
} while (0)
/*
* Circular queue definitions.
*/
#define CIRCLEQ_HEAD(name, type) \
struct name { \
struct type *cqh_first; /* first element */ \
struct type *cqh_last; /* last element */ \
}
#define CIRCLEQ_HEAD_INITIALIZER(head) \
{ CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
#define CIRCLEQ_ENTRY(type) \
struct { \
struct type *cqe_next; /* next element */ \
struct type *cqe_prev; /* previous element */ \
}
/*
* Circular queue access methods
*/
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
#define CIRCLEQ_END(head) ((void *)(head))
#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
#define CIRCLEQ_EMPTY(head) \
(CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
#define CIRCLEQ_FOREACH(var, head, field) \
for((var) = CIRCLEQ_FIRST(head); \
(var) != CIRCLEQ_END(head); \
(var) = CIRCLEQ_NEXT(var, field))
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
for((var) = CIRCLEQ_LAST(head); \
(var) != CIRCLEQ_END(head); \
(var) = CIRCLEQ_PREV(var, field))
/*
* Circular queue functions.
*/
#define CIRCLEQ_INIT(head) do { \
(head)->cqh_first = CIRCLEQ_END(head); \
(head)->cqh_last = CIRCLEQ_END(head); \
} while (0)
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
(elm)->field.cqe_next = (listelm)->field.cqe_next; \
(elm)->field.cqe_prev = (listelm); \
if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
(head)->cqh_last = (elm); \
else \
(listelm)->field.cqe_next->field.cqe_prev = (elm); \
(listelm)->field.cqe_next = (elm); \
} while (0)
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
(elm)->field.cqe_next = (listelm); \
(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
(head)->cqh_first = (elm); \
else \
(listelm)->field.cqe_prev->field.cqe_next = (elm); \
(listelm)->field.cqe_prev = (elm); \
} while (0)
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
(elm)->field.cqe_next = (head)->cqh_first; \
(elm)->field.cqe_prev = CIRCLEQ_END(head); \
if ((head)->cqh_last == CIRCLEQ_END(head)) \
(head)->cqh_last = (elm); \
else \
(head)->cqh_first->field.cqe_prev = (elm); \
(head)->cqh_first = (elm); \
} while (0)
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.cqe_next = CIRCLEQ_END(head); \
(elm)->field.cqe_prev = (head)->cqh_last; \
if ((head)->cqh_first == CIRCLEQ_END(head)) \
(head)->cqh_first = (elm); \
else \
(head)->cqh_last->field.cqe_next = (elm); \
(head)->cqh_last = (elm); \
} while (0)
#define CIRCLEQ_REMOVE(head, elm, field) do { \
if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
(head)->cqh_last = (elm)->field.cqe_prev; \
else \
(elm)->field.cqe_next->field.cqe_prev = \
(elm)->field.cqe_prev; \
if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
(head)->cqh_first = (elm)->field.cqe_next; \
else \
(elm)->field.cqe_prev->field.cqe_next = \
(elm)->field.cqe_next; \
_Q_INVALIDATE((elm)->field.cqe_prev); \
_Q_INVALIDATE((elm)->field.cqe_next); \
} while (0)
#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
CIRCLEQ_END(head)) \
(head).cqh_last = (elm2); \
else \
(elm2)->field.cqe_next->field.cqe_prev = (elm2); \
if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
CIRCLEQ_END(head)) \
(head).cqh_first = (elm2); \
else \
(elm2)->field.cqe_prev->field.cqe_next = (elm2); \
_Q_INVALIDATE((elm)->field.cqe_prev); \
_Q_INVALIDATE((elm)->field.cqe_next); \
} while (0)
#endif /* !_SYS_QUEUE_H_ */

View File

@@ -1,31 +0,0 @@
/* $Id: codelength.h,v 1.4 2012/09/27 15:40:29 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas BERNARD
* copyright (c) 2005-2011 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
#ifndef CODELENGTH_H_INCLUDED
#define CODELENGTH_H_INCLUDED
/* Encode length by using 7bit per Byte :
* Most significant bit of each byte specifies that the
* following byte is part of the code */
#define DECODELENGTH(n, p) n = 0; \
do { n = (n << 7) | (*p & 0x7f); } \
while((*(p++)&0x80) && (n<(1<<25)));
#define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \
n = 0; \
do { \
if((p) >= (p_limit)) break; \
n = (n << 7) | (*(p) & 0x7f); \
} while((*((p)++)&0x80) && (n<(1<<25)));
#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \
if(n>=2097152) *(p++) = (n >> 21) | 0x80; \
if(n>=16384) *(p++) = (n >> 14) | 0x80; \
if(n>=128) *(p++) = (n >> 7) | 0x80; \
*(p++) = n & 0x7f;
#endif

View File

@@ -1,261 +0,0 @@
/* $Id: connecthostport.c,v 1.13 2014/03/31 12:36:36 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2010-2014 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
/* use getaddrinfo() or gethostbyname()
* uncomment the following line in order to use gethostbyname() */
#ifdef NO_GETADDRINFO
#define USE_GETHOSTBYNAME
#endif
#include <string.h>
#include <stdio.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#define MAXHOSTNAMELEN 64
#define snprintf _snprintf
#define herror
#define socklen_t int
#else /* #ifdef _WIN32 */
#include <unistd.h>
#include <sys/param.h>
#include <sys/select.h>
#include <errno.h>
#define closesocket close
#include <netdb.h>
#include <netinet/in.h>
/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
* during the connect() call */
#define MINIUPNPC_IGNORE_EINTR
#ifndef USE_GETHOSTBYNAME
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#endif /* #ifndef USE_GETHOSTBYNAME */
#endif /* #else _WIN32 */
/* definition of PRINT_SOCKET_ERROR */
#ifdef _WIN32
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
#else
#define PRINT_SOCKET_ERROR(x) perror(x)
#endif
#if defined(__amigaos__) || defined(__amigaos4__)
#define herror(A) printf("%s\n", A)
#endif
#include "connecthostport.h"
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
/* connecthostport()
* return a socket connected (TCP) to the host and port
* or -1 in case of error */
int connecthostport(const char * host, unsigned short port,
unsigned int scope_id)
{
int s, n;
#ifdef USE_GETHOSTBYNAME
struct sockaddr_in dest;
struct hostent *hp;
#else /* #ifdef USE_GETHOSTBYNAME */
char tmp_host[MAXHOSTNAMELEN+1];
char port_str[8];
struct addrinfo *ai, *p;
struct addrinfo hints;
#endif /* #ifdef USE_GETHOSTBYNAME */
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
struct timeval timeout;
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
#ifdef USE_GETHOSTBYNAME
hp = gethostbyname(host);
if(hp == NULL)
{
herror(host);
return -1;
}
memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr));
memset(dest.sin_zero, 0, sizeof(dest.sin_zero));
s = socket(PF_INET, SOCK_STREAM, 0);
if(s < 0)
{
PRINT_SOCKET_ERROR("socket");
return -1;
}
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
/* setting a 3 seconds timeout for the connect() call */
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt");
}
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt");
}
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
dest.sin_family = AF_INET;
dest.sin_port = htons(port);
n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in));
#ifdef MINIUPNPC_IGNORE_EINTR
/* EINTR The system call was interrupted by a signal that was caught
* EINPROGRESS The socket is nonblocking and the connection cannot
* be completed immediately. */
while(n < 0 && (errno == EINTR || errno = EINPROGRESS))
{
socklen_t len;
fd_set wset;
int err;
FD_ZERO(&wset);
FD_SET(s, &wset);
if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR)
continue;
/*len = 0;*/
/*n = getpeername(s, NULL, &len);*/
len = sizeof(err);
if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
PRINT_SOCKET_ERROR("getsockopt");
closesocket(s);
return -1;
}
if(err != 0) {
errno = err;
n = -1;
}
}
#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */
if(n<0)
{
PRINT_SOCKET_ERROR("connect");
closesocket(s);
return -1;
}
#else /* #ifdef USE_GETHOSTBYNAME */
/* use getaddrinfo() instead of gethostbyname() */
memset(&hints, 0, sizeof(hints));
/* hints.ai_flags = AI_ADDRCONFIG; */
#ifdef AI_NUMERICSERV
hints.ai_flags = AI_NUMERICSERV;
#endif
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_UNSPEC; /* AF_INET, AF_INET6 or AF_UNSPEC */
/* hints.ai_protocol = IPPROTO_TCP; */
snprintf(port_str, sizeof(port_str), "%hu", port);
if(host[0] == '[')
{
/* literal ip v6 address */
int i, j;
for(i = 0, j = 1; host[j] && (host[j] != ']') && i < MAXHOSTNAMELEN; i++, j++)
{
tmp_host[i] = host[j];
if(0 == memcmp(host+j, "%25", 3)) /* %25 is just url encoding for '%' */
j+=2; /* skip "25" */
}
tmp_host[i] = '\0';
}
else
{
strncpy(tmp_host, host, MAXHOSTNAMELEN);
}
tmp_host[MAXHOSTNAMELEN] = '\0';
n = getaddrinfo(tmp_host, port_str, &hints, &ai);
if(n != 0)
{
#ifdef _WIN32
fprintf(stderr, "getaddrinfo() error : %d\n", n);
#else
fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n));
#endif
return -1;
}
s = -1;
for(p = ai; p; p = p->ai_next)
{
s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if(s < 0)
continue;
if(p->ai_addr->sa_family == AF_INET6 && scope_id > 0) {
struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *)p->ai_addr;
addr6->sin6_scope_id = scope_id;
}
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
/* setting a 3 seconds timeout for the connect() call */
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt");
}
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt");
}
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
n = connect(s, p->ai_addr, p->ai_addrlen);
#ifdef MINIUPNPC_IGNORE_EINTR
/* EINTR The system call was interrupted by a signal that was caught
* EINPROGRESS The socket is nonblocking and the connection cannot
* be completed immediately. */
while(n < 0 && (errno == EINTR || errno == EINPROGRESS))
{
socklen_t len;
fd_set wset;
int err;
FD_ZERO(&wset);
FD_SET(s, &wset);
if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR)
continue;
/*len = 0;*/
/*n = getpeername(s, NULL, &len);*/
len = sizeof(err);
if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
PRINT_SOCKET_ERROR("getsockopt");
closesocket(s);
freeaddrinfo(ai);
return -1;
}
if(err != 0) {
errno = err;
n = -1;
}
}
#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */
if(n < 0)
{
closesocket(s);
continue;
}
else
{
break;
}
}
freeaddrinfo(ai);
if(s < 0)
{
PRINT_SOCKET_ERROR("socket");
return -1;
}
if(n < 0)
{
PRINT_SOCKET_ERROR("connect");
return -1;
}
#endif /* #ifdef USE_GETHOSTBYNAME */
return s;
}

View File

@@ -1,18 +0,0 @@
/* $Id: connecthostport.h,v 1.3 2012/09/27 15:42:10 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/
* Author: Thomas Bernard
* Copyright (c) 2010-2012 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef CONNECTHOSTPORT_H_INCLUDED
#define CONNECTHOSTPORT_H_INCLUDED
/* connecthostport()
* return a socket connected (TCP) to the host and port
* or -1 in case of error */
int connecthostport(const char * host, unsigned short port,
unsigned int scope_id);
#endif

View File

@@ -1,21 +0,0 @@
#ifndef DECLSPEC_H_INCLUDED
#define DECLSPEC_H_INCLUDED
#if defined(_WIN32) && !defined(STATICLIB)
/* for windows dll */
#ifdef MINIUPNP_EXPORTS
#define LIBSPEC __declspec(dllexport)
#else
#define LIBSPEC __declspec(dllimport)
#endif
#else
#if defined(__GNUC__) && __GNUC__ >= 4
/* fix dynlib for OS X 10.9.2 and Apple LLVM version 5.0 */
#define LIBSPEC __attribute__ ((visibility ("default")))
#else
#define LIBSPEC
#endif
#endif
#endif

View File

@@ -1,125 +0,0 @@
/* $Id: igd_desc_parse.c,v 1.14 2011/04/11 09:19:24 nanard Exp $ */
/* Project : miniupnp
* http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2005-2010 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
#include "igd_desc_parse.h"
#include <stdio.h>
#include <string.h>
/* Start element handler :
* update nesting level counter and copy element name */
void IGDstartelt(void * d, const char * name, int l)
{
struct IGDdatas * datas = (struct IGDdatas *)d;
memcpy( datas->cureltname, name, l);
datas->cureltname[l] = '\0';
datas->level++;
if( (l==7) && !memcmp(name, "service", l) ) {
datas->tmp.controlurl[0] = '\0';
datas->tmp.eventsuburl[0] = '\0';
datas->tmp.scpdurl[0] = '\0';
datas->tmp.servicetype[0] = '\0';
}
}
/* End element handler :
* update nesting level counter and update parser state if
* service element is parsed */
void IGDendelt(void * d, const char * name, int l)
{
struct IGDdatas * datas = (struct IGDdatas *)d;
datas->level--;
/*printf("endelt %2d %.*s\n", datas->level, l, name);*/
if( (l==7) && !memcmp(name, "service", l) )
{
/*
if( datas->state < 1
&& !strcmp(datas->servicetype,
// "urn:schemas-upnp-org:service:WANIPConnection:1") )
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"))
datas->state ++;
*/
if(0==strcmp(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) {
memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service));
} else if(0==strcmp(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANIPv6FirewallControl:1")) {
memcpy(&datas->IPv6FC, &datas->tmp, sizeof(struct IGDdatas_service));
} else if(0==strcmp(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANIPConnection:1")
|| 0==strcmp(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANPPPConnection:1") ) {
if(datas->first.servicetype[0] == '\0') {
memcpy(&datas->first, &datas->tmp, sizeof(struct IGDdatas_service));
} else {
memcpy(&datas->second, &datas->tmp, sizeof(struct IGDdatas_service));
}
}
}
}
/* Data handler :
* copy data depending on the current element name and state */
void IGDdata(void * d, const char * data, int l)
{
struct IGDdatas * datas = (struct IGDdatas *)d;
char * dstmember = 0;
/*printf("%2d %s : %.*s\n",
datas->level, datas->cureltname, l, data); */
if( !strcmp(datas->cureltname, "URLBase") )
dstmember = datas->urlbase;
else if( !strcmp(datas->cureltname, "presentationURL") )
dstmember = datas->presentationurl;
else if( !strcmp(datas->cureltname, "serviceType") )
dstmember = datas->tmp.servicetype;
else if( !strcmp(datas->cureltname, "controlURL") )
dstmember = datas->tmp.controlurl;
else if( !strcmp(datas->cureltname, "eventSubURL") )
dstmember = datas->tmp.eventsuburl;
else if( !strcmp(datas->cureltname, "SCPDURL") )
dstmember = datas->tmp.scpdurl;
/* else if( !strcmp(datas->cureltname, "deviceType") )
dstmember = datas->devicetype_tmp;*/
if(dstmember)
{
if(l>=MINIUPNPC_URL_MAXSIZE)
l = MINIUPNPC_URL_MAXSIZE-1;
memcpy(dstmember, data, l);
dstmember[l] = '\0';
}
}
void printIGD(struct IGDdatas * d)
{
printf("urlbase = '%s'\n", d->urlbase);
printf("WAN Device (Common interface config) :\n");
/*printf(" deviceType = '%s'\n", d->CIF.devicetype);*/
printf(" serviceType = '%s'\n", d->CIF.servicetype);
printf(" controlURL = '%s'\n", d->CIF.controlurl);
printf(" eventSubURL = '%s'\n", d->CIF.eventsuburl);
printf(" SCPDURL = '%s'\n", d->CIF.scpdurl);
printf("primary WAN Connection Device (IP or PPP Connection):\n");
/*printf(" deviceType = '%s'\n", d->first.devicetype);*/
printf(" servicetype = '%s'\n", d->first.servicetype);
printf(" controlURL = '%s'\n", d->first.controlurl);
printf(" eventSubURL = '%s'\n", d->first.eventsuburl);
printf(" SCPDURL = '%s'\n", d->first.scpdurl);
printf("secondary WAN Connection Device (IP or PPP Connection):\n");
/*printf(" deviceType = '%s'\n", d->second.devicetype);*/
printf(" servicetype = '%s'\n", d->second.servicetype);
printf(" controlURL = '%s'\n", d->second.controlurl);
printf(" eventSubURL = '%s'\n", d->second.eventsuburl);
printf(" SCPDURL = '%s'\n", d->second.scpdurl);
printf("WAN IPv6 Firewall Control :\n");
/*printf(" deviceType = '%s'\n", d->IPv6FC.devicetype);*/
printf(" servicetype = '%s'\n", d->IPv6FC.servicetype);
printf(" controlURL = '%s'\n", d->IPv6FC.controlurl);
printf(" eventSubURL = '%s'\n", d->IPv6FC.eventsuburl);
printf(" SCPDURL = '%s'\n", d->IPv6FC.scpdurl);
}

View File

@@ -1,48 +0,0 @@
/* $Id: igd_desc_parse.h,v 1.11 2012/10/16 16:49:02 nanard Exp $ */
/* Project : miniupnp
* http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2005-2010 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#ifndef IGD_DESC_PARSE_H_INCLUDED
#define IGD_DESC_PARSE_H_INCLUDED
/* Structure to store the result of the parsing of UPnP
* descriptions of Internet Gateway Devices */
#define MINIUPNPC_URL_MAXSIZE (128)
struct IGDdatas_service {
char controlurl[MINIUPNPC_URL_MAXSIZE];
char eventsuburl[MINIUPNPC_URL_MAXSIZE];
char scpdurl[MINIUPNPC_URL_MAXSIZE];
char servicetype[MINIUPNPC_URL_MAXSIZE];
/*char devicetype[MINIUPNPC_URL_MAXSIZE];*/
};
struct IGDdatas {
char cureltname[MINIUPNPC_URL_MAXSIZE];
char urlbase[MINIUPNPC_URL_MAXSIZE];
char presentationurl[MINIUPNPC_URL_MAXSIZE];
int level;
/*int state;*/
/* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */
struct IGDdatas_service CIF;
/* "urn:schemas-upnp-org:service:WANIPConnection:1"
* "urn:schemas-upnp-org:service:WANPPPConnection:1" */
struct IGDdatas_service first;
/* if both WANIPConnection and WANPPPConnection are present */
struct IGDdatas_service second;
/* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */
struct IGDdatas_service IPv6FC;
/* tmp */
struct IGDdatas_service tmp;
};
void IGDstartelt(void *, const char *, int);
void IGDendelt(void *, const char *, int);
void IGDdata(void *, const char *, int);
void printIGD(struct IGDdatas *);
#endif

View File

@@ -1,121 +0,0 @@
/* $Id: minisoap.c,v 1.22 2012/01/21 13:30:31 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
*
* Minimal SOAP implementation for UPnP protocol.
*/
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
#include <io.h>
#include <winsock2.h>
#define snprintf _snprintf
#else
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#endif
#include "minisoap.h"
#include "miniupnpcstrings.h"
/* only for malloc */
#include <stdlib.h>
#ifdef _WIN32
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
#else
#define PRINT_SOCKET_ERROR(x) perror(x)
#endif
/* httpWrite sends the headers and the body to the socket
* and returns the number of bytes sent */
static int
httpWrite(int fd, const char * body, int bodysize,
const char * headers, int headerssize)
{
int n = 0;
/*n = write(fd, headers, headerssize);*/
/*if(bodysize>0)
n += write(fd, body, bodysize);*/
/* Note : my old linksys router only took into account
* soap request that are sent into only one packet */
char * p;
/* TODO: AVOID MALLOC */
p = malloc(headerssize+bodysize);
if(!p)
return 0;
memcpy(p, headers, headerssize);
memcpy(p+headerssize, body, bodysize);
/*n = write(fd, p, headerssize+bodysize);*/
n = send(fd, p, headerssize+bodysize, 0);
if(n<0) {
PRINT_SOCKET_ERROR("send");
}
/* disable send on the socket */
/* draytek routers dont seems to like that... */
#if 0
#ifdef _WIN32
if(shutdown(fd, SD_SEND)<0) {
#else
if(shutdown(fd, SHUT_WR)<0) { /*SD_SEND*/
#endif
PRINT_SOCKET_ERROR("shutdown");
}
#endif
free(p);
return n;
}
/* self explanatory */
int soapPostSubmit(int fd,
const char * url,
const char * host,
unsigned short port,
const char * action,
const char * body,
const char * httpversion)
{
int bodysize;
char headerbuf[512];
int headerssize;
char portstr[8];
bodysize = (int)strlen(body);
/* We are not using keep-alive HTTP connections.
* HTTP/1.1 needs the header Connection: close to do that.
* This is the default with HTTP/1.0
* Using HTTP/1.1 means we need to support chunked transfer-encoding :
* When using HTTP/1.1, the router "BiPAC 7404VNOX" always use chunked
* transfer encoding. */
/* Connection: Close is normally there only in HTTP/1.1 but who knows */
portstr[0] = '\0';
if(port != 80)
snprintf(portstr, sizeof(portstr), ":%hu", port);
headerssize = snprintf(headerbuf, sizeof(headerbuf),
"POST %s HTTP/%s\r\n"
"Host: %s%s\r\n"
"User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
"Content-Length: %d\r\n"
"Content-Type: text/xml\r\n"
"SOAPAction: \"%s\"\r\n"
"Connection: Close\r\n"
"Cache-Control: no-cache\r\n" /* ??? */
"Pragma: no-cache\r\n"
"\r\n",
url, httpversion, host, portstr, bodysize, action);
#ifdef DEBUG
/*printf("SOAP request : headersize=%d bodysize=%d\n",
headerssize, bodysize);
*/
printf("SOAP request : POST %s HTTP/%s - Host: %s%s\n",
url, httpversion, host, portstr);
printf("SOAPAction: \"%s\" - Content-Length: %d\n", action, bodysize);
printf("Headers :\n%s", headerbuf);
printf("Body :\n%s\n", body);
#endif
return httpWrite(fd, body, bodysize, headerbuf, headerssize);
}

View File

@@ -1,15 +0,0 @@
/* $Id: minisoap.h,v 1.5 2012/09/27 15:42:10 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
#ifndef MINISOAP_H_INCLUDED
#define MINISOAP_H_INCLUDED
/*int httpWrite(int, const char *, int, const char *);*/
int soapPostSubmit(int, const char *, const char *, unsigned short,
const char *, const char *, const char *);
#endif

View File

@@ -1,133 +0,0 @@
/* $Id: minissdpc.c,v 1.16 2012/03/05 19:42:46 nanard Exp $ */
/* Project : miniupnp
* Web : http://miniupnp.free.fr/
* Author : Thomas BERNARD
* copyright (c) 2005-2012 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
/*#include <syslog.h>*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#include <winsock.h>
#include <stdint.h>
#endif
#if defined(__amigaos__) || defined(__amigaos4__)
#include <sys/socket.h>
#endif
#if defined(__amigaos__)
#define uint16_t unsigned short
#endif
/* Hack */
#define UNIX_PATH_LEN 108
struct sockaddr_un {
uint16_t sun_family;
char sun_path[UNIX_PATH_LEN];
};
#else
#include <sys/socket.h>
#include <sys/un.h>
#endif
#include "minissdpc.h"
#include "miniupnpc.h"
#include "codelength.h"
struct UPNPDev *
getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath)
{
struct UPNPDev * tmp;
struct UPNPDev * devlist = NULL;
unsigned char buffer[2048];
ssize_t n;
unsigned char * p;
unsigned char * url;
unsigned int i;
unsigned int urlsize, stsize, usnsize, l;
int s;
struct sockaddr_un addr;
s = socket(AF_UNIX, SOCK_STREAM, 0);
if(s < 0)
{
/*syslog(LOG_ERR, "socket(unix): %m");*/
perror("socket(unix)");
return NULL;
}
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path));
/* TODO : check if we need to handle the EINTR */
if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
{
/*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath);*/
close(s);
return NULL;
}
stsize = strlen(devtype);
buffer[0] = 1; /* request type 1 : request devices/services by type */
p = buffer + 1;
l = stsize; CODELENGTH(l, p);
if(p + stsize > buffer + sizeof(buffer))
{
/* devtype is too long ! */
close(s);
return NULL;
}
memcpy(p, devtype, stsize);
p += stsize;
if(write(s, buffer, p - buffer) < 0)
{
/*syslog(LOG_ERR, "write(): %m");*/
perror("minissdpc.c: write()");
close(s);
return NULL;
}
n = read(s, buffer, sizeof(buffer));
if(n<=0)
{
perror("minissdpc.c: read()");
close(s);
return NULL;
}
p = buffer + 1;
for(i = 0; i < buffer[0]; i++)
{
if(p+2>=buffer+sizeof(buffer))
break;
DECODELENGTH(urlsize, p);
if(p+urlsize+2>=buffer+sizeof(buffer))
break;
url = p;
p += urlsize;
DECODELENGTH(stsize, p);
if(p+stsize+2>=buffer+sizeof(buffer))
break;
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize);
tmp->pNext = devlist;
tmp->descURL = tmp->buffer;
tmp->st = tmp->buffer + 1 + urlsize;
memcpy(tmp->buffer, url, urlsize);
tmp->buffer[urlsize] = '\0';
memcpy(tmp->buffer + urlsize + 1, p, stsize);
p += stsize;
tmp->buffer[urlsize+1+stsize] = '\0';
devlist = tmp;
/* added for compatibility with recent versions of MiniSSDPd
* >= 2007/12/19 */
DECODELENGTH(usnsize, p);
p += usnsize;
if(p>buffer + sizeof(buffer))
break;
}
close(s);
return devlist;
}

View File

@@ -1,15 +0,0 @@
/* $Id: minissdpc.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author: Thomas Bernard
* Copyright (c) 2005-2007 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef MINISSDPC_H_INCLUDED
#define MINISSDPC_H_INCLUDED
struct UPNPDev *
getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,130 +0,0 @@
/* $Id: miniupnpc.h,v 1.35 2014/01/31 13:26:34 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/
* Author: Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef MINIUPNPC_H_INCLUDED
#define MINIUPNPC_H_INCLUDED
#include "declspec.h"
#include "igd_desc_parse.h"
/* error codes : */
#define UPNPDISCOVER_SUCCESS (0)
#define UPNPDISCOVER_UNKNOWN_ERROR (-1)
#define UPNPDISCOVER_SOCKET_ERROR (-101)
#define UPNPDISCOVER_MEMORY_ERROR (-102)
/* versions : */
#define MINIUPNPC_VERSION "1.9.20140401"
#define MINIUPNPC_API_VERSION 10
#ifdef __cplusplus
extern "C" {
#endif
/* Structures definitions : */
struct UPNParg { const char * elt; const char * val; };
char *
simpleUPnPcommand(int, const char *, const char *,
const char *, struct UPNParg *,
int *);
struct UPNPDev {
struct UPNPDev * pNext;
char * descURL;
char * st;
unsigned int scope_id;
char buffer[2];
};
/* upnpDiscover()
* discover UPnP devices on the network.
* The discovered devices are returned as a chained list.
* It is up to the caller to free the list with freeUPNPDevlist().
* delay (in millisecond) is the maximum time for waiting any device
* response.
* If available, device list will be obtained from MiniSSDPd.
* Default path for minissdpd socket will be used if minissdpdsock argument
* is NULL.
* If multicastif is not NULL, it will be used instead of the default
* multicast interface for sending SSDP discover packets.
* If sameport is not null, SSDP packets will be sent from the source port
* 1900 (same as destination port) otherwise system assign a source port. */
LIBSPEC struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock, int sameport,
int ipv6,
int * error);
/* freeUPNPDevlist()
* free list returned by upnpDiscover() */
LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist);
/* parserootdesc() :
* parse root XML description of a UPnP device and fill the IGDdatas
* structure. */
LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *);
/* structure used to get fast access to urls
* controlURL: controlURL of the WANIPConnection
* ipcondescURL: url of the description of the WANIPConnection
* controlURL_CIF: controlURL of the WANCommonInterfaceConfig
* controlURL_6FC: controlURL of the WANIPv6FirewallControl
*/
struct UPNPUrls {
char * controlURL;
char * ipcondescURL;
char * controlURL_CIF;
char * controlURL_6FC;
char * rootdescURL;
};
/* UPNP_GetValidIGD() :
* return values :
* 0 = NO IGD found
* 1 = A valid connected IGD has been found
* 2 = A valid IGD has been found but it reported as
* not connected
* 3 = an UPnP device has been found but was not recognized as an IGD
*
* In any non zero return case, the urls and data structures
* passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
* free allocated memory.
*/
LIBSPEC int
UPNP_GetValidIGD(struct UPNPDev * devlist,
struct UPNPUrls * urls,
struct IGDdatas * data,
char * lanaddr, int lanaddrlen);
/* UPNP_GetIGDFromUrl()
* Used when skipping the discovery process.
* return value :
* 0 - Not ok
* 1 - OK */
LIBSPEC int
UPNP_GetIGDFromUrl(const char * rootdescurl,
struct UPNPUrls * urls,
struct IGDdatas * data,
char * lanaddr, int lanaddrlen);
LIBSPEC void
GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *,
const char *, unsigned int);
LIBSPEC void
FreeUPNPUrls(struct UPNPUrls *);
/* return 0 or 1 */
LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,15 +0,0 @@
/* $Id: miniupnpcstrings.h.in,v 1.5 2012/10/16 16:48:26 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author: Thomas Bernard
* Copyright (c) 2005-2011 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef MINIUPNPCSTRINGS_H_INCLUDED
#define MINIUPNPCSTRINGS_H_INCLUDED
#define OS_STRING "OS/version"
#define MINIUPNPC_VERSION_STRING "version"
#endif

View File

@@ -1,19 +0,0 @@
/* $Id: miniupnpctypes.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */
/* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org
* Author : Thomas Bernard
* Copyright (c) 2011 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided within this distribution */
#ifndef MINIUPNPCTYPES_H_INCLUDED
#define MINIUPNPCTYPES_H_INCLUDED
#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
#define UNSIGNED_INTEGER unsigned long long
#define STRTOUI strtoull
#else
#define UNSIGNED_INTEGER unsigned int
#define STRTOUI strtoul
#endif
#endif

View File

@@ -1,575 +0,0 @@
/* $Id: miniwget.c,v 1.61 2014/02/05 17:27:48 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2005-2014 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#define MAXHOSTNAMELEN 64
#define MIN(x,y) (((x)<(y))?(x):(y))
#define snprintf _snprintf
#define socklen_t int
#ifndef strncasecmp
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#define strncasecmp _memicmp
#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
#define strncasecmp memicmp
#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
#endif /* #ifndef strncasecmp */
#else /* #ifdef _WIN32 */
#include <unistd.h>
#include <sys/param.h>
#if defined(__amigaos__) && !defined(__amigaos4__)
#define socklen_t int
#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */
#include <sys/select.h>
#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netdb.h>
#define closesocket close
#endif /* #else _WIN32 */
#if defined(__sun) || defined(sun)
#define MIN(x,y) (((x)<(y))?(x):(y))
#endif
#include "miniupnpcstrings.h"
#include "miniwget.h"
#include "connecthostport.h"
#include "receivedata.h"
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
/*
* Read a HTTP response from a socket.
* Process Content-Length and Transfer-encoding headers.
* return a pointer to the content buffer, which length is saved
* to the length parameter.
*/
void *
getHTTPResponse(int s, int * size)
{
char buf[2048];
int n;
int endofheaders = 0;
int chunked = 0;
int content_length = -1;
unsigned int chunksize = 0;
unsigned int bytestocopy = 0;
/* buffers : */
char * header_buf;
unsigned int header_buf_len = 2048;
unsigned int header_buf_used = 0;
char * content_buf;
unsigned int content_buf_len = 2048;
unsigned int content_buf_used = 0;
char chunksize_buf[32];
unsigned int chunksize_buf_index;
header_buf = malloc(header_buf_len);
content_buf = malloc(content_buf_len);
chunksize_buf[0] = '\0';
chunksize_buf_index = 0;
while((n = receivedata(s, buf, 2048, 5000, NULL)) > 0)
{
if(endofheaders == 0)
{
int i;
int linestart=0;
int colon=0;
int valuestart=0;
if(header_buf_used + n > header_buf_len) {
header_buf = realloc(header_buf, header_buf_used + n);
header_buf_len = header_buf_used + n;
}
memcpy(header_buf + header_buf_used, buf, n);
header_buf_used += n;
/* search for CR LF CR LF (end of headers)
* recognize also LF LF */
i = 0;
while(i < ((int)header_buf_used-1) && (endofheaders == 0)) {
if(header_buf[i] == '\r') {
i++;
if(header_buf[i] == '\n') {
i++;
if(i < (int)header_buf_used && header_buf[i] == '\r') {
i++;
if(i < (int)header_buf_used && header_buf[i] == '\n') {
endofheaders = i+1;
}
}
}
} else if(header_buf[i] == '\n') {
i++;
if(header_buf[i] == '\n') {
endofheaders = i+1;
}
}
i++;
}
if(endofheaders == 0)
continue;
/* parse header lines */
for(i = 0; i < endofheaders - 1; i++) {
if(colon <= linestart && header_buf[i]==':')
{
colon = i;
while(i < (endofheaders-1)
&& (header_buf[i+1] == ' ' || header_buf[i+1] == '\t'))
i++;
valuestart = i + 1;
}
/* detecting end of line */
else if(header_buf[i]=='\r' || header_buf[i]=='\n')
{
if(colon > linestart && valuestart > colon)
{
#ifdef DEBUG
printf("header='%.*s', value='%.*s'\n",
colon-linestart, header_buf+linestart,
i-valuestart, header_buf+valuestart);
#endif
if(0==strncasecmp(header_buf+linestart, "content-length", colon-linestart))
{
content_length = atoi(header_buf+valuestart);
#ifdef DEBUG
printf("Content-Length: %d\n", content_length);
#endif
}
else if(0==strncasecmp(header_buf+linestart, "transfer-encoding", colon-linestart)
&& 0==strncasecmp(header_buf+valuestart, "chunked", 7))
{
#ifdef DEBUG
printf("chunked transfer-encoding!\n");
#endif
chunked = 1;
}
}
while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n'))
i++;
linestart = i;
colon = linestart;
valuestart = 0;
}
}
/* copy the remaining of the received data back to buf */
n = header_buf_used - endofheaders;
memcpy(buf, header_buf + endofheaders, n);
/* if(headers) */
}
if(endofheaders)
{
/* content */
if(chunked)
{
int i = 0;
while(i < n)
{
if(chunksize == 0)
{
/* reading chunk size */
if(chunksize_buf_index == 0) {
/* skipping any leading CR LF */
if(i<n && buf[i] == '\r') i++;
if(i<n && buf[i] == '\n') i++;
}
while(i<n && isxdigit(buf[i])
&& chunksize_buf_index < (sizeof(chunksize_buf)-1))
{
chunksize_buf[chunksize_buf_index++] = buf[i];
chunksize_buf[chunksize_buf_index] = '\0';
i++;
}
while(i<n && buf[i] != '\r' && buf[i] != '\n')
i++; /* discarding chunk-extension */
if(i<n && buf[i] == '\r') i++;
if(i<n && buf[i] == '\n') {
unsigned int j;
for(j = 0; j < chunksize_buf_index; j++) {
if(chunksize_buf[j] >= '0'
&& chunksize_buf[j] <= '9')
chunksize = (chunksize << 4) + (chunksize_buf[j] - '0');
else
chunksize = (chunksize << 4) + ((chunksize_buf[j] | 32) - 'a' + 10);
}
chunksize_buf[0] = '\0';
chunksize_buf_index = 0;
i++;
} else {
/* not finished to get chunksize */
continue;
}
#ifdef DEBUG
printf("chunksize = %u (%x)\n", chunksize, chunksize);
#endif
if(chunksize == 0)
{
#ifdef DEBUG
printf("end of HTTP content - %d %d\n", i, n);
/*printf("'%.*s'\n", n-i, buf+i);*/
#endif
goto end_of_stream;
}
}
bytestocopy = ((int)chunksize < (n - i))?chunksize:(unsigned int)(n - i);
if((content_buf_used + bytestocopy) > content_buf_len)
{
if(content_length >= (int)(content_buf_used + bytestocopy)) {
content_buf_len = content_length;
} else {
content_buf_len = content_buf_used + bytestocopy;
}
content_buf = (char *)realloc((void *)content_buf,
content_buf_len);
}
memcpy(content_buf + content_buf_used, buf + i, bytestocopy);
content_buf_used += bytestocopy;
i += bytestocopy;
chunksize -= bytestocopy;
}
}
else
{
/* not chunked */
if(content_length > 0
&& (int)(content_buf_used + n) > content_length) {
/* skipping additional bytes */
n = content_length - content_buf_used;
}
if(content_buf_used + n > content_buf_len)
{
if(content_length >= (int)(content_buf_used + n)) {
content_buf_len = content_length;
} else {
content_buf_len = content_buf_used + n;
}
content_buf = (char *)realloc((void *)content_buf,
content_buf_len);
}
memcpy(content_buf + content_buf_used, buf, n);
content_buf_used += n;
}
}
/* use the Content-Length header value if available */
if(content_length > 0 && (int)content_buf_used >= content_length)
{
#ifdef DEBUG
printf("End of HTTP content\n");
#endif
break;
}
}
end_of_stream:
free(header_buf); header_buf = NULL;
*size = content_buf_used;
if(content_buf_used == 0)
{
free(content_buf);
content_buf = NULL;
}
return content_buf;
}
/* miniwget3() :
* do all the work.
* Return NULL if something failed. */
static void *
miniwget3(const char * host,
unsigned short port, const char * path,
int * size, char * addr_str, int addr_str_len,
const char * httpversion, unsigned int scope_id)
{
char buf[2048];
int s;
int n;
int len;
int sent;
void * content;
*size = 0;
s = connecthostport(host, port, scope_id);
if(s < 0)
return NULL;
/* get address for caller ! */
if(addr_str)
{
struct sockaddr_storage saddr;
socklen_t saddrlen;
saddrlen = sizeof(saddr);
if(getsockname(s, (struct sockaddr *)&saddr, &saddrlen) < 0)
{
perror("getsockname");
}
else
{
#if defined(__amigaos__) && !defined(__amigaos4__)
/* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD);
* But his function make a string with the port : nn.nn.nn.nn:port */
/* if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr),
NULL, addr_str, (DWORD *)&addr_str_len))
{
printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError());
}*/
/* the following code is only compatible with ip v4 addresses */
strncpy(addr_str, inet_ntoa(((struct sockaddr_in *)&saddr)->sin_addr), addr_str_len);
#else
#if 0
if(saddr.sa_family == AF_INET6) {
inet_ntop(AF_INET6,
&(((struct sockaddr_in6 *)&saddr)->sin6_addr),
addr_str, addr_str_len);
} else {
inet_ntop(AF_INET,
&(((struct sockaddr_in *)&saddr)->sin_addr),
addr_str, addr_str_len);
}
#endif
/* getnameinfo return ip v6 address with the scope identifier
* such as : 2a01:e35:8b2b:7330::%4281128194 */
n = getnameinfo((const struct sockaddr *)&saddr, saddrlen,
addr_str, addr_str_len,
NULL, 0,
NI_NUMERICHOST | NI_NUMERICSERV);
if(n != 0) {
#ifdef _WIN32
fprintf(stderr, "getnameinfo() failed : %d\n", n);
#else
fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n));
#endif
}
#endif
}
#ifdef DEBUG
printf("address miniwget : %s\n", addr_str);
#endif
}
len = snprintf(buf, sizeof(buf),
"GET %s HTTP/%s\r\n"
"Host: %s:%d\r\n"
"Connection: Close\r\n"
"User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
"\r\n",
path, httpversion, host, port);
sent = 0;
/* sending the HTTP request */
while(sent < len)
{
n = send(s, buf+sent, len-sent, 0);
if(n < 0)
{
perror("send");
closesocket(s);
return NULL;
}
else
{
sent += n;
}
}
content = getHTTPResponse(s, size);
closesocket(s);
return content;
}
/* miniwget2() :
* Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */
static void *
miniwget2(const char * host,
unsigned short port, const char * path,
int * size, char * addr_str, int addr_str_len,
unsigned int scope_id)
{
char * respbuffer;
#if 1
respbuffer = miniwget3(host, port, path, size,
addr_str, addr_str_len, "1.1", scope_id);
#else
respbuffer = miniwget3(host, port, path, size,
addr_str, addr_str_len, "1.0", scope_id);
if (*size == 0)
{
#ifdef DEBUG
printf("Retrying with HTTP/1.1\n");
#endif
free(respbuffer);
respbuffer = miniwget3(host, port, path, size,
addr_str, addr_str_len, "1.1", scope_id);
}
#endif
return respbuffer;
}
/* parseURL()
* arguments :
* url : source string not modified
* hostname : hostname destination string (size of MAXHOSTNAMELEN+1)
* port : port (destination)
* path : pointer to the path part of the URL
*
* Return values :
* 0 - Failure
* 1 - Success */
int
parseURL(const char * url,
char * hostname, unsigned short * port,
char * * path, unsigned int * scope_id)
{
char * p1, *p2, *p3;
if(!url)
return 0;
p1 = strstr(url, "://");
if(!p1)
return 0;
p1 += 3;
if( (url[0]!='h') || (url[1]!='t')
||(url[2]!='t') || (url[3]!='p'))
return 0;
memset(hostname, 0, MAXHOSTNAMELEN + 1);
if(*p1 == '[')
{
/* IP v6 : http://[2a00:1450:8002::6a]/path/abc */
char * scope;
scope = strchr(p1, '%');
p2 = strchr(p1, ']');
if(p2 && scope && scope < p2 && scope_id) {
/* parse scope */
#ifdef IF_NAMESIZE
char tmp[IF_NAMESIZE];
int l;
scope++;
/* "%25" is just '%' in URL encoding */
if(scope[0] == '2' && scope[1] == '5')
scope += 2; /* skip "25" */
l = p2 - scope;
if(l >= IF_NAMESIZE)
l = IF_NAMESIZE - 1;
memcpy(tmp, scope, l);
tmp[l] = '\0';
*scope_id = if_nametoindex(tmp);
if(*scope_id == 0) {
*scope_id = (unsigned int)strtoul(tmp, NULL, 10);
}
#else
/* under windows, scope is numerical */
char tmp[8];
int l;
scope++;
/* "%25" is just '%' in URL encoding */
if(scope[0] == '2' && scope[1] == '5')
scope += 2; /* skip "25" */
l = p2 - scope;
if(l >= sizeof(tmp))
l = sizeof(tmp) - 1;
memcpy(tmp, scope, l);
tmp[l] = '\0';
*scope_id = (unsigned int)strtoul(tmp, NULL, 10);
#endif
}
p3 = strchr(p1, '/');
if(p2 && p3)
{
p2++;
strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1)));
if(*p2 == ':')
{
*port = 0;
p2++;
while( (*p2 >= '0') && (*p2 <= '9'))
{
*port *= 10;
*port += (unsigned short)(*p2 - '0');
p2++;
}
}
else
{
*port = 80;
}
*path = p3;
return 1;
}
}
p2 = strchr(p1, ':');
p3 = strchr(p1, '/');
if(!p3)
return 0;
if(!p2 || (p2>p3))
{
strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1)));
*port = 80;
}
else
{
strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1)));
*port = 0;
p2++;
while( (*p2 >= '0') && (*p2 <= '9'))
{
*port *= 10;
*port += (unsigned short)(*p2 - '0');
p2++;
}
}
*path = p3;
return 1;
}
void *
miniwget(const char * url, int * size, unsigned int scope_id)
{
unsigned short port;
char * path;
/* protocol://host:port/chemin */
char hostname[MAXHOSTNAMELEN+1];
*size = 0;
if(!parseURL(url, hostname, &port, &path, &scope_id))
return NULL;
#ifdef DEBUG
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
hostname, port, path, scope_id);
#endif
return miniwget2(hostname, port, path, size, 0, 0, scope_id);
}
void *
miniwget_getaddr(const char * url, int * size,
char * addr, int addrlen, unsigned int scope_id)
{
unsigned short port;
char * path;
/* protocol://host:port/path */
char hostname[MAXHOSTNAMELEN+1];
*size = 0;
if(addr)
addr[0] = '\0';
if(!parseURL(url, hostname, &port, &path, &scope_id))
return NULL;
#ifdef DEBUG
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
hostname, port, path, scope_id);
#endif
return miniwget2(hostname, port, path, size, addr, addrlen, scope_id);
}

View File

@@ -1,30 +0,0 @@
/* $Id: miniwget.h,v 1.8 2012/09/27 15:42:10 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#ifndef MINIWGET_H_INCLUDED
#define MINIWGET_H_INCLUDED
#include "declspec.h"
#ifdef __cplusplus
extern "C" {
#endif
LIBSPEC void * getHTTPResponse(int s, int * size);
LIBSPEC void * miniwget(const char *, int *, unsigned int);
LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int);
int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,229 +0,0 @@
/* $Id: minixml.c,v 1.11 2014/02/03 15:54:12 nanard Exp $ */
/* minixml.c : the minimum size a xml parser can be ! */
/* Project : miniupnp
* webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author : Thomas Bernard
Copyright (c) 2005-2014, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include "minixml.h"
/* parseatt : used to parse the argument list
* return 0 (false) in case of success and -1 (true) if the end
* of the xmlbuffer is reached. */
static int parseatt(struct xmlparser * p)
{
const char * attname;
int attnamelen;
const char * attvalue;
int attvaluelen;
while(p->xml < p->xmlend)
{
if(*p->xml=='/' || *p->xml=='>')
return 0;
if( !IS_WHITE_SPACE(*p->xml) )
{
char sep;
attname = p->xml;
attnamelen = 0;
while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) )
{
attnamelen++; p->xml++;
if(p->xml >= p->xmlend)
return -1;
}
while(*(p->xml++) != '=')
{
if(p->xml >= p->xmlend)
return -1;
}
while(IS_WHITE_SPACE(*p->xml))
{
p->xml++;
if(p->xml >= p->xmlend)
return -1;
}
sep = *p->xml;
if(sep=='\'' || sep=='\"')
{
p->xml++;
if(p->xml >= p->xmlend)
return -1;
attvalue = p->xml;
attvaluelen = 0;
while(*p->xml != sep)
{
attvaluelen++; p->xml++;
if(p->xml >= p->xmlend)
return -1;
}
}
else
{
attvalue = p->xml;
attvaluelen = 0;
while( !IS_WHITE_SPACE(*p->xml)
&& *p->xml != '>' && *p->xml != '/')
{
attvaluelen++; p->xml++;
if(p->xml >= p->xmlend)
return -1;
}
}
/*printf("%.*s='%.*s'\n",
attnamelen, attname, attvaluelen, attvalue);*/
if(p->attfunc)
p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen);
}
p->xml++;
}
return -1;
}
/* parseelt parse the xml stream and
* call the callback functions when needed... */
static void parseelt(struct xmlparser * p)
{
int i;
const char * elementname;
while(p->xml < (p->xmlend - 1))
{
if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "<!--", 4)))
{
p->xml += 3;
/* ignore comments */
do
{
p->xml++;
if ((p->xml + 3) >= p->xmlend)
return;
}
while(memcmp(p->xml, "-->", 3) != 0);
p->xml += 3;
}
else if((p->xml)[0]=='<' && (p->xml)[1]!='?')
{
i = 0; elementname = ++p->xml;
while( !IS_WHITE_SPACE(*p->xml)
&& (*p->xml!='>') && (*p->xml!='/')
)
{
i++; p->xml++;
if (p->xml >= p->xmlend)
return;
/* to ignore namespace : */
if(*p->xml==':')
{
i = 0;
elementname = ++p->xml;
}
}
if(i>0)
{
if(p->starteltfunc)
p->starteltfunc(p->data, elementname, i);
if(parseatt(p))
return;
if(*p->xml!='/')
{
const char * data;
i = 0; data = ++p->xml;
if (p->xml >= p->xmlend)
return;
while( IS_WHITE_SPACE(*p->xml) )
{
i++; p->xml++;
if (p->xml >= p->xmlend)
return;
}
if(memcmp(p->xml, "<![CDATA[", 9) == 0)
{
/* CDATA handling */
p->xml += 9;
data = p->xml;
i = 0;
while(memcmp(p->xml, "]]>", 3) != 0)
{
i++; p->xml++;
if ((p->xml + 3) >= p->xmlend)
return;
}
if(i>0 && p->datafunc)
p->datafunc(p->data, data, i);
while(*p->xml!='<')
{
p->xml++;
if (p->xml >= p->xmlend)
return;
}
}
else
{
while(*p->xml!='<')
{
i++; p->xml++;
if ((p->xml + 1) >= p->xmlend)
return;
}
if(i>0 && p->datafunc && *(p->xml + 1) == '/')
p->datafunc(p->data, data, i);
}
}
}
else if(*p->xml == '/')
{
i = 0; elementname = ++p->xml;
if (p->xml >= p->xmlend)
return;
while((*p->xml != '>'))
{
i++; p->xml++;
if (p->xml >= p->xmlend)
return;
}
if(p->endeltfunc)
p->endeltfunc(p->data, elementname, i);
p->xml++;
}
}
else
{
p->xml++;
}
}
}
/* the parser must be initialized before calling this function */
void parsexml(struct xmlparser * parser)
{
parser->xml = parser->xmlstart;
parser->xmlend = parser->xmlstart + parser->xmlsize;
parseelt(parser);
}

View File

@@ -1,37 +0,0 @@
/* $Id: minixml.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */
/* minimal xml parser
*
* Project : miniupnp
* Website : http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2005 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#ifndef MINIXML_H_INCLUDED
#define MINIXML_H_INCLUDED
#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n'))
/* if a callback function pointer is set to NULL,
* the function is not called */
struct xmlparser {
const char *xmlstart;
const char *xmlend;
const char *xml; /* pointer to current character */
int xmlsize;
void * data;
void (*starteltfunc) (void *, const char *, int);
void (*endeltfunc) (void *, const char *, int);
void (*datafunc) (void *, const char *, int);
void (*attfunc) (void *, const char *, int, const char *, int);
};
/* parsexml()
* the xmlparser structure must be initialized before the call
* the following structure members have to be initialized :
* xmlstart, xmlsize, data, *func
* xml is for internal usage, xmlend is computed automatically */
void parsexml(struct xmlparser *);
#endif

View File

@@ -1,159 +0,0 @@
/* $Id: portlistingparse.c,v 1.6 2012/05/29 10:26:51 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2011 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <string.h>
#include <stdlib.h>
#include "portlistingparse.h"
#include "minixml.h"
/* list of the elements */
static const struct {
const portMappingElt code;
const char * const str;
} elements[] = {
{ PortMappingEntry, "PortMappingEntry"},
{ NewRemoteHost, "NewRemoteHost"},
{ NewExternalPort, "NewExternalPort"},
{ NewProtocol, "NewProtocol"},
{ NewInternalPort, "NewInternalPort"},
{ NewInternalClient, "NewInternalClient"},
{ NewEnabled, "NewEnabled"},
{ NewDescription, "NewDescription"},
{ NewLeaseTime, "NewLeaseTime"},
{ PortMappingEltNone, NULL}
};
/* Helper function */
static UNSIGNED_INTEGER
atoui(const char * p, int l)
{
UNSIGNED_INTEGER r = 0;
while(l > 0 && *p)
{
if(*p >= '0' && *p <= '9')
r = r*10 + (*p - '0');
else
break;
p++;
l--;
}
return r;
}
/* Start element handler */
static void
startelt(void * d, const char * name, int l)
{
int i;
struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
pdata->curelt = PortMappingEltNone;
for(i = 0; elements[i].str; i++)
{
if(memcmp(name, elements[i].str, l) == 0)
{
pdata->curelt = elements[i].code;
break;
}
}
if(pdata->curelt == PortMappingEntry)
{
struct PortMapping * pm;
pm = calloc(1, sizeof(struct PortMapping));
LIST_INSERT_HEAD( &(pdata->head), pm, entries);
}
}
/* End element handler */
static void
endelt(void * d, const char * name, int l)
{
struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
(void)name;
(void)l;
pdata->curelt = PortMappingEltNone;
}
/* Data handler */
static void
data(void * d, const char * data, int l)
{
struct PortMapping * pm;
struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
pm = pdata->head.lh_first;
if(!pm)
return;
if(l > 63)
l = 63;
switch(pdata->curelt)
{
case NewRemoteHost:
memcpy(pm->remoteHost, data, l);
pm->remoteHost[l] = '\0';
break;
case NewExternalPort:
pm->externalPort = (unsigned short)atoui(data, l);
break;
case NewProtocol:
if(l > 3)
l = 3;
memcpy(pm->protocol, data, l);
pm->protocol[l] = '\0';
break;
case NewInternalPort:
pm->internalPort = (unsigned short)atoui(data, l);
break;
case NewInternalClient:
memcpy(pm->internalClient, data, l);
pm->internalClient[l] = '\0';
break;
case NewEnabled:
pm->enabled = (unsigned char)atoui(data, l);
break;
case NewDescription:
memcpy(pm->description, data, l);
pm->description[l] = '\0';
break;
case NewLeaseTime:
pm->leaseTime = atoui(data, l);
break;
default:
break;
}
}
/* Parse the PortMappingList XML document for IGD version 2
*/
void
ParsePortListing(const char * buffer, int bufsize,
struct PortMappingParserData * pdata)
{
struct xmlparser parser;
memset(pdata, 0, sizeof(struct PortMappingParserData));
LIST_INIT(&(pdata->head));
/* init xmlparser */
parser.xmlstart = buffer;
parser.xmlsize = bufsize;
parser.data = pdata;
parser.starteltfunc = startelt;
parser.endeltfunc = endelt;
parser.datafunc = data;
parser.attfunc = 0;
parsexml(&parser);
}
void
FreePortListing(struct PortMappingParserData * pdata)
{
struct PortMapping * pm;
while((pm = pdata->head.lh_first) != NULL)
{
LIST_REMOVE(pm, entries);
free(pm);
}
}

View File

@@ -1,71 +0,0 @@
/* $Id: portlistingparse.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2011-2012 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#ifndef PORTLISTINGPARSE_H_INCLUDED
#define PORTLISTINGPARSE_H_INCLUDED
#include "declspec.h"
/* for the definition of UNSIGNED_INTEGER */
#include "miniupnpctypes.h"
#if defined(NO_SYS_QUEUE_H) || defined(_WIN32) || defined(__HAIKU__)
#include "bsdqueue.h"
#else
#include <sys/queue.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* sample of PortMappingEntry :
<p:PortMappingEntry>
<p:NewRemoteHost>202.233.2.1</p:NewRemoteHost>
<p:NewExternalPort>2345</p:NewExternalPort>
<p:NewProtocol>TCP</p:NewProtocol>
<p:NewInternalPort>2345</p:NewInternalPort>
<p:NewInternalClient>192.168.1.137</p:NewInternalClient>
<p:NewEnabled>1</p:NewEnabled>
<p:NewDescription>dooom</p:NewDescription>
<p:NewLeaseTime>345</p:NewLeaseTime>
</p:PortMappingEntry>
*/
typedef enum { PortMappingEltNone,
PortMappingEntry, NewRemoteHost,
NewExternalPort, NewProtocol,
NewInternalPort, NewInternalClient,
NewEnabled, NewDescription,
NewLeaseTime } portMappingElt;
struct PortMapping {
LIST_ENTRY(PortMapping) entries;
UNSIGNED_INTEGER leaseTime;
unsigned short externalPort;
unsigned short internalPort;
char remoteHost[64];
char internalClient[64];
char description[64];
char protocol[4];
unsigned char enabled;
};
struct PortMappingParserData {
LIST_HEAD(portmappinglisthead, PortMapping) head;
portMappingElt curelt;
};
LIBSPEC void
ParsePortListing(const char * buffer, int bufsize,
struct PortMappingParserData * pdata);
LIBSPEC void
FreePortListing(struct PortMappingParserData * pdata);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,109 +0,0 @@
/* $Id: receivedata.c,v 1.5 2013/10/07 09:48:36 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2011-2012 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
#include <stdio.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <unistd.h>
#if defined(__amigaos__) && !defined(__amigaos4__)
#define socklen_t int
#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */
#include <sys/select.h>
#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */
#include <sys/socket.h>
#include <netinet/in.h>
#if !defined(__amigaos__) && !defined(__amigaos4__)
#include <poll.h>
#endif
#include <errno.h>
#define MINIUPNPC_IGNORE_EINTR
#endif
#ifdef _WIN32
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
#else
#define PRINT_SOCKET_ERROR(x) perror(x)
#endif
#include "receivedata.h"
int
receivedata(int socket,
char * data, int length,
int timeout, unsigned int * scope_id)
{
#ifdef MINIUPNPC_GET_SRC_ADDR
#ifdef DEBUG
/* to shut up valgrind about uninit value */
struct sockaddr_storage src_addr = {0};
#else
struct sockaddr_storage src_addr;
#endif
socklen_t src_addr_len = sizeof(src_addr);
#endif
int n;
#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
/* using poll */
struct pollfd fds[1]; /* for the poll */
#ifdef MINIUPNPC_IGNORE_EINTR
do {
#endif
fds[0].fd = socket;
fds[0].events = POLLIN;
n = poll(fds, 1, timeout);
#ifdef MINIUPNPC_IGNORE_EINTR
} while(n < 0 && errno == EINTR);
#endif
if(n < 0) {
PRINT_SOCKET_ERROR("poll");
return -1;
} else if(n == 0) {
/* timeout */
return 0;
}
#else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
/* using select under _WIN32 and amigaos */
fd_set socketSet;
TIMEVAL timeval;
FD_ZERO(&socketSet);
FD_SET(socket, &socketSet);
timeval.tv_sec = timeout / 1000;
timeval.tv_usec = (timeout % 1000) * 1000;
n = select(FD_SETSIZE, &socketSet, NULL, NULL, &timeval);
if(n < 0) {
PRINT_SOCKET_ERROR("select");
return -1;
} else if(n == 0) {
return 0;
}
#endif
#ifdef MINIUPNPC_GET_SRC_ADDR
n = recvfrom(socket, data, length, 0,
(struct sockaddr *)&src_addr, &src_addr_len);
#else
n = recv(socket, data, length, 0);
#endif
if(n<0) {
PRINT_SOCKET_ERROR("recv");
}
#ifdef MINIUPNPC_GET_SRC_ADDR
if (src_addr.ss_family == AF_INET6) {
const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr;
#ifdef DEBUG
printf("scope_id=%u\n", src_addr6->sin6_scope_id);
#endif
if(scope_id)
*scope_id = src_addr6->sin6_scope_id;
}
#endif
return n;
}

View File

@@ -1,19 +0,0 @@
/* $Id: receivedata.h,v 1.4 2012/09/27 15:42:10 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author: Thomas Bernard
* Copyright (c) 2011-2012 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef RECEIVEDATA_H_INCLUDED
#define RECEIVEDATA_H_INCLUDED
/* Reads data from the specified socket.
* Returns the number of bytes read if successful, zero if no bytes were
* read or if we timed out. Returns negative if there was an error. */
int receivedata(int socket,
char * data, int length,
int timeout, unsigned int * scope_id);
#endif

View File

@@ -1,54 +0,0 @@
#! /bin/sh
# $Id: updateminiupnpcstrings.sh,v 1.7 2011/01/04 11:41:53 nanard Exp $
# project miniupnp : http://miniupnp.free.fr/
# (c) 2009 Thomas Bernard
VERSION_FILE="$1"
TEMPLATE_FILE="$2"
FILE="$3"
TMPFILE="$3.tmp"
# detecting the OS name and version
OS_NAME=`uname -s`
OS_VERSION=`uname -r`
if [ -f /etc/debian_version ]; then
OS_NAME=Debian
OS_VERSION=`cat /etc/debian_version`
fi
# use lsb_release (Linux Standard Base) when available
LSB_RELEASE=`which lsb_release`
if [ 0 -eq $? -a -x "${LSB_RELEASE}" ]; then
OS_NAME=`${LSB_RELEASE} -i -s`
OS_VERSION=`${LSB_RELEASE} -r -s`
case $OS_NAME in
Debian)
#OS_VERSION=`${LSB_RELEASE} -c -s`
;;
Ubuntu)
#OS_VERSION=`${LSB_RELEASE} -c -s`
;;
esac
fi
# on AmigaOS 3, uname -r returns "unknown", so we use uname -v
if [ "$OS_NAME" = "AmigaOS" ]; then
if [ "$OS_VERSION" = "unknown" ]; then
OS_VERSION=`uname -v`
fi
fi
echo "Detected OS [$OS_NAME] version [$OS_VERSION]"
MINIUPNPC_VERSION=`cat "${VERSION_FILE}"`
echo "MiniUPnPc version [${MINIUPNPC_VERSION}]"
EXPR="s|OS_STRING \".*\"|OS_STRING \"${OS_NAME}/${OS_VERSION}\"|"
#echo $EXPR
test -f "${FILE}.in"
echo "setting OS_STRING macro value to ${OS_NAME}/${OS_VERSION} in $FILE."
sed -e "$EXPR" < "$TEMPLATE_FILE" > "$TMPFILE"
EXPR="s|MINIUPNPC_VERSION_STRING \".*\"|MINIUPNPC_VERSION_STRING \"${MINIUPNPC_VERSION}\"|"
echo "setting MINIUPNPC_VERSION_STRING macro value to ${MINIUPNPC_VERSION} in $FILE."
sed -e "$EXPR" < "$TMPFILE" > "$FILE"
rm "$TMPFILE"

File diff suppressed because it is too large Load Diff

View File

@@ -1,293 +0,0 @@
/* $Id: upnpcommands.h,v 1.27 2014/02/17 15:38:26 nanard Exp $ */
/* Miniupnp project : http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2005-2014 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided within this distribution */
#ifndef UPNPCOMMANDS_H_INCLUDED
#define UPNPCOMMANDS_H_INCLUDED
#include "upnpreplyparse.h"
#include "portlistingparse.h"
#include "declspec.h"
#include "miniupnpctypes.h"
/* MiniUPnPc return codes : */
#define UPNPCOMMAND_SUCCESS (0)
#define UPNPCOMMAND_UNKNOWN_ERROR (-1)
#define UPNPCOMMAND_INVALID_ARGS (-2)
#define UPNPCOMMAND_HTTP_ERROR (-3)
#ifdef __cplusplus
extern "C" {
#endif
LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesSent(const char * controlURL,
const char * servicetype);
LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesReceived(const char * controlURL,
const char * servicetype);
LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalPacketsSent(const char * controlURL,
const char * servicetype);
LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalPacketsReceived(const char * controlURL,
const char * servicetype);
/* UPNP_GetStatusInfo()
* status and lastconnerror are 64 byte buffers
* Return values :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error code */
LIBSPEC int
UPNP_GetStatusInfo(const char * controlURL,
const char * servicetype,
char * status,
unsigned int * uptime,
char * lastconnerror);
/* UPNP_GetConnectionTypeInfo()
* argument connectionType is a 64 character buffer
* Return Values :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error code */
LIBSPEC int
UPNP_GetConnectionTypeInfo(const char * controlURL,
const char * servicetype,
char * connectionType);
/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
* if the third arg is not null the value is copied to it.
* at least 16 bytes must be available
*
* Return values :
* 0 : SUCCESS
* NON ZERO : ERROR Either an UPnP error code or an unknown error.
*
* possible UPnP Errors :
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 501 Action Failed - See UPnP Device Architecture section on Control. */
LIBSPEC int
UPNP_GetExternalIPAddress(const char * controlURL,
const char * servicetype,
char * extIpAdd);
/* UPNP_GetLinkLayerMaxBitRates()
* call WANCommonInterfaceConfig:1#GetCommonLinkProperties
*
* return values :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error Code. */
LIBSPEC int
UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
const char* servicetype,
unsigned int * bitrateDown,
unsigned int * bitrateUp);
/* UPNP_AddPortMapping()
* if desc is NULL, it will be defaulted to "libminiupnpc"
* remoteHost is usually NULL because IGD don't support it.
*
* Return values :
* 0 : SUCCESS
* NON ZERO : ERROR. Either an UPnP error code or an unknown error.
*
* List of possible UPnP errors for AddPortMapping :
* errorCode errorDescription (short) - Description (long)
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 501 Action Failed - See UPnP Device Architecture section on Control.
* 606 Action not authorized - The action requested REQUIRES authorization and
* the sender was not authorized.
* 715 WildCardNotPermittedInSrcIP - The source IP address cannot be
* wild-carded
* 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded
* 718 ConflictInMappingEntry - The port mapping entry specified conflicts
* with a mapping assigned previously to another client
* 724 SamePortValuesRequired - Internal and External port values
* must be the same
* 725 OnlyPermanentLeasesSupported - The NAT implementation only supports
* permanent lease times on port mappings
* 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard
* and cannot be a specific IP address or DNS name
* 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and
* cannot be a specific port value
* 728 NoPortMapsAvailable - There are not enough free ports available to
* complete port mapping.
* 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed
* due to conflict with other mechanisms.
* 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded
*/
LIBSPEC int
UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
const char * extPort,
const char * inPort,
const char * inClient,
const char * desc,
const char * proto,
const char * remoteHost,
const char * leaseDuration);
/* UPNP_DeletePortMapping()
* Use same argument values as what was used for AddPortMapping().
* remoteHost is usually NULL because IGD don't support it.
* Return Values :
* 0 : SUCCESS
* NON ZERO : error. Either an UPnP error code or an undefined error.
*
* List of possible UPnP errors for DeletePortMapping :
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 606 Action not authorized - The action requested REQUIRES authorization
* and the sender was not authorized.
* 714 NoSuchEntryInArray - The specified value does not exist in the array */
LIBSPEC int
UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
const char * extPort, const char * proto,
const char * remoteHost);
/* UPNP_GetPortMappingNumberOfEntries()
* not supported by all routers */
LIBSPEC int
UPNP_GetPortMappingNumberOfEntries(const char* controlURL,
const char* servicetype,
unsigned int * num);
/* UPNP_GetSpecificPortMappingEntry()
* retrieves an existing port mapping
* params :
* in extPort
* in proto
* in remoteHost
* out intClient (16 bytes)
* out intPort (6 bytes)
* out desc (80 bytes)
* out enabled (4 bytes)
* out leaseDuration (16 bytes)
*
* return value :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error Code.
*
* List of possible UPnP errors for _GetSpecificPortMappingEntry :
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 501 Action Failed - See UPnP Device Architecture section on Control.
* 606 Action not authorized - The action requested REQUIRES authorization
* and the sender was not authorized.
* 714 NoSuchEntryInArray - The specified value does not exist in the array.
*/
LIBSPEC int
UPNP_GetSpecificPortMappingEntry(const char * controlURL,
const char * servicetype,
const char * extPort,
const char * proto,
const char * remoteHost,
char * intClient,
char * intPort,
char * desc,
char * enabled,
char * leaseDuration);
/* UPNP_GetGenericPortMappingEntry()
* params :
* in index
* out extPort (6 bytes)
* out intClient (16 bytes)
* out intPort (6 bytes)
* out protocol (4 bytes)
* out desc (80 bytes)
* out enabled (4 bytes)
* out rHost (64 bytes)
* out duration (16 bytes)
*
* return value :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error Code.
*
* Possible UPNP Error codes :
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 606 Action not authorized - The action requested REQUIRES authorization
* and the sender was not authorized.
* 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds
*/
LIBSPEC int
UPNP_GetGenericPortMappingEntry(const char * controlURL,
const char * servicetype,
const char * index,
char * extPort,
char * intClient,
char * intPort,
char * protocol,
char * desc,
char * enabled,
char * rHost,
char * duration);
/* UPNP_GetListOfPortMappings() Available in IGD v2
*
*
* Possible UPNP Error codes :
* 606 Action not Authorized
* 730 PortMappingNotFound - no port mapping is found in the specified range.
* 733 InconsistantParameters - NewStartPort and NewEndPort values are not
* consistent.
*/
LIBSPEC int
UPNP_GetListOfPortMappings(const char * controlURL,
const char * servicetype,
const char * startPort,
const char * endPort,
const char * protocol,
const char * numberOfPorts,
struct PortMappingParserData * data);
/* IGD:2, functions for service WANIPv6FirewallControl:1 */
LIBSPEC int
UPNP_GetFirewallStatus(const char * controlURL,
const char * servicetype,
int * firewallEnabled,
int * inboundPinholeAllowed);
LIBSPEC int
UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype,
const char * remoteHost,
const char * remotePort,
const char * intClient,
const char * intPort,
const char * proto,
int * opTimeout);
LIBSPEC int
UPNP_AddPinhole(const char * controlURL, const char * servicetype,
const char * remoteHost,
const char * remotePort,
const char * intClient,
const char * intPort,
const char * proto,
const char * leaseTime,
char * uniqueID);
LIBSPEC int
UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
const char * uniqueID,
const char * leaseTime);
LIBSPEC int
UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID);
LIBSPEC int
UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
const char * uniqueID, int * isWorking);
LIBSPEC int
UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
const char * uniqueID, int * packets);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,183 +0,0 @@
/* $Id: upnpreplyparse.c,v 1.15 2013/06/06 21:36:40 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "upnpreplyparse.h"
#include "minixml.h"
static void
NameValueParserStartElt(void * d, const char * name, int l)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
data->topelt = 1;
if(l>63)
l = 63;
memcpy(data->curelt, name, l);
data->curelt[l] = '\0';
data->cdata = NULL;
data->cdatalen = 0;
}
static void
NameValueParserEndElt(void * d, const char * name, int l)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValue * nv;
(void)name;
(void)l;
if(!data->topelt)
return;
if(strcmp(data->curelt, "NewPortListing") != 0)
{
int l;
/* standard case. Limited to n chars strings */
l = data->cdatalen;
nv = malloc(sizeof(struct NameValue));
if(l>=(int)sizeof(nv->value))
l = sizeof(nv->value) - 1;
strncpy(nv->name, data->curelt, 64);
nv->name[63] = '\0';
if(data->cdata != NULL)
{
memcpy(nv->value, data->cdata, l);
nv->value[l] = '\0';
}
else
{
nv->value[0] = '\0';
}
LIST_INSERT_HEAD( &(data->head), nv, entries);
}
data->cdata = NULL;
data->cdatalen = 0;
data->topelt = 0;
}
static void
NameValueParserGetData(void * d, const char * datas, int l)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
if(strcmp(data->curelt, "NewPortListing") == 0)
{
/* specific case for NewPortListing which is a XML Document */
data->portListing = malloc(l + 1);
if(!data->portListing)
{
/* malloc error */
return;
}
memcpy(data->portListing, datas, l);
data->portListing[l] = '\0';
data->portListingLength = l;
}
else
{
/* standard case. */
data->cdata = datas;
data->cdatalen = l;
}
}
void
ParseNameValue(const char * buffer, int bufsize,
struct NameValueParserData * data)
{
struct xmlparser parser;
LIST_INIT(&(data->head));
data->portListing = NULL;
data->portListingLength = 0;
/* init xmlparser object */
parser.xmlstart = buffer;
parser.xmlsize = bufsize;
parser.data = data;
parser.starteltfunc = NameValueParserStartElt;
parser.endeltfunc = NameValueParserEndElt;
parser.datafunc = NameValueParserGetData;
parser.attfunc = 0;
parsexml(&parser);
}
void
ClearNameValueList(struct NameValueParserData * pdata)
{
struct NameValue * nv;
if(pdata->portListing)
{
free(pdata->portListing);
pdata->portListing = NULL;
pdata->portListingLength = 0;
}
while((nv = pdata->head.lh_first) != NULL)
{
LIST_REMOVE(nv, entries);
free(nv);
}
}
char *
GetValueFromNameValueList(struct NameValueParserData * pdata,
const char * Name)
{
struct NameValue * nv;
char * p = NULL;
for(nv = pdata->head.lh_first;
(nv != NULL) && (p == NULL);
nv = nv->entries.le_next)
{
if(strcmp(nv->name, Name) == 0)
p = nv->value;
}
return p;
}
#if 0
/* useless now that minixml ignores namespaces by itself */
char *
GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
const char * Name)
{
struct NameValue * nv;
char * p = NULL;
char * pname;
for(nv = pdata->head.lh_first;
(nv != NULL) && (p == NULL);
nv = nv->entries.le_next)
{
pname = strrchr(nv->name, ':');
if(pname)
pname++;
else
pname = nv->name;
if(strcmp(pname, Name)==0)
p = nv->value;
}
return p;
}
#endif
/* debug all-in-one function
* do parsing then display to stdout */
#ifdef DEBUG
void
DisplayNameValueList(char * buffer, int bufsize)
{
struct NameValueParserData pdata;
struct NameValue * nv;
ParseNameValue(buffer, bufsize, &pdata);
for(nv = pdata.head.lh_first;
nv != NULL;
nv = nv->entries.le_next)
{
printf("%s = %s\n", nv->name, nv->value);
}
ClearNameValueList(&pdata);
}
#endif

View File

@@ -1,69 +0,0 @@
/* $Id: upnpreplyparse.h,v 1.17 2013/06/06 21:36:40 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#ifndef UPNPREPLYPARSE_H_INCLUDED
#define UPNPREPLYPARSE_H_INCLUDED
#if defined(NO_SYS_QUEUE_H) || defined(_WIN32) || defined(__HAIKU__)
#include "bsdqueue.h"
#else
#include <sys/queue.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
struct NameValue {
LIST_ENTRY(NameValue) entries;
char name[64];
char value[128];
};
struct NameValueParserData {
LIST_HEAD(listhead, NameValue) head;
char curelt[64];
char * portListing;
int portListingLength;
int topelt;
const char * cdata;
int cdatalen;
};
/* ParseNameValue() */
void
ParseNameValue(const char * buffer, int bufsize,
struct NameValueParserData * data);
/* ClearNameValueList() */
void
ClearNameValueList(struct NameValueParserData * pdata);
/* GetValueFromNameValueList() */
char *
GetValueFromNameValueList(struct NameValueParserData * pdata,
const char * Name);
#if 0
/* GetValueFromNameValueListIgnoreNS() */
char *
GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
const char * Name);
#endif
/* DisplayNameValueList() */
#ifdef DEBUG
void
DisplayNameValueList(char * buffer, int bufsize);
#endif
#ifdef __cplusplus
}
#endif
#endif