Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Christian Butz
VTK
Commits
22e19e78
Commit
22e19e78
authored
Apr 21, 2011
by
David Partyka
Browse files
Merge branch '12087-vtksocket' into release
parents
e6760e8b
bafa6bf9
Changes
2
Hide whitespace changes
Inline
Side-by-side
Common/vtkSocket.cxx
View file @
22e19e78
...
...
@@ -16,6 +16,10 @@
#include "vtkObjectFactory.h"
#if defined(__BORLANDC__)
# pragma warn -8012
/* signed/unsigned comparison */
#endif
// The VTK_SOCKET_FAKE_API definition is given to the compiler
// command line by CMakeLists.txt if there is no real sockets
// interface available. When this macro is defined we simply make
...
...
@@ -38,25 +42,86 @@
#include <unistd.h>
#include <sys/time.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#endif
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
// TODO : document why we restrict to v1.1
#define WSA_VERSION MAKEWORD(1,1)
#define vtkCloseSocketMacro(sock) (closesocket(sock))
#define vtkCloseSocketMacro(sock) (closesocket(sock))
#define vtkErrnoMacro (WSAGetLastError())
#define vtkStrerrorMacro(_num) (wsaStrerror(_num))
#define vtkSocketErrorIdMacro(_id) (WSA##_id)
#define vtkSocketErrorReturnMacro (SOCKET_ERROR)
#else
#define vtkCloseSocketMacro(sock) (close(sock))
#define vtkCloseSocketMacro(sock) (close(sock))
#define vtkErrnoMacro (errno)
#define vtkStrerrorMacro(_num) (strerror(_num))
#define vtkSocketErrorIdMacro(_id) (_id)
#define vtkSocketErrorReturnMacro (-1)
#endif
#if defined(__BORLANDC__)
# pragma warn -8012
/* signed/unsigned comparison */
// This macro wraps a system function call(_call),
// restarting the call in case it was interrupted
// by a signal (EINTR).
#define vtkRestartInterruptedSystemCallMacro(_call,_ret)\
do \
{ \
(_ret)=(_call); \
} \
while (((_ret)==vtkSocketErrorReturnMacro) \
&& (vtkErrnoMacro==vtkSocketErrorIdMacro(EINTR)));
// use when _str may be a null pointer but _fallback is not.
#define vtkSafeStrMacro(_str,_fallback) ((_str)?(_str):(_fallback))
// convert error number to string and report via vtkErrorMacro.
#define vtkSocketErrorMacro(_eno, _message) \
vtkErrorMacro( \
<< (_message) \
<< " " \
<< vtkSafeStrMacro( \
vtkStrerrorMacro(_eno), \
"unknown error") \
<< ".");
// convert error number to string and report via vtkGenericWarningMacro
#define vtkSocketGenericErrorMacro(_message) \
vtkGenericWarningMacro( \
<< (_message) \
<< " " \
<< vtkSafeStrMacro( \
vtkStrerrorMacro(vtkErrnoMacro), \
"unknown error") \
<< ".");
// on windows strerror doesn't handle socket error codes
#if defined(_WIN32) && !defined(__CYGWIN__)
static
const
char
*
wsaStrerror
(
int
wsaeid
)
{
static
char
buf
[
256
]
=
{
'\0'
};
int
ok
;
ok
=
FormatMessage
(
FORMAT_MESSAGE_FROM_SYSTEM
,
0
,
wsaeid
,
0
,
buf
,
256
,
0
);
if
(
!
ok
)
{
return
0
;
}
return
buf
;
}
#endif
//-----------------------------------------------------------------------------
vtkSocket
::
vtkSocket
()
{
this
->
SocketDescriptor
=
-
1
;
}
//-----------------------------------------------------------------------------
...
...
@@ -73,19 +138,39 @@ vtkSocket::~vtkSocket()
int
vtkSocket
::
CreateSocket
()
{
#ifndef VTK_SOCKET_FAKE_API
int
sock
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
int
sock
;
vtkRestartInterruptedSystemCallMacro
(
socket
(
AF_INET
,
SOCK_STREAM
,
0
),
sock
);
if
(
sock
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to socket."
);
return
-
1
;
}
// Elimate windows 0.2 second delay sending (buffering) data.
int
on
=
1
;
if
(
setsockopt
(
sock
,
IPPROTO_TCP
,
TCP_NODELAY
,
(
char
*
)
&
on
,
sizeof
(
on
)))
int
iErr
;
vtkRestartInterruptedSystemCallMacro
(
setsockopt
(
sock
,
IPPROTO_TCP
,
TCP_NODELAY
,
(
char
*
)
&
on
,
sizeof
(
on
)),
iErr
);
if
(
iErr
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to setsockopt."
);
return
-
1
;
}
return
sock
;
#else
return
-
1
;
#endif
}
//-----------------------------------------------------------------------------
void
vtkSocket
::
CloseSocket
()
{
this
->
CloseSocket
(
this
->
SocketDescriptor
);
this
->
SocketDescriptor
=
-
1
;
}
//-----------------------------------------------------------------------------
int
vtkSocket
::
BindSocket
(
int
socketdescriptor
,
int
port
)
{
...
...
@@ -97,16 +182,31 @@ int vtkSocket::BindSocket(int socketdescriptor, int port)
server
.
sin_port
=
htons
(
port
);
// Allow the socket to be bound to an address that is already in use
int
opt
=
1
;
int
iErr
=~
vtkSocketErrorReturnMacro
;
#ifdef _WIN32
setsockopt
(
socketdescriptor
,
SOL_SOCKET
,
SO_REUSEADDR
,
(
char
*
)
&
opt
,
sizeof
(
int
));
vtkRestartInterruptedSystemCallMacro
(
setsockopt
(
socketdescriptor
,
SOL_SOCKET
,
SO_REUSEADDR
,(
char
*
)
&
opt
,
sizeof
(
int
)),
iErr
);
#elif defined(VTK_HAVE_SO_REUSEADDR)
setsockopt
(
socketdescriptor
,
SOL_SOCKET
,
SO_REUSEADDR
,
(
void
*
)
&
opt
,
sizeof
(
int
));
vtkRestartInterruptedSystemCallMacro
(
setsockopt
(
socketdescriptor
,
SOL_SOCKET
,
SO_REUSEADDR
,(
char
*
)
&
opt
,
sizeof
(
int
)),
iErr
);
#endif
if
(
iErr
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to setsockopt."
);
return
-
1
;
}
if
(
bind
(
socketdescriptor
,
reinterpret_cast
<
sockaddr
*>
(
&
server
),
sizeof
(
server
))
)
vtkRestartInterruptedSystemCallMacro
(
bind
(
socketdescriptor
,
reinterpret_cast
<
sockaddr
*>
(
&
server
),
sizeof
(
server
)),
iErr
);
if
(
iErr
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to bind."
);
return
-
1
;
}
return
0
;
#else
static_cast
<
void
>
(
socketdescriptor
);
...
...
@@ -121,9 +221,20 @@ int vtkSocket::Accept(int socketdescriptor)
#ifndef VTK_SOCKET_FAKE_API
if
(
socketdescriptor
<
0
)
{
vtkErrorMacro
(
"Invalid descriptor."
);
return
-
1
;
}
return
accept
(
socketdescriptor
,
0
,
0
);
int
newDescriptor
;
vtkRestartInterruptedSystemCallMacro
(
accept
(
socketdescriptor
,
0
,
0
),
newDescriptor
);
if
(
newDescriptor
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to accept."
);
return
-
1
;
}
return
newDescriptor
;
#else
static_cast
<
void
>
(
socketdescriptor
);
return
-
1
;
...
...
@@ -136,9 +247,19 @@ int vtkSocket::Listen(int socketdescriptor)
#ifndef VTK_SOCKET_FAKE_API
if
(
socketdescriptor
<
0
)
{
vtkErrorMacro
(
"Invalid descriptor."
);
return
-
1
;
}
return
listen
(
socketdescriptor
,
1
);
int
iErr
;
vtkRestartInterruptedSystemCallMacro
(
listen
(
socketdescriptor
,
1
),
iErr
);
if
(
iErr
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to listen."
);
return
-
1
;
}
return
0
;
#else
static_cast
<
void
>
(
socketdescriptor
);
return
-
1
;
...
...
@@ -151,32 +272,54 @@ int vtkSocket::SelectSocket(int socketdescriptor, unsigned long msec)
#ifndef VTK_SOCKET_FAKE_API
if
(
socketdescriptor
<
0
)
{
// invalid socket
descriptor.
vtkErrorMacro
(
"Invalid
descriptor.
"
);
return
-
1
;
}
fd_set
rset
;
struct
timeval
tval
;
struct
timeval
*
tvalptr
=
0
;
if
(
msec
>
0
)
int
res
;
do
{
tval
.
tv_sec
=
msec
/
1000
;
tval
.
tv_usec
=
(
msec
%
1000
)
*
1000
;
tvalptr
=
&
tval
;
struct
timeval
tval
;
struct
timeval
*
tvalptr
=
0
;
if
(
msec
>
0
)
{
tval
.
tv_sec
=
msec
/
1000
;
tval
.
tv_usec
=
(
msec
%
1000
)
*
1000
;
tvalptr
=
&
tval
;
}
FD_ZERO
(
&
rset
);
FD_SET
(
socketdescriptor
,
&
rset
);
// block until socket is readable.
res
=
select
(
socketdescriptor
+
1
,
&
rset
,
0
,
0
,
tvalptr
);
}
FD_ZERO
(
&
rset
);
FD_SET
(
socketdescriptor
,
&
rset
);
int
res
=
select
(
socketdescriptor
+
1
,
&
rset
,
0
,
0
,
tvalptr
);
if
(
res
==
0
)
while
((
res
==
vtkSocketErrorReturnMacro
)
&&
(
vtkErrnoMacro
==
vtkSocketErrorIdMacro
(
EINTR
))
);
if
(
res
==
0
)
{
return
0
;
//for time limit expire
// time out
return
0
;
}
if
(
res
<
0
||
!
(
FD_ISSET
(
socketdescriptor
,
&
rset
))
)
else
if
(
res
==
vtkSocketErrorReturnMacro
)
{
// Some error.
// error in the call
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to select."
);
return
-
1
;
}
else
if
(
!
FD_ISSET
(
socketdescriptor
,
&
rset
))
{
vtkErrorMacro
(
"Socket error in select. Descriptor not selected."
);
return
-
1
;
}
// NOTE: not checking for pending errors,these will be handled
// in the next call to read/recv
// The indicated socket has some activity on it.
return
1
;
#else
...
...
@@ -191,50 +334,70 @@ int vtkSocket::SelectSockets(const int* sockets_to_select, int size,
unsigned
long
msec
,
int
*
selected_index
)
{
#ifndef VTK_SOCKET_FAKE_API
int
i
;
int
max_fd
=
-
1
;
*
selected_index
=
-
1
;
if
(
size
<
0
)
if
(
size
<
0
)
{
vtkGenericWarningMacro
(
"Can't select fewer than 0."
);
return
-
1
;
}
fd_set
rset
;
struct
timeval
tval
;
struct
timeval
*
tvalptr
=
0
;
if
(
msec
>
0
)
{
tval
.
tv_sec
=
msec
/
1000
;
tval
.
tv_usec
=
msec
%
1000
;
tvalptr
=
&
tval
;
}
FD_ZERO
(
&
rset
);
for
(
i
=
0
;
i
<
size
;
i
++
)
int
res
=
-
1
;
do
{
FD_SET
(
sockets_to_select
[
i
],
&
rset
);
max_fd
=
(
sockets_to_select
[
i
]
>
max_fd
)
?
sockets_to_select
[
i
]
:
max_fd
;
struct
timeval
tval
;
struct
timeval
*
tvalptr
=
0
;
if
(
msec
>
0
)
{
tval
.
tv_sec
=
msec
/
1000
;
tval
.
tv_usec
=
msec
%
1000
;
tvalptr
=
&
tval
;
}
FD_ZERO
(
&
rset
);
int
max_fd
=
-
1
;
for
(
int
i
=
0
;
i
<
size
;
i
++
)
{
FD_SET
(
sockets_to_select
[
i
],
&
rset
);
max_fd
=
(
sockets_to_select
[
i
]
>
max_fd
?
sockets_to_select
[
i
]
:
max_fd
);
}
// block until one socket is ready to read.
res
=
select
(
max_fd
+
1
,
&
rset
,
0
,
0
,
tvalptr
);
}
int
res
=
select
(
max_fd
+
1
,
&
rset
,
0
,
0
,
tvalptr
);
if
(
res
==
0
)
while
((
res
==
vtkSocketErrorReturnMacro
)
&&
(
vtkErrnoMacro
==
vtkSocketErrorIdMacro
(
EINTR
)));
if
(
res
==
0
)
{
return
0
;
//Timeout
// time out
return
0
;
}
if
(
res
<
0
)
else
if
(
res
==
vtkSocketErrorReturnMacro
)
{
// SelectSocket error.
// error in the call
vtkSocketGenericErrorMacro
(
"Socket error in call to select."
);
return
-
1
;
}
//
check which
socket has some activity.
for
(
i
=
0
;
i
<
size
;
i
++
)
//
find the first
socket
which
has some activity.
for
(
int
i
=
0
;
i
<
size
;
i
++
)
{
if
(
FD_ISSET
(
sockets_to_select
[
i
],
&
rset
)
)
{
// NOTE: not checking for pending errors, these
// will be handled in the next call to read/recv
*
selected_index
=
i
;
return
1
;
}
}
// no activity on any of the sockets
vtkGenericWarningMacro
(
"Socket error in select. No descriptor selected."
);
return
-
1
;
#else
static_cast
<
void
>
(
sockets_to_select
);
...
...
@@ -251,6 +414,7 @@ int vtkSocket::Connect(int socketdescriptor, const char* hostName, int port)
#ifndef VTK_SOCKET_FAKE_API
if
(
socketdescriptor
<
0
)
{
vtkErrorMacro
(
"Invalid descriptor."
);
return
-
1
;
}
...
...
@@ -261,10 +425,9 @@ int vtkSocket::Connect(int socketdescriptor, const char* hostName, int port)
unsigned
long
addr
=
inet_addr
(
hostName
);
hp
=
gethostbyaddr
((
char
*
)
&
addr
,
sizeof
(
addr
),
AF_INET
);
}
if
(
!
hp
)
{
//
vtkErrorMacro("Unknown host: " << hostName);
vtkErrorMacro
(
"Unknown host: "
<<
hostName
);
return
-
1
;
}
...
...
@@ -273,8 +436,53 @@ int vtkSocket::Connect(int socketdescriptor, const char* hostName, int port)
memcpy
(
&
name
.
sin_addr
,
hp
->
h_addr
,
hp
->
h_length
);
name
.
sin_port
=
htons
(
port
);
return
connect
(
socketdescriptor
,
reinterpret_cast
<
sockaddr
*>
(
&
name
),
sizeof
(
name
));
int
iErr
=
connect
(
socketdescriptor
,
reinterpret_cast
<
sockaddr
*>
(
&
name
),
sizeof
(
name
));
if
(
(
iErr
==
vtkSocketErrorReturnMacro
)
&&
(
vtkErrnoMacro
==
vtkSocketErrorIdMacro
(
EINTR
))
)
{
// Restarting an interrupted connect call only works on linux,
// other unix require a call to select which blocks until the
// connection is complete.
// See Stevens 2d ed, 15.4 p413, "interrupted connect"
iErr
=
this
->
SelectSocket
(
socketdescriptor
,
0
);
if
(
iErr
==
-
1
)
{
// SelectSocket doesn't test for pending errors.
int
pendingErr
;
#if defined(VTK_HAVE_GETSOCKNAME_WITH_SOCKLEN_T)
socklen_t
pendingErrLen
=
sizeof
(
pendingErr
);
#else
int
pendingErrLen
=
sizeof
(
pendingErr
);
#endif
vtkRestartInterruptedSystemCallMacro
(
getsockopt
(
socketdescriptor
,
SOL_SOCKET
,
SO_ERROR
,
(
char
*
)
&
pendingErr
,
&
pendingErrLen
),
iErr
);
if
(
iErr
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to getsockopt."
);
return
-
1
;
}
else
if
(
pendingErr
)
{
vtkSocketErrorMacro
(
pendingErr
,
"Socket error pending from call to connect."
);
return
-
1
;
}
}
}
else
if
(
iErr
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to connect."
);
return
-
1
;
}
return
0
;
#else
static_cast
<
void
>
(
socketdescriptor
);
static_cast
<
void
>
(
hostName
);
...
...
@@ -294,8 +502,15 @@ int vtkSocket::GetPort(int sock)
#else
int
sizebuf
=
sizeof
(
sockinfo
);
#endif
if
(
getsockname
(
sock
,
reinterpret_cast
<
sockaddr
*>
(
&
sockinfo
),
&
sizebuf
)
!=
0
)
int
iErr
;
vtkRestartInterruptedSystemCallMacro
(
getsockname
(
sock
,
reinterpret_cast
<
sockaddr
*>
(
&
sockinfo
),
&
sizebuf
),
iErr
);
if
(
iErr
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to getsockname."
);
return
0
;
}
return
ntohs
(
sockinfo
.
sin_port
);
...
...
@@ -311,9 +526,18 @@ void vtkSocket::CloseSocket(int socketdescriptor)
#ifndef VTK_SOCKET_FAKE_API
if
(
socketdescriptor
<
0
)
{
vtkErrorMacro
(
"Invalid descriptor."
);
return
;
}
vtkCloseSocketMacro
(
socketdescriptor
);
int
iErr
;
vtkRestartInterruptedSystemCallMacro
(
vtkCloseSocketMacro
(
socketdescriptor
),
iErr
);
if
(
iErr
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to close/closesocket."
);
}
#else
static_cast
<
void
>
(
socketdescriptor
);
return
;
...
...
@@ -326,6 +550,7 @@ int vtkSocket::Send(const void* data, int length)
#ifndef VTK_SOCKET_FAKE_API
if
(
!
this
->
GetConnected
())
{
vtkErrorMacro
(
"Not connected."
);
return
0
;
}
if
(
length
==
0
)
...
...
@@ -337,22 +562,19 @@ int vtkSocket::Send(const void* data, int length)
int
total
=
0
;
do
{
int
flags
;
#if defined(_WIN32) && !defined(__CYGWIN__)
flags
=
0
;
#else
// disabling, since not present on SUN.
// flags = MSG_NOSIGNAL; //disable signal on Unix boxes.
flags
=
0
;
#endif
int
n
=
send
(
this
->
SocketDescriptor
,
buffer
+
total
,
length
-
total
,
flags
);
if
(
n
<
0
)
int
flags
=
0
;
int
nSent
;
vtkRestartInterruptedSystemCallMacro
(
send
(
this
->
SocketDescriptor
,
buffer
+
total
,
length
-
total
,
flags
),
nSent
);
if
(
nSent
==
vtkSocketErrorReturnMacro
)
{
vtkErrorMacro
(
"Socket
E
rror
: Send faile
d."
);
vtk
Socket
ErrorMacro
(
vtkErrnoMacro
,
"Socket
e
rror
in call to sen
d."
);
return
0
;
}
total
+=
n
;
total
+=
n
Sent
;
}
while
(
total
<
length
);
return
1
;
#else
static_cast
<
void
>
(
data
);
...
...
@@ -367,39 +589,49 @@ int vtkSocket::Receive(void* data, int length, int readFully/*=1*/)
#ifndef VTK_SOCKET_FAKE_API
if
(
!
this
->
GetConnected
())
{
vtkErrorMacro
(
"Not connected."
);
return
0
;
}
#if defined(_WIN32) && !defined(__CYGWIN__)
int
trys
=
0
;
#endif
char
*
buffer
=
reinterpret_cast
<
char
*>
(
data
);
int
total
=
0
;
do
{
#if defined(_WIN32) && !defined(__CYGWIN__)
int
trys
=
0
;
#endif
int
n
=
recv
(
this
->
SocketDescriptor
,
buffer
+
total
,
length
-
total
,
0
);
if
(
n
<
1
)
int
nRecvd
;
vtkRestartInterruptedSystemCallMacro
(
recv
(
this
->
SocketDescriptor
,
buffer
+
total
,
length
-
total
,
0
),
nRecvd
);
if
(
nRecvd
==
0
)
{
// peer shut down
return
0
;
}
#if defined(_WIN32) && !defined(__CYGWIN__)
if
((
nRecvd
==
vtkSocketErrorReturnMacro
)
&&
(
WSAGetLastError
()
==
WSAENOBUFS
))
{
// On long messages, Windows recv sometimes fails with WSAENOBUFS, but
// will work if you try again.
int
error
=
WSAGetLastError
();
if
((
error
==
WSAENOBUFS
)
&&
(
trys
++
<
1000
))
if
((
trys
++
<
1000
))
{
Sleep
(
1
);
continue
;
}
#else
// On unix, a recv may be interrupted by a signal. In this case we should
// retry.
int
errorNumber
=
errno
;
if
(
errorNumber
==
EINTR
)
continue
;
#endif
vtkErrorMacro
(
"Socket Error: Receive failed."
);
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to recv."
);
return
0
;
}
total
+=
n
;
}
while
(
readFully
&&
total
<
length
);
#endif
total
+=
nRecvd
;
}
while
(
readFully
&&
(
total
<
length
));
return
total
;
#else
static_cast
<
void
>
(
data
);
...
...
Common/vtkSocket.h
View file @
22e19e78
...
...
@@ -36,7 +36,7 @@ public:
// Description:
// Close the socket.
void
CloseSocket
()
{
this
->
CloseSocket
(
this
->
SocketDescriptor
);}
void
CloseSocket
()
;
// ------ Communication API ---
// Description:
...
...
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