Back to index

tor  0.2.3.18-rc
compat.h
Go to the documentation of this file.
00001 /* Copyright (c) 2003-2004, Roger Dingledine
00002  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
00003  * Copyright (c) 2007-2012, The Tor Project, Inc. */
00004 /* See LICENSE for licensing information */
00005 
00006 #ifndef _TOR_COMPAT_H
00007 #define _TOR_COMPAT_H
00008 
00009 #include "orconfig.h"
00010 #include "torint.h"
00011 #ifdef _WIN32
00012 #ifndef _WIN32_WINNT
00013 #define _WIN32_WINNT 0x0501
00014 #endif
00015 #define WIN32_LEAN_AND_MEAN
00016 #if defined(_MSC_VER) && (_MSC_VER < 1300)
00017 #include <winsock.h>
00018 #else
00019 #include <winsock2.h>
00020 #include <ws2tcpip.h>
00021 #endif
00022 #endif
00023 #ifdef HAVE_SYS_PARAM_H
00024 #include <sys/param.h>
00025 #endif
00026 #ifdef HAVE_SYS_TYPES_H
00027 #include <sys/types.h>
00028 #endif
00029 #ifdef HAVE_SYS_TIME_H
00030 #include <sys/time.h>
00031 #endif
00032 #ifdef HAVE_TIME_H
00033 #include <time.h>
00034 #endif
00035 #ifdef HAVE_STRING_H
00036 #include <string.h>
00037 #endif
00038 #if defined(HAVE_PTHREAD_H) && !defined(_WIN32)
00039 #include <pthread.h>
00040 #endif
00041 #include <stdarg.h>
00042 #ifdef HAVE_SYS_RESOURCE_H
00043 #include <sys/resource.h>
00044 #endif
00045 #ifdef HAVE_SYS_SOCKET_H
00046 #include <sys/socket.h>
00047 #endif
00048 #ifdef HAVE_NETINET_IN_H
00049 #include <netinet/in.h>
00050 #endif
00051 #ifdef HAVE_NETINET6_IN6_H
00052 #include <netinet6/in6.h>
00053 #endif
00054 
00055 #include <stdio.h>
00056 
00057 #if defined (WINCE)
00058 #include <fcntl.h>
00059 #include <io.h>
00060 #include <math.h>
00061 #include <projects.h>
00062 #define snprintf _snprintf
00063 /* this is not exported as W .... */
00064 #define SHGetPathFromIDListW SHGetPathFromIDList
00065 /* wcecompat has vasprintf */
00066 #define HAVE_VASPRINTF
00067 /* no service here */
00068 #ifdef NT_SERVICE
00069 #undef NT_SERVICE
00070 #endif
00071 #endif // WINCE
00072 
00073 #ifndef NULL_REP_IS_ZERO_BYTES
00074 #error "It seems your platform does not represent NULL as zero. We can't cope."
00075 #endif
00076 
00077 #if 'a'!=97 || 'z'!=122 || 'A'!=65 || ' '!=32
00078 #error "It seems that you encode characters in something other than ASCII."
00079 #endif
00080 
00081 /* ===== Compiler compatibility */
00082 
00083 /* GCC can check printf types on arbitrary functions. */
00084 #ifdef __GNUC__
00085 #define CHECK_PRINTF(formatIdx, firstArg) \
00086    __attribute__ ((format(printf, formatIdx, firstArg)))
00087 #else
00088 #define CHECK_PRINTF(formatIdx, firstArg)
00089 #endif
00090 
00091 /* inline is __inline on windows. */
00092 #ifdef _WIN32
00093 #define INLINE __inline
00094 #else
00095 #define INLINE inline
00096 #endif
00097 
00098 /* Try to get a reasonable __func__ substitute in place. */
00099 #if defined(_MSC_VER)
00100 /* MSVC compilers before VC7 don't have __func__ at all; later ones call it
00101  * __FUNCTION__. */
00102 #if _MSC_VER < 1300
00103 #define __func__ "???"
00104 #else
00105 #define __func__ __FUNCTION__
00106 #endif
00107 
00108 #else
00109 /* For platforms where autoconf works, make sure __func__ is defined
00110  * sanely. */
00111 #ifndef HAVE_MACRO__func__
00112 #ifdef HAVE_MACRO__FUNCTION__
00113 #define __func__ __FUNCTION__
00114 #elif HAVE_MACRO__FUNC__
00115 #define __func__ __FUNC__
00116 #else
00117 #define __func__ "???"
00118 #endif
00119 #endif /* ifndef MAVE_MACRO__func__ */
00120 #endif /* if not windows */
00121 
00122 #if defined(_MSC_VER) && (_MSC_VER < 1300)
00123 /* MSVC versions before 7 apparently don't believe that you can cast uint64_t
00124  * to double and really mean it. */
00125 extern INLINE double U64_TO_DBL(uint64_t x) {
00126   int64_t i = (int64_t) x;
00127   return (i < 0) ? ((double) INT64_MAX) : (double) i;
00128 }
00129 #define DBL_TO_U64(x) ((uint64_t)(int64_t) (x))
00130 #else
00131 #define U64_TO_DBL(x) ((double) (x))
00132 #define DBL_TO_U64(x) ((uint64_t) (x))
00133 #endif
00134 
00135 /* GCC has several useful attributes. */
00136 #if defined(__GNUC__) && __GNUC__ >= 3
00137 #define ATTR_NORETURN __attribute__((noreturn))
00138 #define ATTR_CONST __attribute__((const))
00139 #define ATTR_MALLOC __attribute__((malloc))
00140 #define ATTR_NORETURN __attribute__((noreturn))
00141 /* Alas, nonnull is not at present a good idea for us.  We'd like to get
00142  * warnings when we pass NULL where we shouldn't (which nonnull does, albeit
00143  * spottily), but we don't want to tell the compiler to make optimizations
00144  * with the assumption that the argument can't be NULL (since this would make
00145  * many of our checks go away, and make our code less robust against
00146  * programming errors).  Unfortunately, nonnull currently does both of these
00147  * things, and there's no good way to split them up.
00148  *
00149  * #define ATTR_NONNULL(x) __attribute__((nonnull x)) */
00150 #define ATTR_NONNULL(x)
00151 
00159 #define PREDICT_LIKELY(exp) __builtin_expect(!!(exp), 1)
00160 
00167 #define PREDICT_UNLIKELY(exp) __builtin_expect(!!(exp), 0)
00168 #else
00169 #define ATTR_NORETURN
00170 #define ATTR_CONST
00171 #define ATTR_MALLOC
00172 #define ATTR_NORETURN
00173 #define ATTR_NONNULL(x)
00174 #define PREDICT_LIKELY(exp) (exp)
00175 #define PREDICT_UNLIKELY(exp) (exp)
00176 #endif
00177 
00179 #define STMT_NIL (void)0
00180 
00183 #define STMT_VOID(a) while (0) { (void)(a); }
00184 
00185 #ifdef __GNUC__
00186 
00188 #define STMT_BEGIN (void) ({
00189 #define STMT_END })
00190 #elif defined(sun) || defined(__sun__)
00191 #define STMT_BEGIN if (1) {
00192 #define STMT_END } else STMT_NIL
00193 #else
00194 #define STMT_BEGIN do {
00195 #define STMT_END } while (0)
00196 #endif
00197 
00198 /* ===== String compatibility */
00199 #ifdef _WIN32
00200 /* Windows names string functions differently from most other platforms. */
00201 #define strncasecmp _strnicmp
00202 #define strcasecmp _stricmp
00203 #endif
00204 #ifndef HAVE_STRLCAT
00205 size_t strlcat(char *dst, const char *src, size_t siz) ATTR_NONNULL((1,2));
00206 #endif
00207 #ifndef HAVE_STRLCPY
00208 size_t strlcpy(char *dst, const char *src, size_t siz) ATTR_NONNULL((1,2));
00209 #endif
00210 
00211 #ifdef _MSC_VER
00212 
00214 #define U64_PRINTF_ARG(a) (a)
00215 
00217 #define U64_SCANF_ARG(a) (a)
00218 
00219 #define U64_LITERAL(n) (n ## ui64)
00220 #define I64_PRINTF_ARG(a) (a)
00221 #define I64_SCANF_ARG(a) (a)
00222 #define I64_LITERAL(n) (n ## i64)
00223 #else
00224 #define U64_PRINTF_ARG(a) ((long long unsigned int)(a))
00225 #define U64_SCANF_ARG(a) ((long long unsigned int*)(a))
00226 #define U64_LITERAL(n) (n ## llu)
00227 #define I64_PRINTF_ARG(a) ((long long signed int)(a))
00228 #define I64_SCANF_ARG(a) ((long long signed int*)(a))
00229 #define I64_LITERAL(n) (n ## ll)
00230 #endif
00231 
00232 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
00233 
00235 #define U64_FORMAT "%I64u"
00236 #define I64_FORMAT "%I64d"
00237 #else
00238 #define U64_FORMAT "%llu"
00239 #define I64_FORMAT "%lld"
00240 #endif
00241 
00244 typedef struct tor_mmap_t {
00245   const char *data; 
00246   size_t size; 
00248   /* None of the fields below should be accessed from outside compat.c */
00249 #ifdef HAVE_SYS_MMAN_H
00250   size_t mapping_size; 
00252 #elif defined _WIN32
00253   HANDLE mmap_handle;
00254 #endif
00255 
00256 } tor_mmap_t;
00257 
00258 tor_mmap_t *tor_mmap_file(const char *filename) ATTR_NONNULL((1));
00259 void tor_munmap_file(tor_mmap_t *handle) ATTR_NONNULL((1));
00260 
00261 int tor_snprintf(char *str, size_t size, const char *format, ...)
00262   CHECK_PRINTF(3,4) ATTR_NONNULL((1,3));
00263 int tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
00264   CHECK_PRINTF(3,0) ATTR_NONNULL((1,3));
00265 
00266 int tor_asprintf(char **strp, const char *fmt, ...)
00267   CHECK_PRINTF(2,3);
00268 int tor_vasprintf(char **strp, const char *fmt, va_list args)
00269   CHECK_PRINTF(2,0);
00270 
00271 const void *tor_memmem(const void *haystack, size_t hlen, const void *needle,
00272                        size_t nlen) ATTR_NONNULL((1,3));
00273 static const void *tor_memstr(const void *haystack, size_t hlen,
00274                            const char *needle) ATTR_NONNULL((1,3));
00275 static INLINE const void *
00276 tor_memstr(const void *haystack, size_t hlen, const char *needle)
00277 {
00278   return tor_memmem(haystack, hlen, needle, strlen(needle));
00279 }
00280 
00281 /* Much of the time when we're checking ctypes, we're doing spec compliance,
00282  * which all assumes we're doing ASCII. */
00283 #define DECLARE_CTYPE_FN(name)                                          \
00284   static int TOR_##name(char c);                                        \
00285   extern const uint32_t TOR_##name##_TABLE[];                           \
00286   static INLINE int TOR_##name(char c) {                                \
00287     uint8_t u = c;                                                      \
00288     return !!(TOR_##name##_TABLE[(u >> 5) & 7] & (1 << (u & 31)));      \
00289   }
00290 DECLARE_CTYPE_FN(ISALPHA)
00291 DECLARE_CTYPE_FN(ISALNUM)
00292 DECLARE_CTYPE_FN(ISSPACE)
00293 DECLARE_CTYPE_FN(ISDIGIT)
00294 DECLARE_CTYPE_FN(ISXDIGIT)
00295 DECLARE_CTYPE_FN(ISPRINT)
00296 DECLARE_CTYPE_FN(ISLOWER)
00297 DECLARE_CTYPE_FN(ISUPPER)
00298 extern const char TOR_TOUPPER_TABLE[];
00299 extern const char TOR_TOLOWER_TABLE[];
00300 #define TOR_TOLOWER(c) (TOR_TOLOWER_TABLE[(uint8_t)c])
00301 #define TOR_TOUPPER(c) (TOR_TOUPPER_TABLE[(uint8_t)c])
00302 
00303 char *tor_strtok_r_impl(char *str, const char *sep, char **lasts);
00304 #ifdef HAVE_STRTOK_R
00305 #define tor_strtok_r(str, sep, lasts) strtok_r(str, sep, lasts)
00306 #else
00307 #define tor_strtok_r(str, sep, lasts) tor_strtok_r_impl(str, sep, lasts)
00308 #endif
00309 
00310 #ifdef _WIN32
00311 #define _SHORT_FILE_ (tor_fix_source_file(__FILE__))
00312 const char *tor_fix_source_file(const char *fname);
00313 #else
00314 #define _SHORT_FILE_ (__FILE__)
00315 #define tor_fix_source_file(s) (s)
00316 #endif
00317 
00318 /* ===== Time compatibility */
00319 #if !defined(HAVE_GETTIMEOFDAY) && !defined(HAVE_STRUCT_TIMEVAL_TV_SEC)
00320 
00321 struct timeval {
00322   time_t tv_sec;
00323   unsigned int tv_usec;
00324 };
00325 #endif
00326 
00327 void tor_gettimeofday(struct timeval *timeval);
00328 
00329 struct tm *tor_localtime_r(const time_t *timep, struct tm *result);
00330 struct tm *tor_gmtime_r(const time_t *timep, struct tm *result);
00331 
00332 #ifndef timeradd
00333 
00335 #define timeradd(tv1,tv2,tvout) \
00336   do {                                                  \
00337     (tvout)->tv_sec = (tv1)->tv_sec + (tv2)->tv_sec;    \
00338     (tvout)->tv_usec = (tv1)->tv_usec + (tv2)->tv_usec; \
00339     if ((tvout)->tv_usec >= 1000000) {                  \
00340       (tvout)->tv_usec -= 1000000;                      \
00341       (tvout)->tv_sec++;                                \
00342     }                                                   \
00343   } while (0)
00344 #endif
00345 
00346 #ifndef timersub
00347 
00349 #define timersub(tv1,tv2,tvout) \
00350   do {                                                  \
00351     (tvout)->tv_sec = (tv1)->tv_sec - (tv2)->tv_sec;    \
00352     (tvout)->tv_usec = (tv1)->tv_usec - (tv2)->tv_usec; \
00353     if ((tvout)->tv_usec < 0) {                         \
00354       (tvout)->tv_usec += 1000000;                      \
00355       (tvout)->tv_sec--;                                \
00356     }                                                   \
00357   } while (0)
00358 #endif
00359 
00360 #ifndef timercmp
00361 
00368 #define timercmp(tv1,tv2,op)                    \
00369   (((tv1)->tv_sec == (tv2)->tv_sec) ?           \
00370    ((tv1)->tv_usec op (tv2)->tv_usec) :         \
00371    ((tv1)->tv_sec op (tv2)->tv_sec))
00372 #endif
00373 
00374 /* ===== File compatibility */
00375 int tor_open_cloexec(const char *path, int flags, unsigned mode);
00376 FILE *tor_fopen_cloexec(const char *path, const char *mode);
00377 
00378 int replace_file(const char *from, const char *to);
00379 int touch_file(const char *fname);
00380 
00381 typedef struct tor_lockfile_t tor_lockfile_t;
00382 tor_lockfile_t *tor_lockfile_lock(const char *filename, int blocking,
00383                                   int *locked_out);
00384 void tor_lockfile_unlock(tor_lockfile_t *lockfile);
00385 
00386 off_t tor_fd_getpos(int fd);
00387 int tor_fd_seekend(int fd);
00388 
00389 #ifdef _WIN32
00390 #define PATH_SEPARATOR "\\"
00391 #else
00392 #define PATH_SEPARATOR "/"
00393 #endif
00394 
00395 /* ===== Net compatibility */
00396 
00397 #if (SIZEOF_SOCKLEN_T == 0)
00398 typedef int socklen_t;
00399 #endif
00400 
00401 #ifdef _WIN32
00402 /* XXX Actually, this should arguably be SOCKET; we use intptr_t here so that
00403  * any inadvertant checks for the socket being <= 0 or > 0 will probably
00404  * still work. */
00405 #define tor_socket_t intptr_t
00406 #define SOCKET_OK(s) ((SOCKET)(s) != INVALID_SOCKET)
00407 #define TOR_INVALID_SOCKET INVALID_SOCKET
00408 #else
00409 
00410 #define tor_socket_t int
00411 
00412 #define SOCKET_OK(s) ((s) >= 0)
00413 
00414 #define TOR_INVALID_SOCKET (-1)
00415 #endif
00416 
00417 int tor_close_socket(tor_socket_t s);
00418 tor_socket_t tor_open_socket(int domain, int type, int protocol);
00419 tor_socket_t tor_accept_socket(tor_socket_t sockfd, struct sockaddr *addr,
00420                                   socklen_t *len);
00421 int get_n_open_sockets(void);
00422 
00423 #define tor_socket_send(s, buf, len, flags) send(s, buf, len, flags)
00424 #define tor_socket_recv(s, buf, len, flags) recv(s, buf, len, flags)
00425 
00430 #if !defined(HAVE_STRUCT_IN6_ADDR)
00431 struct in6_addr
00432 {
00433   union {
00434     uint8_t u6_addr8[16];
00435     uint16_t u6_addr16[8];
00436     uint32_t u6_addr32[4];
00437   } in6_u;
00438 #define s6_addr   in6_u.u6_addr8
00439 #define s6_addr16 in6_u.u6_addr16
00440 #define s6_addr32 in6_u.u6_addr32
00441 };
00442 #endif
00443 
00446 #if defined(__APPLE__) || defined(__darwin__) || defined(__FreeBSD__) \
00447     || defined(__NetBSD__) || defined(__OpenBSD__)
00448 #ifndef s6_addr16
00449 #define s6_addr16 __u6_addr.__u6_addr16
00450 #endif
00451 #ifndef s6_addr32
00452 #define s6_addr32 __u6_addr.__u6_addr32
00453 #endif
00454 #endif
00455 
00457 #ifndef HAVE_SA_FAMILY_T
00458 typedef uint16_t sa_family_t;
00459 #endif
00460 
00464 #ifdef HAVE_STRUCT_IN6_ADDR_S6_ADDR32
00465 #define S6_ADDR32(x) ((uint32_t*)(x).s6_addr32)
00466 #else
00467 #define S6_ADDR32(x) ((uint32_t*)((char*)&(x).s6_addr))
00468 #endif
00469 #ifdef HAVE_STRUCT_IN6_ADDR_S6_ADDR16
00470 #define S6_ADDR16(x) ((uint16_t*)(x).s6_addr16)
00471 #else
00472 #define S6_ADDR16(x) ((uint16_t*)((char*)&(x).s6_addr))
00473 #endif
00474 
00478 #if !defined(HAVE_STRUCT_SOCKADDR_IN6)
00479 struct sockaddr_in6 {
00480   sa_family_t sin6_family;
00481   uint16_t sin6_port;
00482   // uint32_t sin6_flowinfo;
00483   struct in6_addr sin6_addr;
00484   // uint32_t sin6_scope_id;
00485 };
00486 #endif
00487 
00488 int tor_inet_aton(const char *cp, struct in_addr *addr) ATTR_NONNULL((1,2));
00489 const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
00490 int tor_inet_pton(int af, const char *src, void *dst);
00491 int tor_lookup_hostname(const char *name, uint32_t *addr) ATTR_NONNULL((1,2));
00492 void set_socket_nonblocking(tor_socket_t socket);
00493 int tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]);
00494 int network_init(void);
00495 
00496 /* For stupid historical reasons, windows sockets have an independent
00497  * set of errnos, and an independent way to get them.  Also, you can't
00498  * always believe WSAEWOULDBLOCK.  Use the macros below to compare
00499  * errnos against expected values, and use tor_socket_errno to find
00500  * the actual errno after a socket operation fails.
00501  */
00502 #if defined(_WIN32)
00503 
00504 #define ERRNO_IS_EAGAIN(e)           ((e) == EAGAIN || (e) == WSAEWOULDBLOCK)
00505 
00506 #define ERRNO_IS_EINPROGRESS(e)      ((e) == WSAEINPROGRESS)
00507 
00509 #define ERRNO_IS_CONN_EINPROGRESS(e) \
00510   ((e) == WSAEINPROGRESS || (e)== WSAEINVAL || (e) == WSAEWOULDBLOCK)
00511 
00513 #define ERRNO_IS_ACCEPT_EAGAIN(e)    ERRNO_IS_EAGAIN(e)
00514 
00516 #define ERRNO_IS_ACCEPT_RESOURCE_LIMIT(e) \
00517   ((e) == WSAEMFILE || (e) == WSAENOBUFS)
00518 
00519 #define ERRNO_IS_EADDRINUSE(e)      ((e) == WSAEADDRINUSE)
00520 int tor_socket_errno(tor_socket_t sock);
00521 const char *tor_socket_strerror(int e);
00522 #else
00523 #define ERRNO_IS_EAGAIN(e)           ((e) == EAGAIN)
00524 #define ERRNO_IS_EINPROGRESS(e)      ((e) == EINPROGRESS)
00525 #define ERRNO_IS_CONN_EINPROGRESS(e) ((e) == EINPROGRESS)
00526 #define ERRNO_IS_ACCEPT_EAGAIN(e)    ((e) == EAGAIN || (e) == ECONNABORTED)
00527 #define ERRNO_IS_ACCEPT_RESOURCE_LIMIT(e) \
00528   ((e) == EMFILE || (e) == ENFILE || (e) == ENOBUFS || (e) == ENOMEM)
00529 #define ERRNO_IS_EADDRINUSE(e)       ((e) == EADDRINUSE)
00530 #define tor_socket_errno(sock)       (errno)
00531 #define tor_socket_strerror(e)       strerror(e)
00532 #endif
00533 
00535 typedef enum {
00536   SOCKS5_SUCCEEDED                  = 0x00,
00537   SOCKS5_GENERAL_ERROR              = 0x01,
00538   SOCKS5_NOT_ALLOWED                = 0x02,
00539   SOCKS5_NET_UNREACHABLE            = 0x03,
00540   SOCKS5_HOST_UNREACHABLE           = 0x04,
00541   SOCKS5_CONNECTION_REFUSED         = 0x05,
00542   SOCKS5_TTL_EXPIRED                = 0x06,
00543   SOCKS5_COMMAND_NOT_SUPPORTED      = 0x07,
00544   SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED = 0x08,
00545 } socks5_reply_status_t;
00546 
00547 /* ===== Insecure rng */
00548 void tor_init_weak_random(unsigned seed);
00549 long tor_weak_random(void);
00550 #define TOR_RAND_MAX (RAND_MAX)
00551 
00552 /* ===== OS compatibility */
00553 const char *get_uname(void);
00554 
00555 uint16_t get_uint16(const void *cp) ATTR_NONNULL((1));
00556 uint32_t get_uint32(const void *cp) ATTR_NONNULL((1));
00557 uint64_t get_uint64(const void *cp) ATTR_NONNULL((1));
00558 void set_uint16(void *cp, uint16_t v) ATTR_NONNULL((1));
00559 void set_uint32(void *cp, uint32_t v) ATTR_NONNULL((1));
00560 void set_uint64(void *cp, uint64_t v) ATTR_NONNULL((1));
00561 
00562 /* These uint8 variants are defined to make the code more uniform. */
00563 #define get_uint8(cp) (*(const uint8_t*)(cp))
00564 static void set_uint8(void *cp, uint8_t v);
00565 static INLINE void
00566 set_uint8(void *cp, uint8_t v)
00567 {
00568   *(uint8_t*)cp = v;
00569 }
00570 
00571 #if !defined(HAVE_RLIM_T)
00572 typedef unsigned long rlim_t;
00573 #endif
00574 int set_max_file_descriptors(rlim_t limit, int *max);
00575 int tor_disable_debugger_attach(void);
00576 int switch_id(const char *user);
00577 #ifdef HAVE_PWD_H
00578 char *get_user_homedir(const char *username);
00579 #endif
00580 
00581 int get_parent_directory(char *fname);
00582 char *make_path_absolute(char *fname);
00583 
00584 char **get_environment(void);
00585 
00586 int spawn_func(void (*func)(void *), void *data);
00587 void spawn_exit(void) ATTR_NORETURN;
00588 
00589 #if defined(ENABLE_THREADS) && defined(_WIN32)
00590 #define USE_WIN32_THREADS
00591 #define TOR_IS_MULTITHREADED 1
00592 #elif (defined(ENABLE_THREADS) && defined(HAVE_PTHREAD_H) && \
00593        defined(HAVE_PTHREAD_CREATE))
00594 #define USE_PTHREADS
00595 #define TOR_IS_MULTITHREADED 1
00596 #else
00597 #undef TOR_IS_MULTITHREADED
00598 #endif
00599 
00600 int compute_num_cpus(void);
00601 
00602 /* Because we use threads instead of processes on most platforms (Windows,
00603  * Linux, etc), we need locking for them.  On platforms with poor thread
00604  * support or broken gethostbyname_r, these functions are no-ops. */
00605 
00607 typedef struct tor_mutex_t {
00608 #if defined(USE_WIN32_THREADS)
00609 
00610   CRITICAL_SECTION mutex;
00611 #elif defined(USE_PTHREADS)
00612 
00614   pthread_mutex_t mutex;
00615 #else
00616 
00617   int _unused;
00618 #endif
00619 } tor_mutex_t;
00620 
00621 int tor_mlockall(void);
00622 
00623 #ifdef TOR_IS_MULTITHREADED
00624 tor_mutex_t *tor_mutex_new(void);
00625 void tor_mutex_init(tor_mutex_t *m);
00626 void tor_mutex_acquire(tor_mutex_t *m);
00627 void tor_mutex_release(tor_mutex_t *m);
00628 void tor_mutex_free(tor_mutex_t *m);
00629 void tor_mutex_uninit(tor_mutex_t *m);
00630 unsigned long tor_get_thread_id(void);
00631 void tor_threads_init(void);
00632 #else
00633 #define tor_mutex_new() ((tor_mutex_t*)tor_malloc(sizeof(int)))
00634 #define tor_mutex_init(m) STMT_NIL
00635 #define tor_mutex_acquire(m) STMT_VOID(m)
00636 #define tor_mutex_release(m) STMT_NIL
00637 #define tor_mutex_free(m) STMT_BEGIN tor_free(m); STMT_END
00638 #define tor_mutex_uninit(m) STMT_NIL
00639 #define tor_get_thread_id() (1UL)
00640 #define tor_threads_init() STMT_NIL
00641 #endif
00642 
00643 void set_main_thread(void);
00644 int in_main_thread(void);
00645 
00646 #ifdef TOR_IS_MULTITHREADED
00647 #if 0
00648 typedef struct tor_cond_t tor_cond_t;
00649 tor_cond_t *tor_cond_new(void);
00650 void tor_cond_free(tor_cond_t *cond);
00651 int tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex);
00652 void tor_cond_signal_one(tor_cond_t *cond);
00653 void tor_cond_signal_all(tor_cond_t *cond);
00654 #endif
00655 #endif
00656 
00663 #ifndef MAX
00664 #define MAX(a,b) ( ((a)<(b)) ? (b) : (a) )
00665 #endif
00666 #ifndef MIN
00667 #define MIN(a,b) ( ((a)>(b)) ? (b) : (a) )
00668 #endif
00669 
00670 /* Platform-specific helpers. */
00671 #ifdef _WIN32
00672 char *format_win32_error(DWORD err);
00673 #endif
00674 
00675 /*for some reason my compiler doesn't have these version flags defined
00676   a nice homework assignment for someone one day is to define the rest*/
00677 //these are the values as given on MSDN
00678 #ifdef _WIN32
00679 
00680 #ifndef VER_SUITE_EMBEDDEDNT
00681 #define VER_SUITE_EMBEDDEDNT 0x00000040
00682 #endif
00683 
00684 #ifndef VER_SUITE_SINGLEUSERTS
00685 #define VER_SUITE_SINGLEUSERTS 0x00000100
00686 #endif
00687 
00688 #endif
00689 
00690 #endif
00691