Cleaned it up so that code paths which have unsupported WS_SO values

never actually pass them to Unix system calls.
This commit is contained in:
John Gilmore 2000-09-16 20:51:40 +00:00 committed by Alexandre Julliard
parent 5bb74648d8
commit 5180d5635d
1 changed files with 49 additions and 28 deletions

View File

@ -178,17 +178,22 @@ static HANDLE _WSHeap = 0;
static INT _ws_sock_ops[] = static INT _ws_sock_ops[] =
{ WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE, { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF, WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE, WS_SO_DONTLINGER, WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE,
#ifdef SO_RCVTIMEO #ifdef SO_RCVTIMEO
WS_SO_RCVTIMEO, WS_SO_RCVTIMEO,
#endif
#ifdef SO_SNDTIMEO
WS_SO_SNDTIMEO,
#endif #endif
0 }; 0 };
static int _px_sock_ops[] = static int _px_sock_ops[] =
{ SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST, { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE, SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
WS_SO_DONTLINGER, /* no unix equivalent */
#ifdef SO_RCVTIMEO #ifdef SO_RCVTIMEO
SO_RCVTIMEO, SO_RCVTIMEO,
#endif
#ifdef SO_SNDTIMEO
SO_SNDTIMEO,
#endif #endif
}; };
@ -390,8 +395,9 @@ BOOL WINAPI WINSOCK_LibMain(DWORD fdwReason, HINSTANCE hInstDLL, WORD ds,
* convert_sockopt() * convert_sockopt()
* *
* Converts socket flags from Windows format. * Converts socket flags from Windows format.
* Return 1 if converted, 0 if not (error).
*/ */
static void convert_sockopt(INT *level, INT *optname) static int convert_sockopt(INT *level, INT *optname)
{ {
int i; int i;
switch (*level) switch (*level)
@ -400,17 +406,24 @@ static void convert_sockopt(INT *level, INT *optname)
*level = SOL_SOCKET; *level = SOL_SOCKET;
for(i=0; _ws_sock_ops[i]; i++) for(i=0; _ws_sock_ops[i]; i++)
if( _ws_sock_ops[i] == *optname ) break; if( _ws_sock_ops[i] == *optname ) break;
if( _ws_sock_ops[i] ) *optname = _px_sock_ops[i]; if( _ws_sock_ops[i] ) {
else FIXME("Unknown SOL_SOCKET optname %d\n", *optname); *optname = _px_sock_ops[i];
return 1;
}
FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
break; break;
case WS_IPPROTO_TCP: case WS_IPPROTO_TCP:
*level = IPPROTO_TCP; *level = IPPROTO_TCP;
for(i=0; _ws_tcp_ops[i]; i++) for(i=0; _ws_tcp_ops[i]; i++)
if ( _ws_tcp_ops[i] == *optname ) break; if ( _ws_tcp_ops[i] == *optname ) break;
if( _ws_tcp_ops[i] ) *optname = _px_tcp_ops[i]; if( _ws_tcp_ops[i] ) {
else FIXME("Unknown IPPROTO_TCP optname %d\n", *optname); *optname = _px_tcp_ops[i];
return 1;
}
FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
break; break;
} }
return 0;
} }
/* ----------------------------------- Per-thread info (or per-process?) */ /* ----------------------------------- Per-thread info (or per-process?) */
@ -1224,13 +1237,16 @@ INT WINAPI WSOCK32_getsockopt(SOCKET s, INT level,
if( _check_ws(pwsi, s) ) if( _check_ws(pwsi, s) )
{ {
int fd = _get_sock_fd(s); int fd = _get_sock_fd(s);
convert_sockopt(&level, &optname); if (!convert_sockopt(&level, &optname)) {
if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 ) SetLastError(WSAENOPROTOOPT); /* Unknown option */
{ } else {
close(fd); if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
return 0; {
close(fd);
return 0;
}
SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
} }
SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
close(fd); close(fd);
} }
return SOCKET_ERROR; return SOCKET_ERROR;
@ -2064,28 +2080,33 @@ INT WINAPI WSOCK32_setsockopt(SOCKET16 s, INT level, INT optname,
int fd = _get_sock_fd(s); int fd = _get_sock_fd(s);
int woptval; int woptval;
convert_sockopt(&level, &optname);
if(optname == WS_SO_DONTLINGER) { if(optname == WS_SO_DONTLINGER) {
/* This is unique to WinSock and takes special conversion */
linger.l_onoff = *((int*)optval) ? 0: 1; linger.l_onoff = *((int*)optval) ? 0: 1;
linger.l_linger = 0; linger.l_linger = 0;
optname=SO_LINGER; optname=SO_LINGER;
optval = (char*)&linger; optval = (char*)&linger;
optlen = sizeof(struct linger); optlen = sizeof(struct linger);
}else{ }else{
if (optname == SO_LINGER && optval) { if (!convert_sockopt(&level, &optname)) {
/* yes, uses unsigned short in both win16/win32 */ SetLastError(WSAENOPROTOOPT);
linger.l_onoff = ((UINT16*)optval)[0]; close(fd);
linger.l_linger = ((UINT16*)optval)[1]; return SOCKET_ERROR;
/* FIXME: what is documented behavior if SO_LINGER optval }
is null?? */ }
optval = (char*)&linger; if (optname == SO_LINGER && optval) {
optlen = sizeof(struct linger); /* yes, uses unsigned short in both win16/win32 */
} else if (optlen < sizeof(int)){ linger.l_onoff = ((UINT16*)optval)[0];
woptval= *((INT16 *) optval); linger.l_linger = ((UINT16*)optval)[1];
optval= (char*) &woptval; /* FIXME: what is documented behavior if SO_LINGER optval
optlen=sizeof(int); is null?? */
} optval = (char*)&linger;
} optlen = sizeof(struct linger);
} else if (optlen < sizeof(int)){
woptval= *((INT16 *) optval);
optval= (char*) &woptval;
optlen=sizeof(int);
}
if (setsockopt(fd, level, optname, optval, optlen) == 0) if (setsockopt(fd, level, optname, optval, optlen) == 0)
{ {
close(fd); close(fd);