From 2479e06848a7625b1b55511b43f86abc3a76c93d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 3 Mar 2004 13:32:56 +0000 Subject: David Byron's work on making libcurl only require winsock 1.1 on Windows machines. --- lib/Makefile.vc6 | 8 +--- lib/easy.c | 21 +++++---- lib/strtoofft.h | 2 +- lib/telnet.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 141 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/lib/Makefile.vc6 b/lib/Makefile.vc6 index d84f17f3b..e9ddd366e 100644 --- a/lib/Makefile.vc6 +++ b/lib/Makefile.vc6 @@ -48,7 +48,6 @@ CFLAGS = /I "." /I "../include" /nologo /W3 /GX /D "WIN32" /D "VC6" /D "_MBCS" / LNKDLL = link.exe /DLL /def:libcurl.def LNKLIB = link.exe /lib LFLAGS = /nologo -LINKLIBS = ws2_32.lib winmm.lib SSLLIBS = libeay32.lib ssleay32.lib # RSAglue.lib was formerly needed in the SSLLIBS CFGSET = FALSE @@ -84,7 +83,6 @@ TARGET =$(LIB_NAME).lib DIROBJ =.\$(CFG) LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)/out32" LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(TARGET) -LINKLIBS = $(LINKLIBS) CC = $(CCNODBG) $(CFLAGSSSL) CFGSET = TRUE !ENDIF @@ -97,7 +95,6 @@ TARGET =$(LIB_NAME).dll DIROBJ =.\$(CFG) LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)/out32dll" LNK = $(LNKDLL) $(LFLAGSSSL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME).lib" -LINKLIBS = $(LINKLIBS) $(SSLLIBS) CC = $(CCNODBG) $(CFLAGSSSL) CFGSET = TRUE RESOURCE = $(DIROBJ)\libcurl.res @@ -110,7 +107,6 @@ TARGET =$(LIB_NAME).lib DIROBJ =.\$(CFG) LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)/out32dll" LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(TARGET) -LINKLIBS = $(LINKLIBS) $(SSLLIBS) CC = $(CCNODBG) $(CFLAGSSSL) CFGSET = TRUE RESOURCE = $(DIROBJ)\libcurl.res @@ -147,7 +143,6 @@ RESOURCE = $(DIROBJ)\libcurl.res TARGET = $(LIB_NAME_DEBUG).lib DIROBJ =.\$(CFG) LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(TARGET) -LINKLIBS = $(LINKLIBS) CC = $(CCDEBUG) $(CFLAGSSSL) CFGSET = TRUE !ENDIF @@ -160,7 +155,6 @@ TARGET =$(LIB_NAME_DEBUG).dll DIROBJ =.\$(CFG) LFLAGSSSL = /LIBPATH:$(OPENSSL_PATH)/out32dll LNK = $(LNKDLL) $(LFLAGSSSL) /DEBUG /out:$(TARGET) /IMPLIB:"$(LIB_NAME_DEBUG).lib" /PDB:"$(LIB_NAME_DEBUG).pdb" -LINKLIBS = $(LINKLIBS) $(SSLLIBS) CC = $(CCDEBUG) $(CFLAGSSSL) CFGSET = TRUE RESOURCE = $(DIROBJ)\libcurl.res @@ -234,7 +228,7 @@ all : $(TARGET) $(TARGET): $(X_OBJS) - $(LNK) $(LFLAGS) $(LINKLIBS) $(X_OBJS) + $(LNK) $(LFLAGS) $(X_OBJS) $(X_OBJS): $(DIROBJ) diff --git a/lib/easy.c b/lib/easy.c index 5ecd10575..4c4e271f6 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -98,7 +98,12 @@ static CURLcode win32_init(void) WORD wVersionRequested; WSADATA wsaData; int err; - wVersionRequested = MAKEWORD(2, 0); + +#ifdef ENABLE_IPV6 + wVersionRequested = MAKEWORD(2, 0); +#else + wVersionRequested = MAKEWORD(1, 1); +#endif err = WSAStartup(wVersionRequested, &wsaData); @@ -107,14 +112,14 @@ static CURLcode win32_init(void) /* winsock.dll. */ return CURLE_FAILED_INIT; - /* Confirm that the Windows Sockets DLL supports 2.0.*/ + /* Confirm that the Windows Sockets DLL supports what we need.*/ /* Note that if the DLL supports versions greater */ - /* than 2.0 in addition to 2.0, it will still return */ - /* 2.0 in wVersion since that is the version we */ - /* requested. */ - - if ( LOBYTE( wsaData.wVersion ) != 2 || - HIBYTE( wsaData.wVersion ) != 0 ) { + /* than wVersionRequested, it will still return */ + /* wVersionRequested in wVersion. wHighVersion contains the */ + /* highest supported version. */ + + if ( LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) || + HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) { /* Tell the user that we couldn't find a useable */ /* winsock.dll. */ diff --git a/lib/strtoofft.h b/lib/strtoofft.h index 9944ba1d9..27c3668e3 100644 --- a/lib/strtoofft.h +++ b/lib/strtoofft.h @@ -45,7 +45,7 @@ /* For MSVC7 we can use _strtoi64() which seems to be a strtoll() clone */ #if defined(_MSC_VER) && (_MSC_VER >= 1300) -#define strtoll _strtoi64 +#define strtoofft _strtoi64 #else /* MSVC7 or later */ curl_off_t curlx_strtoll(const char *nptr, char **endptr, int base); #define strtoofft curlx_strtoll diff --git a/lib/telnet.c b/lib/telnet.c index 2faffb225..c925ad52e 100644 --- a/lib/telnet.c +++ b/lib/telnet.c @@ -101,6 +101,11 @@ #define CURL_SB_EOF(x) (x->subpointer >= x->subend) #define CURL_SB_LEN(x) (x->subend - x->subpointer) +#ifdef WIN32 +typedef FARPROC WSOCK2_FUNC; +static CURLcode check_wsock2 ( struct SessionHandle *data ); +#endif + static void telrcv(struct connectdata *, unsigned char *inbuf, /* Data received from socket */ @@ -164,6 +169,45 @@ struct TELNET { TelnetReceive telrcv_state; }; +#ifdef WIN32 +static CURLcode +check_wsock2 ( struct SessionHandle *data ) +{ + int err; + WORD wVersionRequested; + WSADATA wsaData; + + curlassert(data); + + /* telnet requires at least WinSock 2.0 so ask for it. */ + wVersionRequested = MAKEWORD(2, 0); + + err = WSAStartup(wVersionRequested, &wsaData); + + /* We must've called this once already, so this call */ + /* should always succeed. But, just in case... */ + if (err != 0) { + failf(data,"WSAStartup failed (%d)",err); + return CURLE_FAILED_INIT; + } + + /* We have to have a WSACleanup call for every successful */ + /* WSAStartup call. */ + WSACleanup(); + + /* Check that our version is supported */ + if (LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || + HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested)) { + /* Our version isn't supported */ + failf(data,"insufficient winsock version to support " + "telnet"); + return CURLE_FAILED_INIT; + } + + /* Our version is supported */ + return CURLE_OK; +} +#endif static CURLcode init_telnet(struct connectdata *conn) { @@ -1037,6 +1081,11 @@ CURLcode Curl_telnet(struct connectdata *conn) struct SessionHandle *data = conn->data; int sockfd = conn->sock[FIRSTSOCKET]; #ifdef WIN32 + HMODULE wsock2; + WSOCK2_FUNC close_event_func; + WSOCK2_FUNC create_event_func; + WSOCK2_FUNC event_select_func; + WSOCK2_FUNC enum_netevents_func; WSAEVENT event_handle; WSANETWORKEVENTS events; HANDLE stdin_handle; @@ -1063,13 +1112,70 @@ CURLcode Curl_telnet(struct connectdata *conn) return code; #ifdef WIN32 + /* + ** This functionality only works with WinSock >= 2.0. So, + ** make sure have it. + */ + code = check_wsock2(data); + if (code) + return code; + + /* OK, so we have WinSock 2.0. We need to dynamically */ + /* load ws2_32.dll and get the function pointers we need. */ + wsock2 = LoadLibrary("WS2_32.DLL"); + if (wsock2 == NULL) { + failf(data,"failed to load WS2_32.DLL (%d)",GetLastError()); + return CURLE_FAILED_INIT; + } + + /* Grab a pointer to WSACreateEvent */ + create_event_func = GetProcAddress(wsock2,"WSACreateEvent"); + if (create_event_func == NULL) { + failf(data,"failed to find WSACreateEvent function (%d)", + GetLastError()); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* And WSACloseEvent */ + close_event_func = GetProcAddress(wsock2,"WSACloseEvent"); + if (create_event_func == NULL) { + failf(data,"failed to find WSACloseEvent function (%d)", + GetLastError()); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* And WSAEventSelect */ + event_select_func = GetProcAddress(wsock2,"WSAEventSelect"); + if (event_select_func == NULL) { + failf(data,"failed to find WSAEventSelect function (%d)", + GetLastError()); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* And WSAEnumNetworkEvents */ + enum_netevents_func = GetProcAddress(wsock2,"WSAEnumNetworkEvents"); + if (enum_netevents_func == NULL) { + failf(data,"failed to find WSAEnumNetworkEvents function (%d)", + GetLastError()); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + /* We want to wait for both stdin and the socket. Since ** the select() function in winsock only works on sockets ** we have to use the WaitForMultipleObjects() call. */ /* First, create a sockets event object */ - event_handle = WSACreateEvent(); + event_handle = (WSAEVENT)create_event_func(); + if (event_handle == WSA_INVALID_EVENT) { + failf(data,"WSACreateEvent failed (%d)",WSAGetLastError()); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } /* The get the Windows file handle for stdin */ stdin_handle = GetStdHandle(STD_INPUT_HANDLE); @@ -1079,7 +1185,9 @@ CURLcode Curl_telnet(struct connectdata *conn) objs[1] = event_handle; /* Tell winsock what events we want to listen to */ - if(WSAEventSelect(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR) { + if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR) { + close_event_func(event_handle); + FreeLibrary(wsock2); return 0; } @@ -1113,7 +1221,7 @@ CURLcode Curl_telnet(struct connectdata *conn) break; case 1: - if(WSAEnumNetworkEvents(sockfd, event_handle, &events) + if(enum_netevents_func(sockfd, event_handle, &events) != SOCKET_ERROR) { if(events.lNetworkEvents & FD_READ) { /* This reallu OUGHT to check its return code. */ @@ -1139,6 +1247,21 @@ CURLcode Curl_telnet(struct connectdata *conn) break; } } + + /* We called WSACreateEvent, so call WSACloseEvent */ + if (close_event_func(event_handle) == FALSE) { + infof(data,"WSACloseEvent failed (%d)",WSAGetLastError()); + } + + /* "Forget" pointers into the library we're about to free */ + create_event_func = NULL; + close_event_func = NULL; + event_select_func = NULL; + enum_netevents_func = NULL; + + /* We called LoadLibrary, so call FreeLibrary */ + if (!FreeLibrary(wsock2)) + infof(data,"FreeLibrary(wsock2) failed (%d)",GetLastError()); #else FD_ZERO (&readfd); /* clear it */ FD_SET (sockfd, &readfd); -- cgit v1.2.3