Large diffs are not rendered by default.

This file was deleted.

This file was deleted.

@@ -1,26 +1,16 @@
c-ares version 1.7.5
c-ares version 1.9.0

Fixed:
Changed:

o Added ares_parse_soa_reply

o detection of semicolon comments in resolv.conf
o avoid using system's inet_net_pton affected by the WLB-2008080064 advisory
o replacement ares_inet_net_pton affected by the WLB-2008080064 advisory
o replacement ares_inet_ntop affected by potential out of bounds write
o added install target to Makefile.msvc
o only fall back to AF_INET searches when looking for AF_UNSPEC addresses
o fixed ares_parse_*_reply memory leaks
o Use correct sizeof in ares_getnameinfo()
o IPv6-on-windows: find DNS servers correctly
o man pages: docs for the c-ares utility programs
o getservbyport replacement for Win CE
o config_sortlist: (win32) missing else
o advance_tcp_send_queue: avoid NULL ptr dereference
o configure: fix a bashism
o ares_expand_name: Fix encoded length for indirect root
Fixed:

o libcares.pc generation for static MingW* cross builds
o ares_dup: UDP and TCP port byte order in saved options

Thanks go to these friendly people for their efforts and contributions:

Yang Tse, Jakub Hrozek, Gisle Vanem, Tom Hughes, David Stuart, Dima Tisnek,
Peter Pentchev, Stefan Buhler
Yang Tse, Nick Alcock, Marko Kreen

Have fun!
@@ -1,5 +1,5 @@

/* Copyright 1998, 2010 by the Massachusetts Institute of Technology.
/* Copyright 1998, 2011 by the Massachusetts Institute of Technology.
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
@@ -31,6 +31,7 @@

#include "ares.h"
#include "inet_net_pton.h"
#include "ares_nowarn.h"
#include "ares_private.h"

int ares__get_hostent(FILE *fp, int family, struct hostent **host)
@@ -219,8 +220,8 @@ int ares__get_hostent(FILE *fp, int family, struct hostent **host)
break;

/* Copy actual network address family and length. */
hostent->h_addrtype = addr.family;
hostent->h_length = (int)addrlen;
hostent->h_addrtype = aresx_sitoss(addr.family);
hostent->h_length = aresx_uztoss(addrlen);

/* Free line buffer. */
free(line);
@@ -1,5 +1,5 @@

/* Copyright (C) 2009-2010 by Daniel Stenberg
/* Copyright (C) 2009-2012 by Daniel Stenberg
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
@@ -92,6 +92,27 @@ void ares_free_data(void *dataptr)
ares_free_data(ptr->data.addr_node.next);
break;

case ARES_DATATYPE_NAPTR_REPLY:

if (ptr->data.naptr_reply.next)
ares_free_data(ptr->data.naptr_reply.next);
if (ptr->data.naptr_reply.flags)
free(ptr->data.naptr_reply.flags);
if (ptr->data.naptr_reply.service)
free(ptr->data.naptr_reply.service);
if (ptr->data.naptr_reply.regexp)
free(ptr->data.naptr_reply.regexp);
if (ptr->data.naptr_reply.replacement)
free(ptr->data.naptr_reply.replacement);
break;

case ARES_DATATYPE_SOA_REPLY:
if (ptr->data.soa_reply.nsname)
free(ptr->data.soa_reply.nsname);
if (ptr->data.soa_reply.hostmaster)
free(ptr->data.soa_reply.hostmaster);
break;

default:
return;
}
@@ -138,7 +159,7 @@ void *ares_malloc_data(ares_datatype type)
case ARES_DATATYPE_TXT_REPLY:
ptr->data.txt_reply.next = NULL;
ptr->data.txt_reply.txt = NULL;
ptr->data.txt_reply.length = 0;
ptr->data.txt_reply.length = 0;
break;

case ARES_DATATYPE_ADDR_NODE:
@@ -148,6 +169,26 @@ void *ares_malloc_data(ares_datatype type)
sizeof(ptr->data.addr_node.addrV6));
break;

case ARES_DATATYPE_NAPTR_REPLY:
ptr->data.naptr_reply.next = NULL;
ptr->data.naptr_reply.flags = NULL;
ptr->data.naptr_reply.service = NULL;
ptr->data.naptr_reply.regexp = NULL;
ptr->data.naptr_reply.replacement = NULL;
ptr->data.naptr_reply.order = 0;
ptr->data.naptr_reply.preference = 0;
break;

case ARES_DATATYPE_SOA_REPLY:
ptr->data.soa_reply.nsname = NULL;
ptr->data.soa_reply.hostmaster = NULL;
ptr->data.soa_reply.serial = 0;
ptr->data.soa_reply.refresh = 0;
ptr->data.soa_reply.retry = 0;
ptr->data.soa_reply.expire = 0;
ptr->data.soa_reply.minttl = 0;
break;

default:
free(ptr);
return NULL;
@@ -1,5 +1,5 @@

/* Copyright (C) 2009-2010 by Daniel Stenberg
/* Copyright (C) 2009-2012 by Daniel Stenberg
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
@@ -20,6 +20,8 @@ typedef enum {
ARES_DATATYPE_TXT_REPLY, /* struct ares_txt_reply - introduced in 1.7.0 */
ARES_DATATYPE_ADDR_NODE, /* struct ares_addr_node - introduced in 1.7.1 */
ARES_DATATYPE_MX_REPLY, /* struct ares_mx_reply - introduced in 1.7.2 */
ARES_DATATYPE_NAPTR_REPLY,/* struct ares_naptr_reply - introduced in 1.7.6 */
ARES_DATATYPE_SOA_REPLY, /* struct ares_soa_reply - introduced in 1.9.0 */
#if 0
ARES_DATATYPE_ADDR6TTL, /* struct ares_addrttl */
ARES_DATATYPE_ADDRTTL, /* struct ares_addr6ttl */
@@ -53,10 +55,12 @@ struct ares_data {
ares_datatype type; /* Actual data type identifier. */
unsigned int mark; /* Private ares_data signature. */
union {
struct ares_txt_reply txt_reply;
struct ares_srv_reply srv_reply;
struct ares_addr_node addr_node;
struct ares_mx_reply mx_reply;
struct ares_txt_reply txt_reply;
struct ares_srv_reply srv_reply;
struct ares_addr_node addr_node;
struct ares_mx_reply mx_reply;
struct ares_naptr_reply naptr_reply;
struct ares_soa_reply soa_reply;
} data;
};

@@ -1,6 +1,6 @@

/* Copyright 1998 by the Massachusetts Institute of Technology.
* Copyright (C) 2004-2010 by Daniel Stenberg
* Copyright (C) 2004-2011 by Daniel Stenberg
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
@@ -29,10 +29,12 @@ void ares_destroy_options(struct ares_options *options)
free(options->servers);
for (i = 0; i < options->ndomains; i++)
free(options->domains[i]);
free(options->domains);
if(options->domains)
free(options->domains);
if(options->sortlist)
free(options->sortlist);
free(options->lookups);
if(options->lookups)
free(options->lookups);
}

void ares_destroy(ares_channel channel)
@@ -1,5 +1,7 @@
#ifndef HEADER_CARES_DNS_H
#define HEADER_CARES_DNS_H

/* Copyright 1998 by the Massachusetts Institute of Technology.
/* Copyright 1998, 2011 by the Massachusetts Institute of Technology.
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
@@ -14,12 +16,23 @@
* without express or implied warranty.
*/

#ifndef ARES__DNS_H
#define ARES__DNS_H
/*
* Macro DNS__16BIT reads a network short (16 bit) given in network
* byte order, and returns its value as an unsigned short.
*/
#define DNS__16BIT(p) ((unsigned short)((unsigned int) 0xffff & \
(((unsigned int)((unsigned char)(p)[0]) << 8U) | \
((unsigned int)((unsigned char)(p)[1])))))

#define DNS__16BIT(p) (((p)[0] << 8) | (p)[1])
#define DNS__32BIT(p) (((p)[0] << 24) | ((p)[1] << 16) | \
((p)[2] << 8) | (p)[3])
/*
* Macro DNS__32BIT reads a network long (32 bit) given in network
* byte order, and returns its value as an unsigned int.
*/
#define DNS__32BIT(p) ((unsigned int) \
(((unsigned int)((unsigned char)(p)[0]) << 24U) | \
((unsigned int)((unsigned char)(p)[1]) << 16U) | \
((unsigned int)((unsigned char)(p)[2]) << 8U) | \
((unsigned int)((unsigned char)(p)[3]))))

#define DNS__SET16BIT(p, v) (((p)[0] = (unsigned char)(((v) >> 8) & 0xff)), \
((p)[1] = (unsigned char)((v) & 0xff)))
@@ -87,4 +100,4 @@
#define DNS_RR_SET_TTL(r) DNS__SET32BIT((r) + 4, v)
#define DNS_RR_SET_LEN(r) DNS__SET16BIT((r) + 8, v)

#endif /* ARES__DNS_H */
#endif /* HEADER_CARES_DNS_H */
@@ -1,5 +1,5 @@

/* Copyright 1998 by the Massachusetts Institute of Technology.
/* Copyright 1998, 2011 by the Massachusetts Institute of Technology.
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
@@ -33,6 +33,7 @@

#include <stdlib.h>
#include "ares.h"
#include "ares_nowarn.h"
#include "ares_private.h" /* for the memdebug */

static int name_length(const unsigned char *encoded, const unsigned char *abuf,
@@ -91,9 +92,9 @@ int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
/* indirect root label (like 0xc0 0x0c) is 2 bytes long (stupid, but
valid) */
if ((*encoded & INDIR_MASK) == INDIR_MASK)
*enclen = 2;
*enclen = 2L;
else
*enclen = 1; /* the caller should move one byte to get past this */
*enclen = 1L; /* the caller should move one byte to get past this */

return ARES_SUCCESS;
}
@@ -106,7 +107,7 @@ int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
{
if (!indir)
{
*enclen = p + 2 - encoded;
*enclen = aresx_uztosl(p + 2U - encoded);
indir = 1;
}
p = abuf + ((*p & ~INDIR_MASK) << 8 | *(p + 1));
@@ -126,7 +127,7 @@ int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
}
}
if (!indir)
*enclen = p + 1 - encoded;
*enclen = aresx_uztosl(p + 1U - encoded);

/* Nuke the trailing period if we wrote one. */
if (q > *s)
@@ -1,5 +1,5 @@

/* Copyright 1998 by the Massachusetts Institute of Technology.
/* Copyright 1998, 2011 by the Massachusetts Institute of Technology.
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
@@ -49,6 +49,7 @@
#include "inet_net_pton.h"
#include "bitncmp.h"
#include "ares_platform.h"
#include "ares_nowarn.h"
#include "ares_private.h"

#ifdef WATT32
@@ -300,7 +301,7 @@ static int fake_hostent(const char *name, int family,
/* Fill in the rest of the host structure and terminate the query. */
addrs[1] = NULL;
hostent.h_aliases = aliases;
hostent.h_addrtype = family;
hostent.h_addrtype = aresx_sitoss(family);
hostent.h_addr_list = addrs;
callback(arg, ARES_SUCCESS, 0, &hostent);

@@ -188,15 +188,15 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa,
if (sa->sa_family == AF_INET)
{
niquery->family = AF_INET;
memcpy(&niquery->addr.addr4, addr, sizeof(struct in_addr));
memcpy(&niquery->addr.addr4, addr, sizeof(niquery->addr.addr4));
ares_gethostbyaddr(channel, &addr->sin_addr,
sizeof(struct in_addr), AF_INET,
nameinfo_callback, niquery);
}
else
{
niquery->family = AF_INET6;
memcpy(&niquery->addr.addr6, addr6, sizeof(struct ares_in6_addr));
memcpy(&niquery->addr.addr6, addr6, sizeof(niquery->addr.addr6));
ares_gethostbyaddr(channel, &addr6->sin6_addr,
sizeof(struct ares_in6_addr), AF_INET6,
nameinfo_callback, niquery);

Large diffs are not rendered by default.

@@ -23,7 +23,7 @@
#ifdef USE_WINSOCK

#include <iphlpapi.h>
#include "ares_iphlpapi.h"
#include <ares_iphlpapi.h>

typedef DWORD (WINAPI *fpGetNetworkParams_t) (FIXED_INFO*, DWORD*);
typedef BOOLEAN (APIENTRY *fpSystemFunction036_t) (void*, ULONG);
@@ -1,5 +1,5 @@

/* Copyright (C) 2010-2011 by Daniel Stenberg
/* Copyright (C) 2010-2012 by Daniel Stenberg
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
@@ -39,20 +39,32 @@

#include "ares_nowarn.h"

#if (SIZEOF_INT == 2)
# define CARES_MASK_SINT 0x7FFF
# define CARES_MASK_UINT 0xFFFF
#elif (SIZEOF_INT == 4)
# define CARES_MASK_SINT 0x7FFFFFFF
# define CARES_MASK_UINT 0xFFFFFFFF
#elif (SIZEOF_INT == 8)
# define CARES_MASK_SINT 0x7FFFFFFFFFFFFFFF
# define CARES_MASK_UINT 0xFFFFFFFFFFFFFFFF
#elif (SIZEOF_INT == 16)
# define CARES_MASK_SINT 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
# define CARES_MASK_UINT 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
#define CARES_MASK_USHORT (~(unsigned short) 0)
#define CARES_MASK_UINT (~(unsigned int) 0)
#define CARES_MASK_ULONG (~(unsigned long) 0)

#define CARES_MASK_SSHORT (CARES_MASK_USHORT >> 1)
#define CARES_MASK_SINT (CARES_MASK_UINT >> 1)
#define CARES_MASK_SLONG (CARES_MASK_ULONG >> 1)

/*
** unsigned size_t to signed long
*/

long aresx_uztosl(size_t uznum)
{
#ifdef __INTEL_COMPILER
# pragma warning(push)
# pragma warning(disable:810) /* conversion may lose significant bits */
#endif

return (long)(uznum & (size_t) CARES_MASK_SLONG);

#ifdef __INTEL_COMPILER
# pragma warning(pop)
#endif
}

/*
** unsigned size_t to signed int
*/
@@ -71,6 +83,43 @@ int aresx_uztosi(size_t uznum)
#endif
}

/*
** unsigned size_t to signed short
*/

short aresx_uztoss(size_t uznum)
{
#ifdef __INTEL_COMPILER
# pragma warning(push)
# pragma warning(disable:810) /* conversion may lose significant bits */
#endif

return (short)(uznum & (size_t) CARES_MASK_SSHORT);

#ifdef __INTEL_COMPILER
# pragma warning(pop)
#endif
}

/*
** signed int to signed short
*/

short aresx_sitoss(int sinum)
{
#ifdef __INTEL_COMPILER
# pragma warning(push)
# pragma warning(disable:810) /* conversion may lose significant bits */
#endif

DEBUGASSERT(sinum >= 0);
return (short)(sinum & (int) CARES_MASK_SSHORT);

#ifdef __INTEL_COMPILER
# pragma warning(pop)
#endif
}

/*
** signed long to signed int
*/
@@ -128,6 +177,25 @@ unsigned int aresx_sztoui(ssize_t sznum)
#endif
}

/*
** signed int to unsigned short
*/

unsigned short aresx_sitous(int sinum)
{
#ifdef __INTEL_COMPILER
# pragma warning(push)
# pragma warning(disable:810) /* conversion may lose significant bits */
#endif

DEBUGASSERT(sinum >= 0);
return (unsigned short)(sinum & (int) CARES_MASK_USHORT);

#ifdef __INTEL_COMPILER
# pragma warning(pop)
#endif
}

#if defined(__INTEL_COMPILER) && defined(__unix__)

int aresx_FD_ISSET(int fd, fd_set *fdset)
@@ -2,7 +2,7 @@
#define HEADER_CARES_NOWARN_H


/* Copyright (C) 2010-2011 by Daniel Stenberg
/* Copyright (C) 2010-2012 by Daniel Stenberg
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
@@ -17,14 +17,20 @@
* without express or implied warranty.
*/

int aresx_uztosi(size_t uznum);
long aresx_uztosl(size_t uznum);
int aresx_uztosi(size_t uznum);
short aresx_uztoss(size_t uznum);

short aresx_sitoss(int sinum);

int aresx_sltosi(long slnum);

int aresx_sztosi(ssize_t sznum);

unsigned int aresx_sztoui(ssize_t sznum);

unsigned short aresx_sitous(int sinum);

#if defined(__INTEL_COMPILER) && defined(__unix__)

int aresx_FD_ISSET(int fd, fd_set *fdset);
@@ -204,7 +204,9 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
}
}

if (status == ARES_SUCCESS && naddrs == 0)
/* the check for naliases to be zero is to make sure CNAME responses
don't get caught here */
if (status == ARES_SUCCESS && naddrs == 0 && naliases == 0)
status = ARES_ENODATA;
if (status == ARES_SUCCESS)
{
@@ -0,0 +1,188 @@

/* Copyright 1998 by the Massachusetts Institute of Technology.
* Copyright (C) 2009 by Jakub Hrozek <jhrozek@redhat.com>
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/

#include "ares_setup.h"

#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h>
#else
# include "nameser.h"
#endif
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
# include <arpa/nameser_compat.h>
#endif

#include <stdlib.h>
#include <string.h>
#include "ares.h"
#include "ares_dns.h"
#include "ares_data.h"
#include "ares_private.h"

/* AIX portability check */
#ifndef T_NAPTR
#define T_NAPTR 35 /* naming authority pointer */
#endif

int
ares_parse_naptr_reply (const unsigned char *abuf, int alen,
struct ares_naptr_reply **naptr_out)
{
unsigned int qdcount, ancount, i;
const unsigned char *aptr, *vptr;
int status, rr_type, rr_class, rr_len;
long len;
char *hostname = NULL, *rr_name = NULL;
struct ares_naptr_reply *naptr_head = NULL;
struct ares_naptr_reply *naptr_last = NULL;
struct ares_naptr_reply *naptr_curr;

/* Set *naptr_out to NULL for all failure cases. */
*naptr_out = NULL;

/* Give up if abuf doesn't have room for a header. */
if (alen < HFIXEDSZ)
return ARES_EBADRESP;

/* Fetch the question and answer count from the header. */
qdcount = DNS_HEADER_QDCOUNT (abuf);
ancount = DNS_HEADER_ANCOUNT (abuf);
if (qdcount != 1)
return ARES_EBADRESP;
if (ancount == 0)
return ARES_ENODATA;

/* Expand the name from the question, and skip past the question. */
aptr = abuf + HFIXEDSZ;
status = ares_expand_name (aptr, abuf, alen, &hostname, &len);
if (status != ARES_SUCCESS)
return status;

if (aptr + len + QFIXEDSZ > abuf + alen)
{
free (hostname);
return ARES_EBADRESP;
}
aptr += len + QFIXEDSZ;

/* Examine each answer resource record (RR) in turn. */
for (i = 0; i < ancount; i++)
{
/* Decode the RR up to the data field. */
status = ares_expand_name (aptr, abuf, alen, &rr_name, &len);
if (status != ARES_SUCCESS)
{
break;
}
aptr += len;
if (aptr + RRFIXEDSZ > abuf + alen)
{
status = ARES_EBADRESP;
break;
}
rr_type = DNS_RR_TYPE (aptr);
rr_class = DNS_RR_CLASS (aptr);
rr_len = DNS_RR_LEN (aptr);
aptr += RRFIXEDSZ;

/* Check if we are really looking at a NAPTR record */
if (rr_class == C_IN && rr_type == T_NAPTR)
{
/* parse the NAPTR record itself */

/* Allocate storage for this NAPTR answer appending it to the list */
naptr_curr = ares_malloc_data(ARES_DATATYPE_NAPTR_REPLY);
if (!naptr_curr)
{
status = ARES_ENOMEM;
break;
}
if (naptr_last)
{
naptr_last->next = naptr_curr;
}
else
{
naptr_head = naptr_curr;
}
naptr_last = naptr_curr;

vptr = aptr;
naptr_curr->order = DNS__16BIT(vptr);
vptr += sizeof(unsigned short);
naptr_curr->preference = DNS__16BIT(vptr);
vptr += sizeof(unsigned short);

status = ares_expand_string(vptr, abuf, alen, &naptr_curr->flags, &len);
if (status != ARES_SUCCESS)
break;
vptr += len;

status = ares_expand_string(vptr, abuf, alen, &naptr_curr->service, &len);
if (status != ARES_SUCCESS)
break;
vptr += len;

status = ares_expand_string(vptr, abuf, alen, &naptr_curr->regexp, &len);
if (status != ARES_SUCCESS)
break;
vptr += len;

status = ares_expand_name(vptr, abuf, alen, &naptr_curr->replacement, &len);
if (status != ARES_SUCCESS)
break;
}

/* Don't lose memory in the next iteration */
free (rr_name);
rr_name = NULL;

/* Move on to the next record */
aptr += rr_len;
}

if (hostname)
free (hostname);
if (rr_name)
free (rr_name);

/* clean up on error */
if (status != ARES_SUCCESS)
{
if (naptr_head)
ares_free_data (naptr_head);
return status;
}

/* everything looks fine, return the data */
*naptr_out = naptr_head;

return ARES_SUCCESS;
}

@@ -42,6 +42,7 @@
#include <string.h>
#include "ares.h"
#include "ares_dns.h"
#include "ares_nowarn.h"
#include "ares_private.h"

int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
@@ -189,8 +190,8 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
for (i=0 ; i<aliascnt ; i++)
hostent->h_aliases[i] = aliases[i];
hostent->h_aliases[aliascnt] = NULL;
hostent->h_addrtype = family;
hostent->h_length = addrlen;
hostent->h_addrtype = aresx_sitoss(family);
hostent->h_length = aresx_sitoss(addrlen);
memcpy(hostent->h_addr_list[0], addr, addrlen);
hostent->h_addr_list[1] = NULL;
*host = hostent;
@@ -0,0 +1,135 @@

/* Copyright 1998 by the Massachusetts Institute of Technology.
* Copyright (C) 2012 Marko Kreen <markokr@gmail.com>
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/

#include "ares_setup.h"

#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h>
#else
# include "nameser.h"
#endif
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
# include <arpa/nameser_compat.h>
#endif

#include <stdlib.h>
#include <string.h>
#include "ares.h"
#include "ares_dns.h"
#include "ares_data.h"
#include "ares_private.h"

int
ares_parse_soa_reply(const unsigned char *abuf, int alen,
struct ares_soa_reply **soa_out)
{
const unsigned char *aptr;
long len;
char *qname = NULL, *rr_name = NULL;
struct ares_soa_reply *soa = NULL;
int qdcount, ancount;
int status;

if (alen < HFIXEDSZ)
return ARES_EBADRESP;

/* parse message header */
qdcount = DNS_HEADER_QDCOUNT(abuf);
ancount = DNS_HEADER_ANCOUNT(abuf);
if (qdcount != 1 || ancount != 1)
return ARES_EBADRESP;
aptr = abuf + HFIXEDSZ;

/* query name */
status = ares__expand_name_for_response(aptr, abuf, alen, &qname, &len);
if (status != ARES_SUCCESS)
goto failed_stat;
aptr += len;

/* skip qtype & qclass */
if (aptr + QFIXEDSZ > abuf + alen)
goto failed;
aptr += QFIXEDSZ;

/* rr_name */
status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len);
if (status != ARES_SUCCESS)
goto failed_stat;
aptr += len;

/* skip rr_type, rr_class, rr_ttl, rr_rdlen */
if (aptr + RRFIXEDSZ > abuf + alen)
goto failed;
aptr += RRFIXEDSZ;

/* allocate result struct */
soa = ares_malloc_data(ARES_DATATYPE_SOA_REPLY);
if (!soa)
return ARES_ENOMEM;

/* nsname */
status = ares__expand_name_for_response(aptr, abuf, alen, &soa->nsname, &len);
if (status != ARES_SUCCESS)
goto failed_stat;
aptr += len;

/* hostmaster */
status = ares__expand_name_for_response(aptr, abuf, alen, &soa->hostmaster, &len);
if (status != ARES_SUCCESS)
goto failed_stat;
aptr += len;

/* integer fields */
if (aptr + 5 * 4 > abuf + alen)
goto failed;
soa->serial = DNS__32BIT(aptr + 0 * 4);
soa->refresh = DNS__32BIT(aptr + 1 * 4);
soa->retry = DNS__32BIT(aptr + 2 * 4);
soa->expire = DNS__32BIT(aptr + 3 * 4);
soa->minttl = DNS__32BIT(aptr + 4 * 4);

free(qname);
free(rr_name);

*soa_out = soa;

return ARES_SUCCESS;

failed:
status = ARES_EBADRESP;

failed_stat:
ares_free_data(soa);
if (qname)
free(qname);
if (rr_name)
free(rr_name);
return status;
}

@@ -342,7 +342,7 @@ long ares__tvdiff(struct timeval t1, struct timeval t2);
do { \
if ((c)->sock_state_cb) \
(c)->sock_state_cb((c)->sock_state_cb_data, (s), (r), (w)); \
} while (0)
} WHILE_FALSE

#ifdef CURLDEBUG
/* This is low-level hard-hacking memory leak tracking and similar. Using the
@@ -1,6 +1,6 @@

/* Copyright 1998 by the Massachusetts Institute of Technology.
* Copyright (C) 2004-2010 by Daniel Stenberg
* Copyright (C) 2004-2012 by Daniel Stenberg
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
@@ -837,30 +837,29 @@ static int setsocknonblock(ares_socket_t sockfd, /* operate on this */
#elif defined(HAVE_IOCTL_FIONBIO)

/* older unix versions */
int flags;
flags = nonblock;
int flags = nonblock ? 1 : 0;
return ioctl(sockfd, FIONBIO, &flags);

#elif defined(HAVE_IOCTLSOCKET_FIONBIO)

#ifdef WATT32
char flags;
char flags = nonblock ? 1 : 0;
#else
/* Windows */
unsigned long flags;
unsigned long flags = nonblock ? 1UL : 0UL;
#endif
flags = nonblock;
return ioctlsocket(sockfd, FIONBIO, &flags);

#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO)

/* Amiga */
return IoctlSocket(sockfd, FIONBIO, (long)nonblock);
long flags = nonblock ? 1L : 0L;
return IoctlSocket(sockfd, FIONBIO, flags);

#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK)

/* BeOS */
long b = nonblock ? 1 : 0;
long b = nonblock ? 1L : 0L;
return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));

#else
@@ -947,7 +946,7 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server)
salen = sizeof(saddr.sa4);
memset(sa, 0, salen);
saddr.sa4.sin_family = AF_INET;
saddr.sa4.sin_port = (unsigned short)(channel->tcp_port & 0xffff);
saddr.sa4.sin_port = aresx_sitous(channel->tcp_port);
memcpy(&saddr.sa4.sin_addr, &server->addr.addrV4,
sizeof(server->addr.addrV4));
break;
@@ -956,7 +955,7 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server)
salen = sizeof(saddr.sa6);
memset(sa, 0, salen);
saddr.sa6.sin6_family = AF_INET6;
saddr.sa6.sin6_port = (unsigned short)(channel->tcp_port & 0xffff);
saddr.sa6.sin6_port = aresx_sitous(channel->tcp_port);
memcpy(&saddr.sa6.sin6_addr, &server->addr.addrV6,
sizeof(server->addr.addrV6));
break;
@@ -1039,7 +1038,7 @@ static int open_udp_socket(ares_channel channel, struct server_state *server)
salen = sizeof(saddr.sa4);
memset(sa, 0, salen);
saddr.sa4.sin_family = AF_INET;
saddr.sa4.sin_port = (unsigned short)(channel->udp_port & 0xffff);
saddr.sa4.sin_port = aresx_sitous(channel->udp_port);
memcpy(&saddr.sa4.sin_addr, &server->addr.addrV4,
sizeof(server->addr.addrV4));
break;
@@ -1048,7 +1047,7 @@ static int open_udp_socket(ares_channel channel, struct server_state *server)
salen = sizeof(saddr.sa6);
memset(sa, 0, salen);
saddr.sa6.sin6_family = AF_INET6;
saddr.sa6.sin6_port = (unsigned short)(channel->udp_port & 0xffff);
saddr.sa6.sin6_port = aresx_sitous(channel->udp_port);
memcpy(&saddr.sa6.sin6_addr, &server->addr.addrV6,
sizeof(server->addr.addrV6));
break;
@@ -77,7 +77,7 @@ void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen,
}

/* Compute the query ID. Start with no timeout. */
query->qid = (unsigned short)DNS_HEADER_QID(qbuf);
query->qid = DNS_HEADER_QID(qbuf);
query->timeout.tv_sec = 0;
query->timeout.tv_usec = 0;

@@ -2,7 +2,7 @@
#define HEADER_CARES_SETUP_H


/* Copyright (C) 2004 - 2009 by Daniel Stenberg et al
/* Copyright (C) 2004 - 2012 by Daniel Stenberg et al
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
@@ -75,7 +75,9 @@
/* please, do it beyond the point further indicated in this file. */
/* ================================================================ */

#if 0 /* libuv hack */
#if 1 /* libuv hack */
#include <errno.h> /* needed on windows */
#else
/*
* c-ares external interface definitions are also used internally,
* and might also include required system header files to define them.
@@ -159,12 +161,32 @@

#endif /* HAVE_CONFIG_H */

/*
* Arg 2 type for gethostname in case it hasn't been defined in config file.
*/

#ifndef GETHOSTNAME_TYPE_ARG2
# ifdef USE_WINSOCK
# define GETHOSTNAME_TYPE_ARG2 int
# else
# define GETHOSTNAME_TYPE_ARG2 size_t
# endif
#endif

#ifdef __POCC__
# include <sys/types.h>
# include <unistd.h>
# define ESRCH 3
#endif

/*
* Android does have the arpa/nameser.h header which is detected by configure
* but it appears to be empty with recent NDK r7b / r7c, so we undefine here.
*/
#if (defined(ANDROID) || defined(__ANDROID__)) && defined(HAVE_ARPA_NAMESER_H)
# undef HAVE_ARPA_NAMESER_H
#endif

/*
* Recent autoconf versions define these symbols in ares_config.h. We don't
* want them (since they collide with the libcurl ones when we build
@@ -62,19 +62,20 @@ struct timeval *ares_timeout(ares_channel channel, struct timeval *maxtv,
min_offset = offset;
}

if(min_offset != -1) {
nextstop.tv_sec = min_offset/1000;
nextstop.tv_usec = (min_offset%1000)*1000;
}

/* If we found a minimum timeout and it's sooner than the one specified in
* maxtv (if any), return it. Otherwise go with maxtv.
*/
if (min_offset != -1 && (!maxtv || ares__timedout(maxtv, &nextstop)))
if (min_offset != -1)
{
*tvbuf = nextstop;
return tvbuf;
nextstop.tv_sec = min_offset/1000;
nextstop.tv_usec = (min_offset%1000)*1000;

if (!maxtv || ares__timedout(maxtv, &nextstop))
{
*tvbuf = nextstop;
return tvbuf;
}
}
else
return maxtv;

return maxtv;
}
@@ -2,7 +2,7 @@
#define __SETUP_ONCE_H


/* Copyright (C) 2004 - 2011 by Daniel Stenberg et al
/* Copyright (C) 2004 - 2012 by Daniel Stenberg et al
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
@@ -72,7 +72,7 @@
#include <fcntl.h>
#endif

#ifdef HAVE_STDBOOL_H
#if defined(HAVE_STDBOOL_H) && defined(HAVE_BOOL_T)
#include <stdbool.h>
#endif

@@ -299,6 +299,27 @@ struct timeval {
#endif


/*
* Macro WHILE_FALSE may be used to build single-iteration do-while loops,
* avoiding compiler warnings. Mostly intended for other macro definitions.
*/

#define WHILE_FALSE while(0)

#if defined(_MSC_VER) && !defined(__POCC__)
# undef WHILE_FALSE
# if (_MSC_VER < 1500)
# define WHILE_FALSE while(1, 0)
# else
# define WHILE_FALSE \
__pragma(warning(push)) \
__pragma(warning(disable:4127)) \
while(0) \
__pragma(warning(pop))
# endif
#endif


/*
* Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type.
*/
@@ -336,7 +357,7 @@ typedef int sig_atomic_t;
#ifdef DEBUGBUILD
#define DEBUGF(x) x
#else
#define DEBUGF(x) do { } while (0)
#define DEBUGF(x) do { } WHILE_FALSE
#endif


@@ -347,7 +368,7 @@ typedef int sig_atomic_t;
#if defined(DEBUGBUILD) && defined(HAVE_ASSERT_H)
#define DEBUGASSERT(x) assert(x)
#else
#define DEBUGASSERT(x) do { } while (0)
#define DEBUGASSERT(x) do { } WHILE_FALSE
#endif


@@ -459,18 +480,6 @@ typedef int sig_atomic_t;
#endif


/*
* System error codes for Windows CE
*/

#if defined(WIN32) && !defined(HAVE_ERRNO_H)
#define ENOENT ERROR_FILE_NOT_FOUND
#define ESRCH ERROR_PATH_NOT_FOUND
#define ENOMEM ERROR_NOT_ENOUGH_MEMORY
#define ENOSPC ERROR_INVALID_PARAMETER
#endif


/*
* Actually use __32_getpwuid() on 64-bit VMS builds for getpwuid()
*/
@@ -501,4 +510,3 @@ typedef int sig_atomic_t;


#endif /* __SETUP_ONCE_H */

@@ -30,6 +30,36 @@ static int uv__async_init(uv_loop_t* loop);
static void uv__async_io(uv_loop_t* loop, uv__io_t* handle, int events);


__attribute__((always_inline))
inline static int uv__async_make_pending(volatile sig_atomic_t* ptr) {
/* Do a cheap read first. */
if (*ptr)
return 1;

/* Micro-optimization: use atomic memory operations to detect if we've been
* preempted by another thread and don't have to make an expensive syscall.
* This speeds up the heavily contended case by about 1-2% and has little
* if any impact on the non-contended case.
*
* Use XCHG instead of the CMPXCHG that __sync_val_compare_and_swap() emits
* on x86, it's about 4x faster. It probably makes zero difference in the
* grand scheme of things but I'm OCD enough not to let this one pass.
*/
#if __i386__ || __x86_64__
{
unsigned int val = 1;
__asm__ __volatile__("xchgl %0, %1" : "+r" (val) : "m" (*ptr));
return val != 0;
}
#elif __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 1 /* gcc >= 4.1 */
return __sync_val_compare_and_swap(ptr, 0, 1) != 0;
#else
*ptr = 1;
return 1;
#endif
}


int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
if (uv__async_init(loop))
return uv__set_sys_error(loop, errno);
@@ -50,7 +80,8 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
int uv_async_send(uv_async_t* handle) {
int r;

handle->pending = 1; /* XXX needs a memory barrier? */
if (uv__async_make_pending(&handle->pending))
return 0; /* already pending */

do
r = write(handle->loop->async_pipefd[1], "x", 1);
@@ -228,7 +228,7 @@ void uv_loop_delete(uv_loop_t* loop) {


static unsigned int uv__poll_timeout(uv_loop_t* loop) {
if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))
if (!uv__has_active_handles(loop))
return 0;

if (!ngx_queue_empty(&loop->idle_handles))
@@ -298,9 +298,15 @@ static int uv_getaddrinfo_done(eio_req* req_) {

uv__req_unregister(req->loop, req);

free(req->hints);
free(req->service);
free(req->hostname);
/* see initialization in uv_getaddrinfo() */
if (req->hints)
free(req->hints);
else if (req->service)
free(req->service);
else if (req->hostname)
free(req->hostname);
else
assert(0);

if (req->retcode == 0) {
/* OK */
@@ -325,62 +331,81 @@ static int uv_getaddrinfo_done(eio_req* req_) {
}


static void getaddrinfo_thread_proc(eio_req *req) {
uv_getaddrinfo_t* handle = req->data;
static void getaddrinfo_thread_proc(eio_req *req_) {
uv_getaddrinfo_t* req = req_->data;

handle->retcode = getaddrinfo(handle->hostname,
handle->service,
handle->hints,
&handle->res);
req->retcode = getaddrinfo(req->hostname,
req->service,
req->hints,
&req->res);
}


/* stub implementation of uv_getaddrinfo */
int uv_getaddrinfo(uv_loop_t* loop,
uv_getaddrinfo_t* handle,
uv_getaddrinfo_t* req,
uv_getaddrinfo_cb cb,
const char* hostname,
const char* service,
const struct addrinfo* hints) {
eio_req* req;
size_t hostname_len;
size_t service_len;
size_t hints_len;
eio_req* req_;
size_t len;
char* buf;

if (req == NULL || cb == NULL || (hostname == NULL && service == NULL))
return uv__set_artificial_error(loop, UV_EINVAL);

uv_eio_init(loop);

if (handle == NULL || cb == NULL ||
(hostname == NULL && service == NULL)) {
uv__set_artificial_error(loop, UV_EINVAL);
return -1;
}
hostname_len = hostname ? strlen(hostname) + 1 : 0;
service_len = service ? strlen(service) + 1 : 0;
hints_len = hints ? sizeof(*hints) : 0;
buf = malloc(hostname_len + service_len + hints_len);

uv__req_init(loop, handle, UV_GETADDRINFO);
handle->loop = loop;
handle->cb = cb;
if (buf == NULL)
return uv__set_artificial_error(loop, UV_ENOMEM);

/* TODO don't alloc so much. */
uv__req_init(loop, req, UV_GETADDRINFO);
req->loop = loop;
req->cb = cb;
req->res = NULL;
req->hints = NULL;
req->service = NULL;
req->hostname = NULL;
req->retcode = 0;

/* order matters, see uv_getaddrinfo_done() */
len = 0;

if (hints) {
handle->hints = malloc(sizeof(struct addrinfo));
memcpy(handle->hints, hints, sizeof(struct addrinfo));
req->hints = memcpy(buf + len, hints, sizeof(*hints));
len += sizeof(*hints);
}
else {
handle->hints = NULL;

if (service) {
req->service = memcpy(buf + len, service, service_len);
len += service_len;
}

/* TODO security! check lengths, check return values. */
if (hostname) {
req->hostname = memcpy(buf + len, hostname, hostname_len);
len += hostname_len;
}

handle->hostname = hostname ? strdup(hostname) : NULL;
handle->service = service ? strdup(service) : NULL;
handle->res = NULL;
handle->retcode = 0;
req_ = eio_custom(getaddrinfo_thread_proc,
EIO_PRI_DEFAULT,
uv_getaddrinfo_done,
req,
&loop->uv_eio_channel);

/* TODO check handle->hostname == NULL */
/* TODO check handle->service == NULL */
if (req_)
return 0;

req = eio_custom(getaddrinfo_thread_proc, EIO_PRI_DEFAULT,
uv_getaddrinfo_done, handle, &loop->uv_eio_channel);
assert(req);
assert(req->data == handle);
free(buf);

return 0;
return uv__set_artificial_error(loop, UV_ENOMEM);
}


@@ -470,17 +495,34 @@ int uv__accept(int sockfd) {
}


#if __linux__

int uv__nonblock(int fd, int set) {
int r;

#if FIONBIO
do
r = ioctl(fd, FIONBIO, &set);
while (r == -1 && errno == EINTR);

return r;
#else
}


int uv__cloexec(int fd, int set) {
int r;

do
r = ioctl(fd, set ? FIOCLEX : FIONCLEX);
while (r == -1 && errno == EINTR);

return r;
}

#else /* !__linux__ */

int uv__nonblock(int fd, int set) {
int flags;
int r;

do
r = fcntl(fd, F_GETFL);
@@ -499,23 +541,13 @@ int uv__nonblock(int fd, int set) {
while (r == -1 && errno == EINTR);

return r;
#endif
}


int uv__cloexec(int fd, int set) {
int flags;
int r;

#if __linux__
/* Linux knows only FD_CLOEXEC so we can safely omit the fcntl(F_GETFD)
* syscall. CHECKME: That's probably true for other Unices as well.
*/
if (set)
flags = FD_CLOEXEC;
else
flags = 0;
#else
do
r = fcntl(fd, F_GETFD);
while (r == -1 && errno == EINTR);
@@ -527,7 +559,6 @@ int uv__cloexec(int fd, int set) {
flags = r | FD_CLOEXEC;
else
flags = r & ~FD_CLOEXEC;
#endif

do
r = fcntl(fd, F_SETFD, flags);
@@ -536,6 +567,8 @@ int uv__cloexec(int fd, int set) {
return r;
}

#endif /* __linux__ */


/* This function is not execve-safe, there is a race window
* between the call to dup() and fcntl(FD_CLOEXEC).
@@ -211,7 +211,8 @@ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
uv_cpu_info_t* cpu_info;

size = sizeof(model);
if (sysctlbyname("hw.model", &model, &size, NULL, 0) < 0) {
if (sysctlbyname("machdep.cpu.brand_string", &model, &size, NULL, 0) < 0 &&
sysctlbyname("hw.model", &model, &size, NULL, 0) < 0) {
return uv__new_sys_error(errno);
}
size = sizeof(cpuspeed);
@@ -139,23 +139,9 @@ char** uv_setup_args(int argc, char** argv) {


uv_err_t uv_set_process_title(const char* title) {
int oid[4];

if (process_title) free(process_title);
process_title = strdup(title);

oid[0] = CTL_KERN;
oid[1] = KERN_PROC;
oid[2] = KERN_PROC_ARGS;
oid[3] = getpid();

sysctl(oid,
ARRAY_SIZE(oid),
NULL,
NULL,
process_title,
strlen(process_title) + 1);

setproctitle(title);
return uv_ok_;
}

@@ -275,7 +261,7 @@ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
return uv__new_sys_error(ENOMEM);
}

if (sysctlbyname("kern.cp_times", cp_times, &size, NULL, 0) < 0) {
if (sysctlbyname("kern.cp_times", &cp_times, &size, NULL, 0) < 0) {
free(cp_times);
free(*cpu_infos);
return uv__new_sys_error(errno);
@@ -139,6 +139,8 @@ int uv__stream_open(uv_stream_t*, int fd, int flags);
void uv__stream_destroy(uv_stream_t* stream);
void uv__server_io(uv_loop_t* loop, uv__io_t* watcher, int events);
int uv__accept(int sockfd);
int uv__connect(uv_connect_t* req, uv_stream_t* stream, struct sockaddr* addr,
socklen_t addrlen, uv_connect_cb cb);

/* tcp */
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb);
@@ -69,6 +69,56 @@
# endif
#endif /* __NR_eventfd2 */

#ifndef __NR_epoll_create
# if __x86_64__
# define __NR_epoll_create 213
# elif __i386__
# define __NR_epoll_create 254
# elif __arm__
# define __NR_epoll_create (UV_SYSCALL_BASE + 250)
# endif
#endif /* __NR_epoll_create */

#ifndef __NR_epoll_create1
# if __x86_64__
# define __NR_epoll_create1 291
# elif __i386__
# define __NR_epoll_create1 329
# elif __arm__
# define __NR_epoll_create1 (UV_SYSCALL_BASE + 357)
# endif
#endif /* __NR_epoll_create1 */

#ifndef __NR_epoll_ctl
# if __x86_64__
# define __NR_epoll_ctl 233 /* used to be 214 */
# elif __i386__
# define __NR_epoll_ctl 255
# elif __arm__
# define __NR_epoll_ctl (UV_SYSCALL_BASE + 251)
# endif
#endif /* __NR_epoll_ctl */

#ifndef __NR_epoll_wait
# if __x86_64__
# define __NR_epoll_wait 232 /* used to be 215 */
# elif __i386__
# define __NR_epoll_wait 256
# elif __arm__
# define __NR_epoll_wait (UV_SYSCALL_BASE + 252)
# endif
#endif /* __NR_epoll_wait */

#ifndef __NR_epoll_pwait
# if __x86_64__
# define __NR_epoll_pwait 281
# elif __i386__
# define __NR_epoll_pwait 319
# elif __arm__
# define __NR_epoll_pwait (UV_SYSCALL_BASE + 346)
# endif
#endif /* __NR_epoll_pwait */

#ifndef __NR_inotify_init
# if __x86_64__
# define __NR_inotify_init 253
@@ -197,6 +247,64 @@ int uv__eventfd2(unsigned int count, int flags) {
}


int uv__epoll_create(void) {
#if __NR_epoll_create
return syscall(__NR_epoll_create);
#else
return errno = ENOSYS, -1;
#endif
}


int uv__epoll_create1(int flags) {
#if __NR_epoll_create1
return syscall(__NR_epoll_create1, flags);
#else
return errno = ENOSYS, -1;
#endif
}


int uv__epoll_ctl(int epfd, int op, int fd, struct uv__epoll_event* events) {
#if __NR_epoll_ctl
return syscall(__NR_epoll_ctl, epfd, op, fd, events);
#else
return errno = ENOSYS, -1;
#endif
}


int uv__epoll_wait(int epfd,
struct uv__epoll_event* events,
int nevents,
int timeout) {
#if __NR_epoll_wait
return syscall(__NR_epoll_wait, epfd, events, nevents, timeout);
#else
return errno = ENOSYS, -1;
#endif
}


int uv__epoll_pwait(int epfd,
struct uv__epoll_event* events,
int nevents,
int timeout,
const sigset_t* sigmask) {
#if __NR_epoll_pwait
return syscall(__NR_epoll_pwait,
epfd,
events,
nevents,
timeout,
sigmask,
sizeof(*sigmask));
#else
return errno = ENOSYS, -1;
#endif
}


int uv__inotify_init(void) {
#if __NR_inotify_init
return syscall(__NR_inotify_init);
@@ -25,6 +25,7 @@
#undef _GNU_SOURCE
#define _GNU_SOURCE

#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/types.h>
@@ -41,6 +42,19 @@
#define UV__SOCK_CLOEXEC UV__O_CLOEXEC
#define UV__SOCK_NONBLOCK UV__O_NONBLOCK

/* epoll flags */
#define UV__EPOLL_CLOEXEC UV__O_CLOEXEC
#define UV__EPOLL_CTL_ADD 1
#define UV__EPOLL_CTL_DEL 2
#define UV__EPOLL_CTL_MOD 3

#define UV__EPOLLIN 1
#define UV__EPOLLOUT 4
#define UV__EPOLLERR 8
#define UV__EPOLLHUP 16
#define UV__EPOLLONESHOT 0x40000000
#define UV__EPOLLET 0x80000000

/* inotify flags */
#define UV__IN_ACCESS 0x001
#define UV__IN_MODIFY 0x002
@@ -55,6 +69,11 @@
#define UV__IN_DELETE_SELF 0x400
#define UV__IN_MOVE_SELF 0x800

struct uv__epoll_event {
__u32 events;
__u64 data;
} __attribute__((packed));

struct uv__inotify_event {
__s32 wd;
__u32 mask;
@@ -70,6 +89,18 @@ struct uv__mmsghdr {

int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags);
int uv__eventfd(unsigned int count);
int uv__epoll_create(void);
int uv__epoll_create1(int flags);
int uv__epoll_ctl(int epfd, int op, int fd, struct uv__epoll_event *ev);
int uv__epoll_wait(int epfd,
struct uv__epoll_event* events,
int nevents,
int timeout);
int uv__epoll_pwait(int epfd,
struct uv__epoll_event* events,
int nevents,
int timeout,
const sigset_t* sigmask);
int uv__eventfd2(unsigned int count, int flags);
int uv__inotify_init(void);
int uv__inotify_init1(int flags);
@@ -170,17 +170,18 @@ void uv_pipe_connect(uv_connect_t* req,
uv_connect_cb cb) {
struct sockaddr_un saddr;
int saved_errno;
int new_sock;
int err;
int sockfd;
int status;
int r;

saved_errno = errno;
new_sock = (handle->fd == -1);
err = -1;
sockfd = -1;
status = -1;

if (new_sock)
if ((handle->fd = uv__socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
goto out;
if ((sockfd = uv__socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
uv__set_sys_error(handle->loop, errno);
goto out;
}

memset(&saddr, 0, sizeof saddr);
uv_strlcpy(saddr.sun_path, name, sizeof(saddr.sun_path));
@@ -190,25 +191,25 @@ void uv_pipe_connect(uv_connect_t* req,
* is either there or not.
*/
do {
r = connect(handle->fd, (struct sockaddr*)&saddr, sizeof saddr);
r = connect(sockfd, (struct sockaddr*)&saddr, sizeof saddr);
}
while (r == -1 && errno == EINTR);

if (r == -1)
if (r == -1) {
status = errno;
close(sockfd);
goto out;
}

if (new_sock)
if (uv__stream_open((uv_stream_t*)handle,
handle->fd,
UV_STREAM_READABLE | UV_STREAM_WRITABLE))
goto out;

uv__stream_open((uv_stream_t*)handle,
sockfd,
UV_STREAM_READABLE | UV_STREAM_WRITABLE);
uv__io_start(handle->loop, &handle->read_watcher);
uv__io_start(handle->loop, &handle->write_watcher);
err = 0;
status = 0;

out:
handle->delayed_error = err ? errno : 0; /* Passed to callback. */
handle->delayed_error = status; /* Passed to callback. */
handle->connect_req = req;

uv__req_init(handle->loop, req, UV_CONNECT);
@@ -784,6 +784,9 @@ static void uv__stream_connect(uv_stream_t* stream) {
if (error == EINPROGRESS)
return;

if (error == 0)
uv__io_start(stream->loop, &stream->read_watcher);

stream->connect_req = NULL;
uv__req_unregister(stream->loop, req);

@@ -794,6 +797,65 @@ static void uv__stream_connect(uv_stream_t* stream) {
}


int uv__connect(uv_connect_t* req, uv_stream_t* stream, struct sockaddr* addr,
socklen_t addrlen, uv_connect_cb cb) {
int sockfd;
int r;

if (stream->type != UV_TCP)
return uv__set_sys_error(stream->loop, ENOTSOCK);

if (stream->connect_req)
return uv__set_sys_error(stream->loop, EALREADY);

if (stream->fd <= 0) {
sockfd = uv__socket(addr->sa_family, SOCK_STREAM, 0);

if (sockfd == -1)
return uv__set_sys_error(stream->loop, errno);

if (uv__stream_open(stream,
sockfd,
UV_STREAM_READABLE | UV_STREAM_WRITABLE)) {
close(sockfd);
return -1;
}
}

stream->delayed_error = 0;

do
r = connect(stream->fd, addr, addrlen);
while (r == -1 && errno == EINTR);

if (r == -1) {
if (errno == EINPROGRESS)
; /* not an error */
else if (errno == ECONNREFUSED)
/* If we get a ECONNREFUSED wait until the next tick to report the
* error. Solaris wants to report immediately--other unixes want to
* wait.
*/
stream->delayed_error = errno;
else
return uv__set_sys_error(stream->loop, errno);
}

uv__req_init(stream->loop, req, UV_CONNECT);
req->cb = cb;
req->handle = stream;
ngx_queue_init(&req->queue);
stream->connect_req = req;

uv__io_start(stream->loop, &stream->write_watcher);

if (stream->delayed_error)
uv__io_feed(stream->loop, &stream->write_watcher, UV__IO_WRITE);

return 0;
}


int uv_write2(uv_write_t* req, uv_stream_t* stream, uv_buf_t bufs[], int bufcnt,
uv_stream_t* send_handle, uv_write_cb cb) {
int empty_queue;
@@ -75,7 +75,6 @@ uint64_t uv_hrtime() {
*/
int uv_exepath(char* buffer, size_t* size) {
ssize_t res;
pid_t pid;
char buf[128];

if (buffer == NULL)
@@ -84,8 +83,7 @@ int uv_exepath(char* buffer, size_t* size) {
if (size == NULL)
return (-1);

pid = getpid();
(void) snprintf(buf, sizeof (buf), "/proc/%d/path/a.out", pid);
(void) snprintf(buf, sizeof(buf), "/proc/%lu/path/a.out", (unsigned long) getpid());
res = readlink(buf, buffer, *size - 1);

if (res < 0)
@@ -128,26 +126,27 @@ static void uv__fs_event_rearm(uv_fs_event_t *handle) {
}


static void uv__fs_event_read(EV_P_ ev_io* w, int revents) {
static void uv__fs_event_read(uv_loop_t* loop, uv__io_t* w, int revents) {
uv_fs_event_t *handle;
uv_loop_t *loop_;
timespec_t timeout;
port_event_t pe;
int events;
int r;

loop_ = container_of(w, uv_loop_t, fs_event_watcher);
(void) w;
(void) revents;

do {
/* TODO use port_getn() */
do {
memset(&timeout, 0, sizeof timeout);
r = port_get(loop_->fs_fd, &pe, &timeout);
r = port_get(loop->fs_fd, &pe, &timeout);
}
while (r == -1 && errno == EINTR);

if (r == -1 && errno == ETIME)
break;

handle = (uv_fs_event_t *)pe.portev_user;
assert((r == 0) && "unexpected port_get() error");

@@ -199,8 +198,8 @@ int uv_fs_event_init(uv_loop_t* loop,
uv__fs_event_rearm(handle);

if (first_run) {
ev_io_init(&loop->fs_event_watcher, uv__fs_event_read, portfd, EV_READ);
ev_io_start(loop->ev, &loop->fs_event_watcher);
uv__io_init(&loop->fs_event_watcher, uv__fs_event_read, portfd, UV__IO_READ);
uv__io_start(loop, &loop->fs_event_watcher);
}

return 0;
@@ -433,7 +432,8 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
address = *addresses;

for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
bzero(&ip, sizeof (ip));
memset(&ip, 0, sizeof(ip));

if (!(ent->ifa_flags & IFF_UP && ent->ifa_flags & IFF_RUNNING)) {
continue;
}
@@ -34,26 +34,6 @@ int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) {
}


static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) {
int sockfd;

if (handle->fd != -1)
return 0;

sockfd = uv__socket(domain, SOCK_STREAM, 0);

if (sockfd == -1)
return uv__set_sys_error(handle->loop, errno);

if (uv__stream_open((uv_stream_t*)handle, sockfd, flags)) {
close(sockfd);
return -1;
}

return 0;
}


static int uv__bind(uv_tcp_t* tcp,
int domain,
struct sockaddr* addr,
@@ -64,8 +44,23 @@ static int uv__bind(uv_tcp_t* tcp,
saved_errno = errno;
status = -1;

if (maybe_new_socket(tcp, domain, UV_STREAM_READABLE|UV_STREAM_WRITABLE))
return -1;
if (tcp->fd < 0) {
if ((tcp->fd = uv__socket(domain, SOCK_STREAM, 0)) == -1) {
uv__set_sys_error(tcp->loop, errno);
goto out;
}

if (uv__stream_open((uv_stream_t*)tcp,
tcp->fd,
UV_STREAM_READABLE | UV_STREAM_WRITABLE)) {
close(tcp->fd);
tcp->fd = -1;
status = -2;
goto out;
}
}

assert(tcp->fd >= 0);

tcp->delayed_error = 0;
if (bind(tcp->fd, addr, addrsize) == -1) {
@@ -84,58 +79,6 @@ static int uv__bind(uv_tcp_t* tcp,
}


static int uv__connect(uv_connect_t* req,
uv_tcp_t* handle,
struct sockaddr* addr,
socklen_t addrlen,
uv_connect_cb cb) {
int r;

assert(handle->type == UV_TCP);

if (handle->connect_req)
return uv__set_sys_error(handle->loop, EALREADY);

if (maybe_new_socket(handle,
addr->sa_family,
UV_STREAM_READABLE|UV_STREAM_WRITABLE)) {
return -1;
}

handle->delayed_error = 0;

do
r = connect(handle->fd, addr, addrlen);
while (r == -1 && errno == EINTR);

if (r == -1) {
if (errno == EINPROGRESS)
; /* not an error */
else if (errno == ECONNREFUSED)
/* If we get a ECONNREFUSED wait until the next tick to report the
* error. Solaris wants to report immediately--other unixes want to
* wait.
*/
handle->delayed_error = errno;
else
return uv__set_sys_error(handle->loop, errno);
}

uv__req_init(handle->loop, req, UV_CONNECT);
req->cb = cb;
req->handle = (uv_stream_t*) handle;
ngx_queue_init(&req->queue);
handle->connect_req = req;

uv__io_start(handle->loop, &handle->write_watcher);

if (handle->delayed_error)
uv__io_feed(handle->loop, &handle->write_watcher, UV__IO_WRITE);

return 0;
}


int uv__tcp_bind(uv_tcp_t* handle, struct sockaddr_in addr) {
return uv__bind(handle,
AF_INET,
@@ -227,14 +170,33 @@ int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name,


int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
if (tcp->delayed_error)
return uv__set_sys_error(tcp->loop, tcp->delayed_error);
int r;

if (maybe_new_socket(tcp, AF_INET, UV_STREAM_READABLE))
if (tcp->delayed_error) {
uv__set_sys_error(tcp->loop, tcp->delayed_error);
return -1;
}

if (listen(tcp->fd, backlog))
return uv__set_sys_error(tcp->loop, errno);
if (tcp->fd < 0) {
if ((tcp->fd = uv__socket(AF_INET, SOCK_STREAM, 0)) == -1) {
uv__set_sys_error(tcp->loop, errno);
return -1;
}

if (uv__stream_open((uv_stream_t*)tcp, tcp->fd, UV_STREAM_READABLE)) {
close(tcp->fd);
tcp->fd = -1;
return -1;
}
}

assert(tcp->fd >= 0);

r = listen(tcp->fd, backlog);
if (r < 0) {
uv__set_sys_error(tcp->loop, errno);
return -1;
}

tcp->connection_cb = cb;

@@ -247,31 +209,37 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {


int uv__tcp_connect(uv_connect_t* req,
uv_tcp_t* handle,
struct sockaddr_in addr,
uv_connect_cb cb) {
int saved_errno;
uv_tcp_t* handle,
struct sockaddr_in address,
uv_connect_cb cb) {
int saved_errno = errno;
int status;

saved_errno = errno;
status = uv__connect(req, handle, (struct sockaddr*)&addr, sizeof addr, cb);
errno = saved_errno;
status = uv__connect(req,
(uv_stream_t*)handle,
(struct sockaddr*)&address,
sizeof address,
cb);

errno = saved_errno;
return status;
}


int uv__tcp_connect6(uv_connect_t* req,
uv_tcp_t* handle,
struct sockaddr_in6 addr,
uv_connect_cb cb) {
int saved_errno;
uv_tcp_t* handle,
struct sockaddr_in6 address,
uv_connect_cb cb) {
int saved_errno = errno;
int status;

saved_errno = errno;
status = uv__connect(req, handle, (struct sockaddr*)&addr, sizeof addr, cb);
errno = saved_errno;
status = uv__connect(req,
(uv_stream_t*)handle,
(struct sockaddr*)&address,
sizeof address,
cb);

errno = saved_errno;
return status;
}

@@ -167,44 +167,6 @@ void uv_once(uv_once_t* guard, void (*callback)(void)) {
abort();
}

#if defined(__APPLE__) && defined(__MACH__)

int uv_sem_init(uv_sem_t* sem, unsigned int value) {
return semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, value);
}


void uv_sem_destroy(uv_sem_t* sem) {
if (semaphore_destroy(mach_task_self(), *sem))
abort();
}


void uv_sem_post(uv_sem_t* sem) {
if (semaphore_signal(*sem))
abort();
}


void uv_sem_wait(uv_sem_t* sem) {
if (semaphore_wait(*sem))
abort();
}


int uv_sem_trywait(uv_sem_t* sem) {
mach_timespec_t interval;

interval.tv_sec = 0;
interval.tv_nsec = 0;

if (semaphore_timedwait(*sem, interval) == KERN_SUCCESS)
return 0;
else
return -1;
}

#else /* !(defined(__APPLE__) && defined(__MACH__)) */

int uv_sem_init(uv_sem_t* sem, unsigned int value) {
return sem_init(sem, 0, value);
@@ -247,5 +209,3 @@ int uv_sem_trywait(uv_sem_t* sem) {

return r;
}

#endif /* defined(__APPLE__) && defined(__MACH__) */
@@ -64,7 +64,7 @@ static void prep_tcploopback()
optmask = ARES_OPT_SERVERS | ARES_OPT_TCP_PORT | ARES_OPT_FLAGS;
options.servers = &test_server.sin_addr;
options.nservers = 1;
options.tcp_port = htons(TEST_PORT_2);
options.tcp_port = TEST_PORT_2;
options.flags = ARES_FLAG_USEVC;

rc = uv_ares_init_options(loop, &channel, &options, optmask);
@@ -0,0 +1,97 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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.
*/

#include "task.h"
#include "uv.h"

#include <stdio.h>
#include <stdlib.h>

#define NUM_PINGS (1000 * 1000)

static unsigned int callbacks;
static volatile int done;


static void async_cb(uv_async_t* handle, int status) {
if (++callbacks == NUM_PINGS)
uv_close((uv_handle_t*) handle, NULL);
}


static void pummel(void* arg) {
while (!done)
uv_async_send((uv_async_t*) arg);
}


static int test_async_pummel(int nthreads) {
uv_thread_t* tids;
uv_async_t handle;
uint64_t time;
int i;

tids = calloc(nthreads, sizeof(tids[0]));
ASSERT(tids != NULL);

ASSERT(0 == uv_async_init(uv_default_loop(), &handle, async_cb));

for (i = 0; i < nthreads; i++)
ASSERT(0 == uv_thread_create(tids + i, pummel, &handle));

time = uv_hrtime();

ASSERT(0 == uv_run(uv_default_loop()));

time = uv_hrtime() - time;
done = 1;

for (i = 0; i < nthreads; i++)
ASSERT(0 == uv_thread_join(tids + i));

printf("%s callbacks in %.2f seconds (%s/sec)\n",
fmt(callbacks),
time / 1e9,
fmt(callbacks / (time / 1e9)));

free(tids);
return 0;
}


BENCHMARK_IMPL(async_pummel_1) {
return test_async_pummel(1);
}


BENCHMARK_IMPL(async_pummel_2) {
return test_async_pummel(2);
}


BENCHMARK_IMPL(async_pummel_4) {
return test_async_pummel(4);
}


BENCHMARK_IMPL(async_pummel_8) {
return test_async_pummel(8);
}
@@ -0,0 +1,137 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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.
*/

#include "task.h"
#include "uv.h"

#include <stdio.h>
#include <stdlib.h>

#define NUM_PINGS (1000 * 1000)

struct ctx {
uv_loop_t* loop;
uv_thread_t thread;
uv_async_t main_async; /* wake up main thread */
uv_async_t worker_async; /* wake up worker */
unsigned int nthreads;
unsigned int main_sent;
unsigned int main_seen;
unsigned int worker_sent;
unsigned int worker_seen;
};


static void worker_async_cb(uv_async_t* handle, int status) {
struct ctx* ctx = container_of(handle, struct ctx, worker_async);

ASSERT(0 == uv_async_send(&ctx->main_async));
ctx->worker_sent++;
ctx->worker_seen++;

if (ctx->worker_sent >= NUM_PINGS)
uv_close((uv_handle_t*) &ctx->worker_async, NULL);
}


static void main_async_cb(uv_async_t* handle, int status) {
struct ctx* ctx = container_of(handle, struct ctx, main_async);

ASSERT(0 == uv_async_send(&ctx->worker_async));
ctx->main_sent++;
ctx->main_seen++;

if (ctx->main_sent >= NUM_PINGS)
uv_close((uv_handle_t*) &ctx->main_async, NULL);
}


static void worker(void* arg) {
struct ctx* ctx = arg;
ASSERT(0 == uv_async_send(&ctx->main_async));
ASSERT(0 == uv_run(ctx->loop));
}


static int test_async(int nthreads) {
struct ctx* threads;
struct ctx* ctx;
uint64_t time;
int i;

threads = calloc(nthreads, sizeof(threads[0]));
ASSERT(threads != NULL);

for (i = 0; i < nthreads; i++) {
ctx = threads + i;
ctx->nthreads = nthreads;
ctx->loop = uv_loop_new();
ASSERT(ctx->loop != NULL);
ASSERT(0 == uv_async_init(ctx->loop, &ctx->worker_async, worker_async_cb));
ASSERT(0 == uv_async_init(uv_default_loop(), &ctx->main_async, main_async_cb));
ASSERT(0 == uv_thread_create(&ctx->thread, worker, ctx));
}

time = uv_hrtime();

ASSERT(0 == uv_run(uv_default_loop()));

for (i = 0; i < nthreads; i++)
ASSERT(0 == uv_thread_join(&threads[i].thread));

time = uv_hrtime() - time;

for (i = 0; i < nthreads; i++) {
ctx = threads + i;
ASSERT(ctx->worker_sent == NUM_PINGS);
ASSERT(ctx->worker_seen == NUM_PINGS);
ASSERT(ctx->main_sent == (unsigned int) NUM_PINGS);
ASSERT(ctx->main_seen == (unsigned int) NUM_PINGS);
}

printf("%.2f sec (%s/sec)\n",
time / 1e9,
fmt(NUM_PINGS / (time / 1e9)));

free(threads);

return 0;
}


BENCHMARK_IMPL(async1) {
return test_async(1);
}


BENCHMARK_IMPL(async2) {
return test_async(2);
}


BENCHMARK_IMPL(async4) {
return test_async(4);
}


BENCHMARK_IMPL(async8) {
return test_async(8);
}
@@ -43,35 +43,6 @@ struct async_req {
};


static const char* fmt(double d) {
uint64_t v;
char* p;

p = (char *) calloc(1, 32) + 31; /* leaks memory */
v = d;

#if 0 /* works but we don't care about fractional precision */
if (d - v >= 0.01) {
*--p = '0' + (uint64_t) (d * 100) % 10;
*--p = '0' + (uint64_t) (d * 10) % 10;
*--p = '.';
}
#endif

if (v == 0)
*--p = '0';

while (v) {
if (v) *--p = '0' + (v % 10), v /= 10;
if (v) *--p = '0' + (v % 10), v /= 10;
if (v) *--p = '0' + (v % 10), v /= 10;
if (v) *--p = ',';
}

return p;
}


static void warmup(const char* path) {
uv_fs_t reqs[MAX_CONCURRENT_REQS];
int i;
@@ -45,6 +45,14 @@ BENCHMARK_DECLARE (udp_packet_storm_1000v1000)
BENCHMARK_DECLARE (gethostbyname)
BENCHMARK_DECLARE (getaddrinfo)
BENCHMARK_DECLARE (fs_stat)
BENCHMARK_DECLARE (async1)
BENCHMARK_DECLARE (async2)
BENCHMARK_DECLARE (async4)
BENCHMARK_DECLARE (async8)
BENCHMARK_DECLARE (async_pummel_1)
BENCHMARK_DECLARE (async_pummel_2)
BENCHMARK_DECLARE (async_pummel_4)
BENCHMARK_DECLARE (async_pummel_8)
BENCHMARK_DECLARE (spawn)
BENCHMARK_DECLARE (thread_create)
BENCHMARK_DECLARE (million_timers)
@@ -108,6 +116,15 @@ TASK_LIST_START

BENCHMARK_ENTRY (fs_stat)

BENCHMARK_ENTRY (async1)
BENCHMARK_ENTRY (async2)
BENCHMARK_ENTRY (async4)
BENCHMARK_ENTRY (async8)
BENCHMARK_ENTRY (async_pummel_1)
BENCHMARK_ENTRY (async_pummel_2)
BENCHMARK_ENTRY (async_pummel_4)
BENCHMARK_ENTRY (async_pummel_8)

BENCHMARK_ENTRY (spawn)
BENCHMARK_ENTRY (thread_create)
BENCHMARK_ENTRY (million_timers)
@@ -40,6 +40,11 @@

/* Do platform-specific initialization. */
void platform_init(int argc, char **argv) {
/* Running the tests as root is not smart - don't do it. */
if (getuid() == 0) {
fprintf(stderr, "Running the tests as root is not safe.\n");
exit(1);
}
/* Disable stdio output buffering. */
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
@@ -37,6 +37,35 @@ static void log_progress(int total, int passed, int failed, const char* name) {
}


const char* fmt(double d) {
uint64_t v;
char* p;

p = (char *) calloc(1, 32) + 31; /* leaks memory */
v = d;

#if 0 /* works but we don't care about fractional precision */
if (d - v >= 0.01) {
*--p = '0' + (uint64_t) (d * 100) % 10;
*--p = '0' + (uint64_t) (d * 10) % 10;
*--p = '.';
}
#endif

if (v == 0)
*--p = '0';

while (v) {
if (v) *--p = '0' + (v % 10), v /= 10;
if (v) *--p = '0' + (v % 10), v /= 10;
if (v) *--p = '0' + (v % 10), v /= 10;
if (v) *--p = ',';
}

return p;
}


int run_tests(int timeout, int benchmark_output) {
int total, passed, failed;
task_entry_t* task;
@@ -106,4 +106,7 @@ typedef enum {
/* Pause the calling thread for a number of milliseconds. */
void uv_sleep(int msec);

/* Format big numbers nicely. WARNING: leaks memory. */
const char* fmt(double d);

#endif /* TASK_H_ */
@@ -47,7 +47,7 @@ TEST_IMPL(hrtime) {
/* Check that the difference between the two hrtime values is somewhat in */
/* the range we expect it to be. */
ASSERT(diff > (uint64_t) 25 * NANOSEC / MILLISEC);
ASSERT(diff < (uint64_t) 80 * NANOSEC / MILLISEC);
ASSERT(diff < (uint64_t) 60 * NANOSEC / MILLISEC);
--i;
}
return 0;
@@ -56,7 +56,6 @@ TEST_DECLARE (tcp_close)
TEST_DECLARE (tcp_flags)
TEST_DECLARE (tcp_write_error)
TEST_DECLARE (tcp_write_to_half_open_connection)
TEST_DECLARE (tcp_unexpected_read)
TEST_DECLARE (tcp_bind6_error_addrinuse)
TEST_DECLARE (tcp_bind6_error_addrnotavail)
TEST_DECLARE (tcp_bind6_error_fault)
@@ -252,7 +251,6 @@ TASK_LIST_START
TEST_ENTRY (tcp_flags)
TEST_ENTRY (tcp_write_error)
TEST_ENTRY (tcp_write_to_half_open_connection)
TEST_ENTRY (tcp_unexpected_read)

TEST_ENTRY (tcp_bind6_error_addrinuse)
TEST_ENTRY (tcp_bind6_error_addrnotavail)
@@ -36,11 +36,6 @@
static int close_cb_called = 0;


static void poll_cb_fail(uv_poll_t* handle, int status, int events) {
ASSERT(0 && "poll_fail_cb should never be called");
}


static void close_cb(uv_handle_t* handle) {
close_cb_called++;
}
@@ -23,27 +23,20 @@
#include "task.h"
#include <string.h>


static void set_title(const char* title) {
TEST_IMPL(process_title) {
char buffer[512];
uv_err_t err;

err = uv_get_process_title(buffer, sizeof(buffer));
ASSERT(UV_OK == err.code);

err = uv_set_process_title(title);
err = uv_set_process_title("new title");
ASSERT(UV_OK == err.code);

err = uv_get_process_title(buffer, sizeof(buffer));
ASSERT(UV_OK == err.code);

ASSERT(strcmp(buffer, title) == 0);
}
ASSERT(strcmp(buffer, "new title") == 0);


TEST_IMPL(process_title) {
/* Check for format string vulnerabilities. */
set_title("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s");
set_title("new title");
return 0;
}
@@ -71,12 +71,6 @@ static void exit_cb_failure_expected(uv_process_t* process, int exit_status,
}


static void exit_cb_unexpected(uv_process_t* process, int exit_status,
int term_signal) {
ASSERT(0 && "should not have been called");
}


static void kill_cb(uv_process_t* process, int exit_status, int term_signal) {
uv_err_t err;

@@ -804,6 +798,14 @@ TEST_IMPL(spawn_setgid_fails) {


#ifdef _WIN32

static void exit_cb_unexpected(uv_process_t* process,
int exit_status,
int term_signal) {
ASSERT(0 && "should not have been called");
}


TEST_IMPL(spawn_setuid_fails) {
int r;

This file was deleted.

@@ -29,6 +29,7 @@
'include',
'include/uv-private',
'src/',
'src/ares',
],
'direct_dependent_settings': {
'include_dirs': [ 'include' ],
@@ -85,8 +86,10 @@
'src/ares/ares_parse_aaaa_reply.c',
'src/ares/ares_parse_a_reply.c',
'src/ares/ares_parse_mx_reply.c',
'src/ares/ares_parse_naptr_reply.c',
'src/ares/ares_parse_ns_reply.c',
'src/ares/ares_parse_ptr_reply.c',
'src/ares/ares_parse_soa_reply.c',
'src/ares/ares_parse_srv_reply.c',
'src/ares/ares_parse_txt_reply.c',
'src/ares/ares_platform.h',
@@ -355,7 +358,6 @@
'test/test-tcp-write-error.c',
'test/test-tcp-write-to-half-open-connection.c',
'test/test-tcp-writealot.c',
'test/test-tcp-unexpected-read.c',
'test/test-threadpool.c',
'test/test-mutexes.c',
'test/test-thread.c',
@@ -405,6 +407,8 @@
'dependencies': [ 'uv' ],
'sources': [
'test/benchmark-ares.c',
'test/benchmark-async.c',
'test/benchmark-async-pummel.c',
'test/benchmark-fs-stat.c',
'test/benchmark-getaddrinfo.c',
'test/benchmark-list.h',