Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ZerXes
Tor
Commits
cd3467bb
Commit
cd3467bb
authored
Aug 14, 2003
by
Nick Mathewson
🥄
Browse files
Attempt to make sockets code work right on windows.
svn:r398
parent
88edae94
Changes
12
Hide whitespace changes
Inline
Side-by-side
src/common/fakepoll.c
View file @
cd3467bb
...
...
@@ -8,6 +8,7 @@
#include
"orconfig.h"
#include
"fakepoll.h"
#ifdef USE_FAKE_POLL
#include
<sys/types.h>
#ifdef HAVE_UNISTD_H
...
...
@@ -30,6 +31,9 @@ poll(struct pollfd *ufds, unsigned int nfds, int timeout)
{
unsigned
int
idx
,
maxfd
,
fd
;
int
r
;
#ifdef MS_WINDOWS
int
any_fds_set
=
0
;
#endif
fd_set
readfds
,
writefds
,
exceptfds
;
#ifdef USING_FAKE_TIMEVAL
#undef timeval
...
...
@@ -46,15 +50,26 @@ poll(struct pollfd *ufds, unsigned int nfds, int timeout)
maxfd
=
-
1
;
for
(
idx
=
0
;
idx
<
nfds
;
++
idx
)
{
fd
=
ufds
[
idx
].
fd
;
if
(
fd
>
maxfd
&&
ufds
[
idx
].
events
)
maxfd
=
fd
;
if
(
ufds
[
idx
].
events
&
(
POLLIN
))
if
(
ufds
[
idx
].
events
)
{
if
(
fd
>
maxfd
)
maxfd
=
fd
;
#ifdef MS_WINDOWS
any_fds_set
=
1
;
#endif
}
if
(
ufds
[
idx
].
events
&
POLLIN
)
FD_SET
(
fd
,
&
readfds
);
if
(
ufds
[
idx
].
events
&
POLLOUT
)
FD_SET
(
fd
,
&
writefds
);
if
(
ufds
[
idx
].
events
&
(
POLLERR
)
)
if
(
ufds
[
idx
].
events
&
POLLERR
)
FD_SET
(
fd
,
&
exceptfds
);
}
#ifdef MS_WINDOWS
if
(
!
any_fds_set
)
{
usleep
(
timeout
);
return
0
;
}
#endif
r
=
select
(
maxfd
+
1
,
&
readfds
,
&
writefds
,
&
exceptfds
,
timeout
==
-
1
?
NULL
:
&
_timeout
);
if
(
r
<=
0
)
...
...
src/common/util.c
View file @
cd3467bb
...
...
@@ -4,7 +4,7 @@
#include
"../or/or.h"
#ifdef
_
MS
C_VER
#ifdef MS
_WINDOWS
#include
<io.h>
#include
<limits.h>
#include
<process.h>
...
...
@@ -90,7 +90,7 @@ void tv_addms(struct timeval *a, long ms) {
void
set_socket_nonblocking
(
int
socket
)
{
#ifdef
_
MS
C_VER
#ifdef MS
_WINDOWS
/* Yes means no and no means yes. Do you not want to be nonblocking? */
int
nonblocking
=
0
;
ioctlsocket
(
socket
,
FIONBIO
,
(
unsigned
long
*
)
&
nonblocking
);
...
...
@@ -101,7 +101,7 @@ void set_socket_nonblocking(int socket)
int
spawn_func
(
int
(
*
func
)(
void
*
),
void
*
data
)
{
#ifdef
_
MS
C_VER
#ifdef MS
_WINDOWS
int
rv
;
rv
=
_beginthread
(
func
,
0
,
data
);
if
(
rv
==
(
unsigned
long
)
-
1
)
...
...
@@ -125,7 +125,7 @@ int spawn_func(int (*func)(void *), void *data)
void
spawn_exit
()
{
#ifdef
_
MS
C_VER
#ifdef MS
_WINDOWS
_endthread
();
#else
exit
(
0
);
...
...
@@ -137,7 +137,7 @@ void spawn_exit()
int
tor_socketpair
(
int
family
,
int
type
,
int
protocol
,
int
fd
[
2
])
{
#ifdef HAVE_SOCKETPAIR_XXX
#ifdef HAVE_SOCKETPAIR_XXX
X
/* For testing purposes, we never fall back to real socketpairs. */
return
socketpair
(
family
,
type
,
protocol
,
fd
);
#else
...
...
@@ -153,8 +153,8 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
||
family
!=
AF_UNIX
#endif
)
{
#ifdef
_
MS
C_VER
errno
=
WSAEAFNOSUPPORT
;
#ifdef MS
_WINDOWS
errno
=
WSAEAFNOSUPPORT
;
#else
errno
=
EAFNOSUPPORT
;
#endif
...
...
@@ -213,7 +213,7 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
return
0
;
abort_tidy_up_and_fail:
#ifdef
_
MS
C_VER
#ifdef MS
_WINDOWS
errno
=
WSAECONNABORTED
;
#else
errno
=
ECONNABORTED
;
/* I hope this is portable and appropriate. */
...
...
@@ -232,3 +232,16 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
}
#endif
}
#ifdef MS_WINDOWS
int
correct_socket_errno
(
int
s
)
{
int
r
,
optval
,
optvallen
=
sizeof
(
optval
);
assert
(
errno
==
WSAEWOULDBLOCK
);
if
(
getsockopt
(
s
,
SOL_SOCKET
,
SO_ERROR
,
(
void
*
)
&
optval
,
&
optvallen
))
return
errno
;
if
(
optval
)
return
optval
;
return
WSAEWOULDBLOCK
;
}
#endif
src/common/util.h
View file @
cd3467bb
...
...
@@ -13,6 +13,12 @@
#ifdef HAVE_TIME_H
#include
<time.h>
#endif
#if _MSC_VER > 1300
#include
<winsock2.h>
#include
<ws2tcpip.h>
#elif defined(_MSC_VER)
#include
<winsock.h>
#endif
#ifndef HAVE_GETTIMEOFDAY
#ifdef HAVE_FTIME
#define USING_FAKE_TIMEVAL
...
...
@@ -23,7 +29,7 @@
#endif
#endif
#ifdef
_
MS
C_VER
#ifdef MS
_WINDOWS
/* Windows names string functions funnily. */
#define strncasecmp strnicmp
#define strcasecmp stricmp
...
...
@@ -55,4 +61,24 @@ void spawn_exit();
int
tor_socketpair
(
int
family
,
int
type
,
int
protocol
,
int
fd
[
2
]);
/* For stupid historical reasons, windows sockets have an independent set of
* errnos which they use as the fancy strikes them.
*/
#ifdef MS_WINDOWS
#define ERRNO_EAGAIN(e) ((e) == EAGAIN || \
(e) == WSAEWOULDBLOCK || \
(e) == EWOULDBLOCK)
#define ERRNO_EINPROGRESS(e) ((e) == EINPROGRESS || \
(e) == WSAEINPROGRESS)
#define ERRNO_CONN_EINPROGRESS(e) ((e) == EINPROGRESS || \
(e) == WSAEINPROGRESS || (e) == WSAEINVAL)
int
correct_socket_errno
(
int
s
);
#else
#define ERRNO_EAGAIN(e) ((e) == EAGAIN)
#define ERRNO_EINPROGRESS(e) ((e) == EINPROGRESS)
#define ERRNO_CONN_EINPROGRESS(e) ((e) == EINPROGRESS)
#define correct_socket_errno(s) (errno)
#endif
#endif
src/or/buffers.c
View file @
cd3467bb
...
...
@@ -36,6 +36,9 @@ void buf_free(char *buf) {
int
read_to_buf
(
int
s
,
int
at_most
,
char
**
buf
,
int
*
buflen
,
int
*
buf_datalen
,
int
*
reached_eof
)
{
int
read_result
;
#ifdef MS_WINDOWS
int
e
;
#endif
assert
(
buf
&&
*
buf
&&
buflen
&&
buf_datalen
&&
reached_eof
&&
(
s
>=
0
));
...
...
@@ -62,9 +65,15 @@ int read_to_buf(int s, int at_most, char **buf, int *buflen, int *buf_datalen, i
// log_fn(LOG_DEBUG,"reading at most %d bytes.",at_most);
read_result
=
read
(
s
,
*
buf
+*
buf_datalen
,
at_most
);
if
(
read_result
<
0
)
{
if
(
errno
!=
EAGAIN
)
{
/* it's a real error */
if
(
!
ERRNO_EAGAIN
(
errno
)
)
{
/* it's a real error */
return
-
1
;
}
#ifdef MS_WINDOWS
e
=
correct_socket_errno
(
s
);
if
(
!
ERRNO_EAGAIN
(
errno
))
{
/* no, it *is* a real error! */
return
-
1
;
}
#endif
return
0
;
}
else
if
(
read_result
==
0
)
{
log_fn
(
LOG_DEBUG
,
"Encountered eof"
);
...
...
@@ -84,6 +93,9 @@ int flush_buf(int s, char **buf, int *buflen, int *buf_flushlen, int *buf_datale
* return -1 or how many bytes remain to be flushed */
int
write_result
;
#ifdef MS_WINDOWS
int
e
;
#endif
assert
(
buf
&&
*
buf
&&
buflen
&&
buf_flushlen
&&
buf_datalen
&&
(
s
>=
0
)
&&
(
*
buf_flushlen
<=
*
buf_datalen
));
...
...
@@ -94,9 +106,15 @@ int flush_buf(int s, char **buf, int *buflen, int *buf_flushlen, int *buf_datale
write_result
=
write
(
s
,
*
buf
,
*
buf_flushlen
);
if
(
write_result
<
0
)
{
if
(
errno
!=
EAGAIN
)
{
/* it's a real error */
if
(
!
ERRNO_EAGAIN
(
errno
))
{
/* it's a real error */
return
-
1
;
}
#ifdef MS_WINDOWS
e
=
correct_socket_errno
(
s
);
if
(
!
ERRNO_EAGAIN
(
errno
))
{
/* no, it *is* a real error! */
return
-
1
;
}
#endif
log_fn
(
LOG_DEBUG
,
"write() would block, returning."
);
return
0
;
}
else
{
...
...
src/or/connection.c
View file @
cd3467bb
...
...
@@ -188,11 +188,21 @@ int connection_handle_listener_read(connection_t *conn, int new_type, int new_st
connection_t
*
newconn
;
struct
sockaddr_in
remote
;
/* information about the remote peer when connecting to other routers */
int
remotelen
=
sizeof
(
struct
sockaddr_in
);
/* length of the remote address */
#ifdef MS_WINDOWS
int
e
;
#endif
news
=
accept
(
conn
->
s
,(
struct
sockaddr
*
)
&
remote
,
&
remotelen
);
if
(
news
==
-
1
)
{
/* accept() error */
if
(
errno
==
EAGAIN
)
if
(
ERRNO_EAGAIN
(
errno
))
{
#ifdef MS_WINDOWS
e
=
correct_socket_errno
(
conn
->
s
);
if
(
ERRNO_EAGAIN
(
e
))
return
0
;
#else
return
0
;
/* he hung up before we could accept(). that's fine. */
#endif
}
/* else there was a real error. */
log_fn
(
LOG_ERR
,
"accept() failed. Closing."
);
return
-
1
;
...
...
src/or/connection_edge.c
View file @
cd3467bb
...
...
@@ -265,7 +265,7 @@ int connection_edge_finished_flushing(connection_t *conn) {
switch
(
conn
->
state
)
{
case
EXIT_CONN_STATE_CONNECTING
:
if
(
getsockopt
(
conn
->
s
,
SOL_SOCKET
,
SO_ERROR
,
(
void
*
)
&
e
,
&
len
)
<
0
)
{
/* not yet */
if
(
errno
!=
EINPROGRESS
)
{
if
(
!
ERRNO_CONN_
EINPROGRESS
(
errno
))
{
/* yuck. kill it. */
log_fn
(
LOG_DEBUG
,
"in-progress exit connect failed. Removing."
);
return
-
1
;
...
...
src/or/connection_exit.c
View file @
cd3467bb
...
...
@@ -90,7 +90,7 @@ int connection_exit_connect(connection_t *conn) {
log_fn
(
LOG_DEBUG
,
"Connecting to %s:%u."
,
conn
->
address
,
conn
->
port
);
if
(
connect
(
s
,(
struct
sockaddr
*
)
&
dest_addr
,
sizeof
(
dest_addr
))
<
0
)
{
if
(
errno
!=
EINPROGRESS
)
{
if
(
!
ERRNO_CONN_
EINPROGRESS
(
errno
))
{
/* yuck. kill it. */
perror
(
"connect"
);
log_fn
(
LOG_DEBUG
,
"Connect failed."
);
...
...
@@ -102,7 +102,9 @@ int connection_exit_connect(connection_t *conn) {
conn
->
state
=
EXIT_CONN_STATE_CONNECTING
;
log_fn
(
LOG_DEBUG
,
"connect in progress, socket %d."
,
s
);
connection_watch_events
(
conn
,
POLLOUT
|
POLLIN
);
connection_watch_events
(
conn
,
POLLOUT
|
POLLIN
|
POLLERR
);
/* writable indicates finish, readable indicates broken link,
error indicates broken link in windowsland. */
return
0
;
}
}
...
...
src/or/connection_or.c
View file @
cd3467bb
...
...
@@ -62,7 +62,7 @@ int connection_or_finished_flushing(connection_t *conn) {
return
or_handshake_op_finished_sending_keys
(
conn
);
case
OR_CONN_STATE_CLIENT_CONNECTING
:
if
(
getsockopt
(
conn
->
s
,
SOL_SOCKET
,
SO_ERROR
,
(
void
*
)
&
e
,
&
len
)
<
0
)
{
/* not yet */
if
(
errno
!=
EINPROGRESS
){
if
(
!
ERRNO_CONN_
EINPROGRESS
(
errno
)
){
/* yuck. kill it. */
log_fn
(
LOG_DEBUG
,
"in-progress connect failed. Removing."
);
return
-
1
;
...
...
@@ -156,7 +156,7 @@ connection_t *connection_or_connect(routerinfo_t *router) {
log
(
LOG_DEBUG
,
"connection_or_connect() : Trying to connect to %s:%u."
,
router
->
address
,
router
->
or_port
);
if
(
connect
(
s
,(
struct
sockaddr
*
)
&
router_addr
,
sizeof
(
router_addr
))
<
0
){
if
(
errno
!=
EINPROGRESS
)
{
if
(
!
ERRNO_CONN_
EINPROGRESS
(
errno
))
{
/* yuck. kill it. */
connection_free
(
conn
);
return
NULL
;
...
...
@@ -170,7 +170,9 @@ connection_t *connection_or_connect(routerinfo_t *router) {
}
log
(
LOG_DEBUG
,
"connection_or_connect() : connect in progress."
);
connection_watch_events
(
conn
,
POLLIN
|
POLLOUT
);
/* writable indicates finish, readable indicates broken link */
connection_watch_events
(
conn
,
POLLIN
|
POLLOUT
|
POLLERR
);
/* writable indicates finish, readable indicates broken link,
error indicates broken link on windows */
conn
->
state
=
OR_CONN_STATE_CLIENT_CONNECTING
;
return
conn
;
}
...
...
src/or/directory.c
View file @
cd3467bb
...
...
@@ -66,7 +66,7 @@ void directory_initiate_fetch(routerinfo_t *router) {
log_fn
(
LOG_DEBUG
,
"Trying to connect to %s:%u."
,
router
->
address
,
router
->
dir_port
);
if
(
connect
(
s
,(
struct
sockaddr
*
)
&
router_addr
,
sizeof
(
router_addr
))
<
0
){
if
(
errno
!=
EINPROGRESS
)
{
if
(
!
ERRNO_CONN_
EINPROGRESS
(
errno
))
{
/* yuck. kill it. */
router_forget_router
(
conn
->
addr
,
conn
->
port
);
/* don't try him again */
connection_free
(
conn
);
...
...
@@ -81,7 +81,9 @@ void directory_initiate_fetch(routerinfo_t *router) {
}
log_fn
(
LOG_DEBUG
,
"connect in progress."
);
connection_watch_events
(
conn
,
POLLIN
|
POLLOUT
);
/* writable indicates finish, readable indicates broken link */
connection_watch_events
(
conn
,
POLLIN
|
POLLOUT
|
POLLERR
);
/* writable indicates finish, readable indicates broken link,
error indicates broken link in windowsland. */
conn
->
state
=
DIR_CONN_STATE_CONNECTING
;
return
;
}
...
...
@@ -255,7 +257,7 @@ int connection_dir_finished_flushing(connection_t *conn) {
switch
(
conn
->
state
)
{
case
DIR_CONN_STATE_CONNECTING
:
if
(
getsockopt
(
conn
->
s
,
SOL_SOCKET
,
SO_ERROR
,
(
void
*
)
&
e
,
&
len
)
<
0
)
{
/* not yet */
if
(
errno
!=
EINPROGRESS
)
{
if
(
!
ERRNO_CONN_
EINPROGRESS
(
errno
))
{
/* yuck. kill it. */
log_fn
(
LOG_DEBUG
,
"in-progress connect failed. Removing."
);
router_forget_router
(
conn
->
addr
,
conn
->
port
);
/* don't try him again */
...
...
src/or/main.c
View file @
cd3467bb
...
...
@@ -243,7 +243,6 @@ void connection_start_writing(connection_t *conn) {
poll_array
[
conn
->
poll_index
].
events
|=
POLLOUT
;
}
static
void
conn_read
(
int
i
)
{
int
retval
;
connection_t
*
conn
;
...
...
@@ -252,6 +251,13 @@ static void conn_read(int i) {
assert
(
conn
);
// log_fn(LOG_DEBUG,"socket %d has something to read.",conn->s);
#ifdef MS_WINDOWS
if
(
poll_array
[
i
].
revents
&
POLLERR
)
{
retval
=
-
1
;
goto
error
;
}
#endif
if
(
conn
->
type
==
CONN_TYPE_OR_LISTENER
)
{
retval
=
connection_or_handle_listener_read
(
conn
);
}
else
if
(
conn
->
type
==
CONN_TYPE_AP_LISTENER
)
{
...
...
@@ -274,14 +280,17 @@ static void conn_read(int i) {
}
}
#ifdef MS_WINDOWS
error:
#endif
if
(
retval
<
0
)
{
/* this connection is broken. remove it */
log_fn
(
LOG_INFO
,
"%s connection broken, removing."
,
conn_type_to_string
[
conn
->
type
]);
connection_remove
(
conn
);
connection_free
(
conn
);
if
(
i
<
nfds
)
{
/* we just replaced the one at i with a new one.
process it too. */
if
(
poll_array
[
i
].
revents
&
POLLIN
||
poll_array
[
i
].
revents
&
POLLHUP
)
/* something to read */
if
(
poll_array
[
i
].
revents
&
(
POLLIN
|
POLLHUP
|
POLLERR
))
/* something to read */
conn_read
(
i
);
}
}
...
...
@@ -565,10 +574,10 @@ static int do_main_loop(void) {
}
if
(
poll_result
>
0
)
{
/* we have at least one connection to deal with */
/* do all the reads first, so we can detect closed sockets */
/* do all the reads
and errors
first, so we can detect closed sockets */
for
(
i
=
0
;
i
<
nfds
;
i
++
)
if
(
poll_array
[
i
].
revents
&
POLLIN
||
poll_array
[
i
].
revents
&
POLLHUP
)
/* something to read */
if
(
poll_array
[
i
].
revents
&
(
POLLIN
|
POLLHUP
|
POLLERR
))
/* something to read
, or an error.
*/
conn_read
(
i
);
/* this also blows away broken connections */
/* see http://www.greenend.org.uk/rjk/2001/06/poll.html for discussion
* of POLLIN vs POLLHUP */
...
...
src/or/or.h
View file @
cd3467bb
...
...
@@ -89,7 +89,6 @@
#define snprintf _snprintf
#endif
#include
"../common/crypto.h"
#include
"../common/log.h"
#include
"../common/util.h"
...
...
src/or/test.c
View file @
cd3467bb
...
...
@@ -7,7 +7,7 @@
#include
<fcntl.h>
#endif
#ifdef
_
MS
C_VER
#ifdef MS
_WINDOWS
/* For mkdir() */
#include
<direct.h>
#endif
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment