1 : /*
2 : * Copyright (c) 2007 Niels Provos <provos@citi.umich.edu>
3 : * All rights reserved.
4 : *
5 : * Redistribution and use in source and binary forms, with or without
6 : * modification, are permitted provided that the following conditions
7 : * are met:
8 : * 1. Redistributions of source code must retain the above copyright
9 : * notice, this list of conditions and the following disclaimer.
10 : * 2. Redistributions in binary form must reproduce the above copyright
11 : * notice, this list of conditions and the following disclaimer in the
12 : * documentation and/or other materials provided with the distribution.
13 : * 3. The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 : *
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 : #ifdef HAVE_CONFIG_H
28 : #include "config.h"
29 : #endif
30 :
31 : #ifdef WIN32
32 : #include <winsock2.h>
33 : #define WIN32_LEAN_AND_MEAN
34 : #include <windows.h>
35 : #undef WIN32_LEAN_AND_MEAN
36 : #endif
37 :
38 : #include <sys/types.h>
39 : #ifdef HAVE_SYS_SOCKET_H
40 : #include <sys/socket.h>
41 : #endif
42 : #ifdef HAVE_UNISTD_H
43 : #include <unistd.h>
44 : #endif
45 : #ifdef HAVE_FCNTL_H
46 : #include <fcntl.h>
47 : #endif
48 : #ifdef HAVE_STDLIB_H
49 : #include <stdlib.h>
50 : #endif
51 : #include <errno.h>
52 : #if defined WIN32 && !defined(HAVE_GETTIMEOFDAY_H)
53 : #include <sys/timeb.h>
54 : #endif
55 : #include <stdio.h>
56 :
57 : #include "evutil.h"
58 : #include "log.h"
59 :
60 : int
61 1420 : evutil_socketpair(int family, int type, int protocol, int fd[2])
62 : {
63 : #ifndef WIN32
64 1420 : return socketpair(family, type, protocol, fd);
65 : #else
66 : /* This code is originally from Tor. Used with permission. */
67 :
68 : /* This socketpair does not work when localhost is down. So
69 : * it's really not the same thing at all. But it's close enough
70 : * for now, and really, when localhost is down sometimes, we
71 : * have other problems too.
72 : */
73 : int listener = -1;
74 : int connector = -1;
75 : int acceptor = -1;
76 : struct sockaddr_in listen_addr;
77 : struct sockaddr_in connect_addr;
78 : int size;
79 : int saved_errno = -1;
80 :
81 : if (protocol
82 : #ifdef AF_UNIX
83 : || family != AF_UNIX
84 : #endif
85 : ) {
86 : EVUTIL_SET_SOCKET_ERROR(WSAEAFNOSUPPORT);
87 : return -1;
88 : }
89 : if (!fd) {
90 : EVUTIL_SET_SOCKET_ERROR(WSAEINVAL);
91 : return -1;
92 : }
93 :
94 : listener = socket(AF_INET, type, 0);
95 : if (listener < 0)
96 : return -1;
97 : memset(&listen_addr, 0, sizeof(listen_addr));
98 : listen_addr.sin_family = AF_INET;
99 : listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
100 : listen_addr.sin_port = 0; /* kernel chooses port. */
101 : if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr))
102 : == -1)
103 : goto tidy_up_and_fail;
104 : if (listen(listener, 1) == -1)
105 : goto tidy_up_and_fail;
106 :
107 : connector = socket(AF_INET, type, 0);
108 : if (connector < 0)
109 : goto tidy_up_and_fail;
110 : /* We want to find out the port number to connect to. */
111 : size = sizeof(connect_addr);
112 : if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
113 : goto tidy_up_and_fail;
114 : if (size != sizeof (connect_addr))
115 : goto abort_tidy_up_and_fail;
116 : if (connect(connector, (struct sockaddr *) &connect_addr,
117 : sizeof(connect_addr)) == -1)
118 : goto tidy_up_and_fail;
119 :
120 : size = sizeof(listen_addr);
121 : acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
122 : if (acceptor < 0)
123 : goto tidy_up_and_fail;
124 : if (size != sizeof(listen_addr))
125 : goto abort_tidy_up_and_fail;
126 : EVUTIL_CLOSESOCKET(listener);
127 : /* Now check we are talking to ourself by matching port and host on the
128 : two sockets. */
129 : if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)
130 : goto tidy_up_and_fail;
131 : if (size != sizeof (connect_addr)
132 : || listen_addr.sin_family != connect_addr.sin_family
133 : || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
134 : || listen_addr.sin_port != connect_addr.sin_port)
135 : goto abort_tidy_up_and_fail;
136 : fd[0] = connector;
137 : fd[1] = acceptor;
138 :
139 : return 0;
140 :
141 : abort_tidy_up_and_fail:
142 : saved_errno = WSAECONNABORTED;
143 : tidy_up_and_fail:
144 : if (saved_errno < 0)
145 : saved_errno = WSAGetLastError();
146 : if (listener != -1)
147 : EVUTIL_CLOSESOCKET(listener);
148 : if (connector != -1)
149 : EVUTIL_CLOSESOCKET(connector);
150 : if (acceptor != -1)
151 : EVUTIL_CLOSESOCKET(acceptor);
152 :
153 : EVUTIL_SET_SOCKET_ERROR(saved_errno);
154 : return -1;
155 : #endif
156 : }
157 :
158 : int
159 1420 : evutil_make_socket_nonblocking(int fd)
160 : {
161 : #ifdef WIN32
162 : {
163 : unsigned long nonblocking = 1;
164 : ioctlsocket(fd, FIONBIO, (unsigned long*) &nonblocking);
165 : }
166 : #else
167 1420 : if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
168 0 : event_warn("fcntl(O_NONBLOCK)");
169 0 : return -1;
170 : }
171 : #endif
172 1420 : return 0;
173 : }
174 :
175 : ev_int64_t
176 0 : evutil_strtoll(const char *s, char **endptr, int base)
177 : {
178 : #ifdef HAVE_STRTOLL
179 0 : return (ev_int64_t)strtoll(s, endptr, base);
180 : #elif SIZEOF_LONG == 8
181 : return (ev_int64_t)strtol(s, endptr, base);
182 : #elif defined(WIN32) && defined(_MSC_VER) && _MSC_VER < 1300
183 : /* XXXX on old versions of MS APIs, we only support base
184 : * 10. */
185 : ev_int64_t r;
186 : if (base != 10)
187 : return 0;
188 : r = (ev_int64_t) _atoi64(s);
189 : while (isspace(*s))
190 : ++s;
191 : while (isdigit(*s))
192 : ++s;
193 : if (endptr)
194 : *endptr = (char*) s;
195 : return r;
196 : #elif defined(WIN32)
197 : return (ev_int64_t) _strtoi64(s, endptr, base);
198 : #else
199 : #error "I don't know how to parse 64-bit integers."
200 : #endif
201 : }
202 :
203 : #ifndef _EVENT_HAVE_GETTIMEOFDAY
204 : int
205 : evutil_gettimeofday(struct timeval *tv, struct timezone *tz)
206 : {
207 : struct _timeb tb;
208 :
209 : if(tv == NULL)
210 : return -1;
211 :
212 : _ftime(&tb);
213 : tv->tv_sec = (long) tb.time;
214 : tv->tv_usec = ((int) tb.millitm) * 1000;
215 : return 0;
216 : }
217 : #endif
218 :
219 : int
220 0 : evutil_snprintf(char *buf, size_t buflen, const char *format, ...)
221 : {
222 : int r;
223 : va_list ap;
224 0 : va_start(ap, format);
225 0 : r = evutil_vsnprintf(buf, buflen, format, ap);
226 0 : va_end(ap);
227 0 : return r;
228 : }
229 :
230 : int
231 0 : evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap)
232 : {
233 : #ifdef _MSC_VER
234 : int r = _vsnprintf(buf, buflen, format, ap);
235 : buf[buflen-1] = '\0';
236 : if (r >= 0)
237 : return r;
238 : else
239 : return _vscprintf(format, ap);
240 : #else
241 0 : int r = vsnprintf(buf, buflen, format, ap);
242 0 : buf[buflen-1] = '\0';
243 0 : return r;
244 : #endif
245 : }
|