+2005-03-12 Hrvoje Niksic <hniksic@xemacs.org>
+
+ * utils.c (debug_test_md5): Moved to gen-md5.c.
+
+ * mswindows.h: Don't declare inet_ntop, since we don't use it.
+
+ * mswindows.h: For consistency, also wrap closesocket, it being
+ a Winsock call.
+
+ * mswindows.h: Don't declare sleep and usleep; we're defining
+ xsleep now.
+
+ * mswindows.h (mkdir): Don't special-case Borland C, _mkdir
+ works there as well.
+
+ * host.c: Don't include winsock header files; the correct ones
+ are already included by mswindows.h.
+
+ * mswindows.c (xsleep): Round toward the nearest millisecond
+ in an attempt to avoid average short sleeps.
+
+ * utils.c (wtimer_granularity): Report correct values for
+ Windows timers and for high-resolution timers.
+
+ * utils.c (wtimer_initialize_once): New function, called to
+ initialize the timer frequency.
+
+ * utils.c: Replace the use of GetSystemTime with high-resolution
+ counters under Windows. When high-resolution counters are
+ unavailable, use GetTickCount().
+
2005-03-15 Hrvoje Niksic <hniksic@xemacs.org>
* retr.c (fd_read_body): Undo the 2004-11-18 change. Instead,
/* Support for sending out cookies in HTTP requests, based on
previously stored cookies. Entry point is
`build_cookies_request'. */
+
+/* Return a count of how many times CHR occurs in STRING. */
+
+static int
+count_char (const char *string, char chr)
+{
+ const char *p;
+ int count = 0;
+ for (p = string; *p; p++)
+ if (*p == chr)
+ ++count;
+ return count;
+}
/* Find the cookie chains whose domains match HOST and store them to
DEST.
MD5_Final (result, ctx_imp);
#endif
}
+
+#if 0
+/* A debugging function for checking whether an MD5 library works. */
+
+#include "gen-md5.h"
+
+char *
+debug_test_md5 (char *buf)
+{
+ unsigned char raw[16];
+ static char res[33];
+ unsigned char *p1;
+ char *p2;
+ int cnt;
+ ALLOCA_MD5_CONTEXT (ctx);
+
+ gen_md5_init (ctx);
+ gen_md5_update ((unsigned char *)buf, strlen (buf), ctx);
+ gen_md5_finish (ctx, raw);
+
+ p1 = raw;
+ p2 = res;
+ cnt = 16;
+ while (cnt--)
+ {
+ *p2++ = XNUM_TO_digit (*p1 >> 4);
+ *p2++ = XNUM_TO_digit (*p1 & 0xf);
+ ++p1;
+ }
+ *p2 = '\0';
+
+ return res;
+}
+#endif
#include <assert.h>
#include <sys/types.h>
-#ifdef WINDOWS
-# include <winsock.h>
-# define SET_H_ERRNO(err) WSASetLastError (err)
-#else
+#ifndef WINDOWS
# include <sys/socket.h>
# include <netinet/in.h>
# ifndef __BEOS__
# endif
# include <netdb.h>
# define SET_H_ERRNO(err) ((void)(h_errno = (err)))
+#else /* WINDOWS */
+# define SET_H_ERRNO(err) WSASetLastError (err)
#endif /* WINDOWS */
#ifndef NO_ADDRESS
}
usleep (seconds * 1000000L);
#else /* not HAVE_USLEEP */
- SleepEx (seconds * 1000, FALSE);
+ SleepEx ((DWORD) (seconds * 1000 + .5), FALSE);
#endif /* not HAVE_USLEEP */
}
void
ws_startup (void)
{
- WORD requested;
WSADATA data;
- int err;
-
- requested = MAKEWORD (1, 1);
- err = WSAStartup (requested, &data);
+ WORD requested = MAKEWORD (1, 1);
+ int err = WSAStartup (requested, &data);
if (err != 0)
{
fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
return rc;
}
\f
-/* Wget expects network calls such as bind, connect, etc., to set errno.
- To achieve that, we place Winsock calls in wrapper functions that, in
- case of error, sets errno to the value of GetLastError(). In addition,
- we provide a wrapper around strerror, which recognizes Winsock errors
- and prints the appropriate error message. */
+/* Wget expects network calls such as connect, recv, send, etc., to set
+ errno on failure. To achieve that, Winsock calls are wrapped with code
+ that, in case of error, sets errno to the value of WSAGetLastError().
+ In addition, we provide a wrapper around strerror, which recognizes
+ Winsock errors and prints the appropriate error message. */
/* Define a macro that creates a function definition that wraps FUN into
a function that sets errno the way the rest of the code expects. */
-#define WRAP(fun, decl, call) int wrap_##fun decl { \
+#define WRAP(fun, decl, call) int wrapped_##fun decl { \
int retval = fun call; \
if (retval < 0) \
errno = WSAGetLastError (); \
WRAP (getpeername, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
WRAP (setsockopt, (int s, int level, int opt, const void *val, int len),
(s, level, opt, val, len))
+WRAP (closesocket, (int s), (s))
/* Return the text of the error message for Winsock error WSERR. */
#include <direct.h>
/* Windows compilers accept only one arg to mkdir. */
-#ifndef __BORLANDC__
-# define mkdir(a, b) _mkdir(a)
-#else /* __BORLANDC__ */
-# define mkdir(a, b) mkdir(a)
-#endif /* __BORLANDC__ */
+#define mkdir(a, b) _mkdir(a)
#ifndef INHIBIT_WRAP
/* Winsock functions don't set errno, so we provide wrappers
that do. */
-#define socket wrap_socket
-#define bind wrap_bind
-#define connect wrap_connect
-#define recv wrap_recv
-#define send wrap_send
-#define select wrap_select
-#define getsockname wrap_getsockname
-#define getpeername wrap_getpeername
-#define setsockopt wrap_setsockopt
+#define socket wrapped_socket
+#define bind wrapped_bind
+#define connect wrapped_connect
+#define recv wrapped_recv
+#define send wrapped_send
+#define select wrapped_select
+#define getsockname wrapped_getsockname
+#define getpeername wrapped_getpeername
+#define setsockopt wrapped_setsockopt
+#define closesocket wrapped_closesocket
#endif /* not INHIBIT_WRAP */
-int wrap_socket (int, int, int);
-int wrap_bind (int, struct sockaddr *, int);
-int wrap_connect (int, const struct sockaddr *, int);
-int wrap_recv (int, void *, int, int);
-int wrap_send (int, const void *, int, int);
-int wrap_select (int, fd_set *, fd_set *, fd_set *, const struct timeval *);
-int wrap_getsockname (int, struct sockaddr *, int *);
-int wrap_getpeername (int, struct sockaddr *, int *);
-int wrap_setsockopt (int, int, int, const void *, int);
+int wrapped_socket (int, int, int);
+int wrapped_bind (int, struct sockaddr *, int);
+int wrapped_connect (int, const struct sockaddr *, int);
+int wrapped_recv (int, void *, int, int);
+int wrapped_send (int, const void *, int, int);
+int wrapped_select (int, fd_set *, fd_set *, fd_set *, const struct timeval *);
+int wrapped_getsockname (int, struct sockaddr *, int *);
+int wrapped_getpeername (int, struct sockaddr *, int *);
+int wrapped_setsockopt (int, int, int, const void *, int);
+int wrapped_closesocket (int);
/* Finally, provide a private version of strerror that does the
right thing with Winsock errors. */
/* Public functions. */
-#ifndef HAVE_SLEEP
-unsigned int sleep (unsigned);
-#endif
-#ifndef HAVE_USLEEP
-int usleep (unsigned long);
-#endif
-
void ws_startup (void);
void ws_changetitle (const char *);
void ws_percenttitle (double);
/* Things needed for IPv6; missing in <ws2tcpip.h>. */
#ifdef ENABLE_IPV6
-# ifndef HAVE_NTOP
- extern const char *inet_ntop (int af, const void *src, char *dst, size_t size);
-# endif
-# ifndef HAVE_PTON
- extern int inet_pton (int af, const char *src, void *dst);
+# ifndef HAVE_INET_NTOP
+extern const char *inet_ntop (int af, const void *src, char *dst, size_t size);
# endif
#endif /* ENABLE_IPV6 */
/* Various utility functions.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GNU Wget.
return copy;
}
-/* Return a count of how many times CHR occurs in STRING. */
-
-int
-count_char (const char *string, char chr)
-{
- const char *p;
- int count = 0;
- for (p = string; *p; p++)
- if (*p == chr)
- ++count;
- return count;
-}
-
/* Copy the string formed by two pointers (one on the beginning, other
on the char after the last char) to a new, malloc-ed location.
0-terminate it. */
only one of the above constants will be defined. Virtually all
modern Unix systems will define TIMER_GETTIMEOFDAY; Windows will
use TIMER_WINDOWS. TIMER_TIME is a catch-all method for
- non-Windows systems without gettimeofday.
-
- #### Perhaps we should also support ftime(), which exists on old
- BSD 4.2-influenced systems? (It also existed under MS DOS Borland
- C, if memory serves me.) */
+ non-Windows systems without gettimeofday. */
#ifdef WINDOWS
# define TIMER_WINDOWS
#endif
#ifdef TIMER_WINDOWS
-typedef ULARGE_INTEGER wget_sys_time;
+typedef union {
+ DWORD lores; /* In case GetTickCount is used */
+ LARGE_INTEGER hires; /* In case high-resolution timer is used */
+} wget_sys_time;
#endif
struct wget_timer {
double elapsed_pre_start;
};
+#ifdef TIMER_WINDOWS
+
+/* Whether high-resolution timers are used. Set by wtimer_initialize_once
+ the first time wtimer_allocate is called. */
+static int using_hires_timers;
+
+/* Frequency of high-resolution timers -- number of updates per
+ millisecond. Calculated the first time wtimer_allocate is called
+ provided that high-resolution timers are available. */
+static double hires_millisec_freq;
+
+/* The first time a timer is created, determine whether to use
+ high-resolution timers. */
+
+static void
+wtimer_initialize_once (void)
+{
+ static int init_done;
+ if (!init_done)
+ {
+ LARGE_INTEGER freq;
+ init_done = 1;
+ freq.QuadPart = 0;
+ QueryPerformanceFrequency (&freq);
+ if (freq.QuadPart != 0)
+ {
+ using_hires_timers = 1;
+ hires_millisec_freq = (double) freq.QuadPart / 1000.0;
+ }
+ }
+}
+#endif /* TIMER_WINDOWS */
+
/* Allocate a timer. Calling wtimer_read on the timer will return
zero. It is not legal to call wtimer_update with a freshly
allocated timer -- use wtimer_reset first. */
{
struct wget_timer *wt = xnew (struct wget_timer);
xzero (*wt);
+
+#ifdef TIMER_WINDOWS
+ wtimer_initialize_once ();
+#endif
+
return wt;
}
#endif
#ifdef TIMER_WINDOWS
- /* We use GetSystemTime to get the elapsed time. MSDN warns that
- system clock adjustments can skew the output of GetSystemTime
- when used as a timer and gives preference to GetTickCount and
- high-resolution timers. But GetTickCount can overflow, and hires
- timers are typically used for profiling, not for regular time
- measurement. Since we handle clock skew anyway, we just use
- GetSystemTime. */
- FILETIME ft;
- SYSTEMTIME st;
- GetSystemTime (&st);
-
- /* As recommended by MSDN, we convert SYSTEMTIME to FILETIME, copy
- FILETIME to ULARGE_INTEGER, and use regular 64-bit integer
- arithmetic on that. */
- SystemTimeToFileTime (&st, &ft);
- wst->HighPart = ft.dwHighDateTime;
- wst->LowPart = ft.dwLowDateTime;
+ if (using_hires_timers)
+ {
+ QueryPerformanceCounter (&wst->hires);
+ }
+ else
+ {
+ /* Where hires counters are not available, use GetTickCount rather
+ GetSystemTime, because it is unaffected by clock skew and simpler
+ to use. Note that overflows don't affect us because we never use
+ absolute values of the ticker, only the differences. */
+ wst->lores = GetTickCount ();
+ }
#endif
}
/* Reset timer WT. This establishes the starting point from which
wtimer_elapsed() will return the number of elapsed milliseconds.
- It is allowed to reset a previously used timer.
-
- If a non-zero value is used as START, the timer's values will be
- offset by START. */
+ It is allowed to reset a previously used timer. */
void
wtimer_reset (struct wget_timer *wt)
#endif
#ifdef WINDOWS
- /* VC++ 6 doesn't support direct cast of uint64 to double. To work
- around this, we subtract, then convert to signed, then finally to
- double. */
- return (double)(signed __int64)(wst1->QuadPart - wst2->QuadPart) / 10000;
+ if (using_hires_timers)
+ return (wst1->hires.QuadPart - wst2->hires.QuadPart) / hires_millisec_freq;
+ else
+ return wst1->lores - wst2->lores;
#endif
}
#endif
#ifdef TIMER_WINDOWS
- /* According to MSDN, GetSystemTime returns a broken-down time
- structure the smallest member of which are milliseconds. */
- return 1;
+ if (using_hires_timers)
+ return 1.0 / hires_millisec_freq;
+ else
+ return 10; /* according to MSDN */
#endif
}
\f
int rnd3 = random_number (1000);
return rnd1 / 1000.0 + rnd2 / 1000000.0 + rnd3 / 1000000000.0;
}
-
-#if 0
-/* A debugging function for checking whether an MD5 library works. */
-
-#include "gen-md5.h"
-
-char *
-debug_test_md5 (char *buf)
-{
- unsigned char raw[16];
- static char res[33];
- unsigned char *p1;
- char *p2;
- int cnt;
- ALLOCA_MD5_CONTEXT (ctx);
-
- gen_md5_init (ctx);
- gen_md5_update ((unsigned char *)buf, strlen (buf), ctx);
- gen_md5_finish (ctx, raw);
-
- p1 = raw;
- p2 = res;
- cnt = 16;
- while (cnt--)
- {
- *p2++ = XNUM_TO_digit (*p1 >> 4);
- *p2++ = XNUM_TO_digit (*p1 & 0xf);
- ++p1;
- }
- *p2 = '\0';
-
- return res;
-}
-#endif
\f
/* Implementation of run_with_timeout, a generic timeout-forcing
routine for systems with Unix-like signal handling. */
#ifdef HAVE_NANOSLEEP
/* nanosleep is the preferred interface because it offers high
accuracy and, more importantly, because it allows us to reliably
- restart after having been interrupted by a signal such as
- SIGWINCH. */
+ restart receiving a signal such as SIGWINCH. (There was an
+ actual Debian bug report about --limit-rate malfunctioning while
+ the terminal was being resized.) */
struct timespec sleep, remaining;
sleep.tv_sec = (long) seconds;
sleep.tv_nsec = 1000000000L * (seconds - (long) seconds);
#endif
char *xstrdup_lower PARAMS ((const char *));
-int count_char PARAMS ((const char *, char));
char *strdupdelim PARAMS ((const char *, const char *));
char **sepstring PARAMS ((const char *));