Backport of svn revision 504:

SF Patch Tracker [ 2969188 ] 1.8.0: patch for FreeBSD compilation
	Submitted By: Nick Leverton (leveret)
	Fix the order of header inclusion for FreeBSD.


git-svn-id: https://pupnp.svn.sourceforge.net/svnroot/pupnp/branches/branch-1.6.x@509 119443c7-1b9e-41f8-b6fc-b9c35fce742c
This commit is contained in:
Marcelo Roberto Jimenez
2010-03-21 15:42:40 +00:00
parent 9226dd833b
commit 5eb55e0fb2
9 changed files with 386 additions and 346 deletions

View File

@@ -43,6 +43,7 @@
#include <lwres/netdb.h>
#endif
#endif
#include <assert.h>
#include "config.h"
@@ -51,7 +52,7 @@
#include "uri.h"
#include "upnpdebug.h"
#include "upnpapi.h"
/*!
@@ -187,28 +188,6 @@ static int parse_uric(
return i;
}
/************************************************************************
* Function : copy_sockaddr_in
*
* Parameters :
* const struct sockaddr_in *in ; Source socket address object
* struct sockaddr_in *out ; Destination socket address object
*
* Description : Copies one socket address into another
*
* Return : void ;
*
* Note :
************************************************************************/
void
copy_sockaddr_in( const struct sockaddr_in *in,
struct sockaddr_in *out )
{
memset( out->sin_zero, 0, 8 );
out->sin_family = in->sin_family;
out->sin_port = in->sin_port;
out->sin_addr.s_addr = in->sin_addr.s_addr;
}
/*!
* \brief Tokens are generally pointers into other strings. This copies the
@@ -263,8 +242,9 @@ int copy_URL_list(URL_list *in, URL_list *out)
in->URLs, &out->parsedURLs[i].hostport.text,
out->URLs );
copy_sockaddr_in( &in->parsedURLs[i].hostport.IPv4address,
&out->parsedURLs[i].hostport.IPv4address );
memcpy( &out->parsedURLs[i].hostport.IPaddress,
&in->parsedURLs[i].hostport.IPaddress,
sizeof(struct sockaddr_storage) );
}
out->size = in->size;
@@ -343,186 +323,156 @@ int token_cmp(token *in1, token *in2)
}
int parse_port(int max, const char *port, unsigned short *out)
{
const char *finger = port;
const char *max_ptr = finger + max;
unsigned short temp = 0;
while((finger < max_ptr) && (isdigit(*finger))) {
temp = temp * 10;
temp += *finger - '0';
finger++;
}
*out = htons(temp);
return finger - port;
}
int parse_hostport(
const char *in,
int max,
hostport_type *out)
{
#define BUFFER_SIZE 8192
int i = 0;
int begin_port;
int hostport_size = 0;
int host_size = 0;
#if !defined(WIN32) && !(defined(__OSX__) || defined(__APPLE__))
char temp_hostbyname_buff[BUFFER_SIZE];
struct hostent h_buf;
#endif
struct hostent *h = NULL;
int errcode = 0;
char *temp_host_name = NULL;
int last_dot = -1;
char workbuf[256];
char* c;
struct sockaddr_in* sai4 = (struct sockaddr_in*)&out->IPaddress;
struct sockaddr_in6* sai6 = (struct sockaddr_in6*)&out->IPaddress;
char *srvname = NULL;
char *srvport = NULL;
char *last_dot = NULL;
unsigned short int port;
int af = AF_UNSPEC;
int hostport_size;
int has_port = 0;
int ret;
memset( out, 0, sizeof(hostport_type) );
out->IPv4address.sin_port = htons( 80 ); //default port is 80
memset( &out->IPv4address.sin_zero, 0, 8 );
// Work on a copy of the input string.
strncpy( workbuf, in, sizeof(workbuf) );
while( ( i < max ) && ( in[i] != ':' ) && ( in[i] != '/' )
&& ( ( isalnum( in[i] ) ) || ( in[i] == '.' )
|| ( in[i] == '-' ) ) ) {
i++;
if( in[i] == '.' ) {
last_dot = i;
c = workbuf;
if( *c == '[' ) {
// IPv6 addresses are enclosed in square brackets.
srvname = ++c;
while( *c != '\0' && *c != ']' ) {
c++;
}
if( *c == '\0' ) {
// did not find closing bracket.
return UPNP_E_INVALID_URL;
}
// NULL terminate the srvname and then increment c.
*c++ = '\0'; // overwrite the ']'
if( *c == ':' ) {
has_port = 1;
c++;
}
af = AF_INET6;
}
host_size = i;
if( ( i < max ) && ( in[i] == ':' ) ) {
begin_port = i + 1;
//convert port
if( !( hostport_size = parse_port( max - begin_port,
&in[begin_port],
&out->IPv4address.sin_port ) ) )
{
return UPNP_E_INVALID_URL;
else {
// IPv4 address -OR- host name.
srvname = c;
while( (*c != ':') && (*c != '/') && ( (isalnum(*c)) || (*c == '.') || (*c == '-') ) ) {
if( *c == '.' )
last_dot = c;
c++;
}
hostport_size += begin_port;
} else
hostport_size = host_size;
has_port = (*c == ':') ? 1 : 0;
// NULL terminate the srvname
*c = '\0';
if( has_port == 1 )
c++;
//convert to temporary null terminated string
temp_host_name = ( char * )malloc( host_size + 1 );
if( temp_host_name == NULL )
return UPNP_E_OUTOF_MEMORY;
memcpy( temp_host_name, in, host_size );
temp_host_name[host_size] = '\0';
//check to see if host name is an ipv4 address
if( ( last_dot != -1 ) && ( last_dot + 1 < host_size )
&& ( isdigit( temp_host_name[last_dot + 1] ) ) ) {
//must be ipv4 address
errcode = inet_pton( AF_INET,
temp_host_name, &out->IPv4address.sin_addr );
if( errcode == 1 ) {
out->IPv4address.sin_family = AF_INET;
} else {
out->IPv4address.sin_addr.s_addr = 0;
out->IPv4address.sin_family = AF_INET;
free( temp_host_name );
temp_host_name = NULL;
return UPNP_E_INVALID_URL;
if( last_dot != NULL && isdigit(*(last_dot+1)) ) {
// Must be an IPv4 address.
af = AF_INET;
}
} else {
int errCode = 0;
//call gethostbyname_r (reentrant form of gethostbyname)
// TODO: Use autoconf to discover this rather than the
// platform-specific stuff below
#if defined(WIN32) || defined(__CYGWIN__)
h = gethostbyname(temp_host_name);
#elif defined(SPARC_SOLARIS)
errCode = gethostbyname_r(
temp_host_name,
&h,
temp_hostbyname_buff,
BUFFER_SIZE, &errcode );
#elif defined(__FreeBSD__) && __FreeBSD_version < 601103
h = lwres_gethostbyname_r(
temp_host_name,
&h_buf,
temp_hostbyname_buff,
BUFFER_SIZE, &errcode );
if ( h == NULL ) {
errCode = 1;
}
#elif defined(__OSX__) || defined(__APPLE__)
h = gethostbyname(temp_host_name);
if ( h == NULL ) {
errCode = 1;
}
#elif defined(__linux__)
errCode = gethostbyname_r(
temp_host_name,
&h_buf,
temp_hostbyname_buff,
BUFFER_SIZE, &h, &errcode );
#else
{
else {
// Must be a host name.
struct addrinfo hints, *res, *res0;
h = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
errCode = getaddrinfo(temp_host_name, "http", &hints, &res0);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if (!errCode) {
for (res = res0; res; res = res->ai_next) {
if (res->ai_family == PF_INET &&
res->ai_addr->sa_family == AF_INET)
{
h = &h_buf;
h->h_addrtype = res->ai_addr->sa_family;
h->h_length = 4;
h->h_addr = (void *) temp_hostbyname_buff;
*(struct in_addr *)h->h_addr =
((struct sockaddr_in *)res->ai_addr)->sin_addr;
ret = getaddrinfo(srvname, NULL, &hints, &res0);
if( ret == 0 ) {
for (res = res0; res; res = res->ai_next) {
if( res->ai_family == AF_INET ||
res->ai_family == AF_INET6 ) {
// Found a valid IPv4 or IPv6 address.
memcpy( &out->IPaddress, res->ai_addr,
res->ai_addrlen );
break;
}
}
}
freeaddrinfo(res0);
}
}
#endif
if( errCode == 0 ) {
if( h ) {
if( ( h->h_addrtype == AF_INET ) && ( h->h_length == 4 ) ) {
out->IPv4address.sin_addr =
( *( struct in_addr * )h->h_addr );
out->IPv4address.sin_family = AF_INET;
freeaddrinfo(res0);
if( res == NULL ) {
// Didn't find an AF_INET or AF_INET6 address.
return UPNP_E_INVALID_URL;
}
}
} else {
out->IPv4address.sin_addr.s_addr = 0;
out->IPv4address.sin_family = AF_INET;
free( temp_host_name );
temp_host_name = NULL;
return UPNP_E_INVALID_URL;
else {
// getaddrinfo failed.
return UPNP_E_INVALID_URL;
}
}
}
if( temp_host_name ) {
free( temp_host_name );
temp_host_name = NULL;
// Check if a port is specified.
if( has_port == 1 ) {
// Port is specified.
srvport = c;
while( *c != '\0' && isdigit(*c) ) {
c++;
}
port = (unsigned short int)atoi(srvport);
if( port == 0 ) {
// Bad port number.
return UPNP_E_INVALID_URL;
}
}
else {
// Port was not specified, use default port.
port = 80;
}
// The length of the host and port string can be calculated by
// subtracting pointers.
hostport_size = (int)(c - workbuf);
// Fill in the 'out' information.
if( af == AF_INET ) {
sai4->sin_family = AF_INET;
sai4->sin_port = htons(port);
ret = inet_pton(AF_INET, srvname, &sai4->sin_addr);
}
else if( af == AF_INET6 ) {
sai6->sin6_family = AF_INET6;
sai6->sin6_port = htons(port);
/*
sai6->sin6_scope_id = gIF_INDEX;
ret = inet_pton(AF_INET6, srvname, &sai6->sin6_addr);
*/
/* libUPnP 1.6.x does not currently support IPV6. */
assert(0);
ret = -1;
} else {
// IP address was set by the hostname (getaddrinfo).
// Override port:
if( out->IPaddress.ss_family == AF_INET )
sai4->sin_port = htons(port);
else
sai6->sin6_port = htons(port);
ret = 1;
}
/* Check if address was converted successfully. */
if (ret <= 0) {
return UPNP_E_INVALID_URL;
}
out->text.size = hostport_size;
out->text.buff = in;
return hostport_size;
return hostport_size;
}
/*!