David Byron's work on making libcurl only require winsock 1.1 on Windows
authorDaniel Stenberg <daniel@haxx.se>
Wed, 3 Mar 2004 13:32:56 +0000 (13:32 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 3 Mar 2004 13:32:56 +0000 (13:32 +0000)
machines.

CHANGES
lib/Makefile.vc6
lib/easy.c
lib/strtoofft.h
lib/telnet.c
src/Makefile.vc6
src/main.c

diff --git a/CHANGES b/CHANGES
index e6d08d0..bdc412f 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,9 @@
                                   Changelog
 
 Daniel (3 March 2004)
+- David Byron's work on making libcurl only require winsock 1.1 on Windows
+  machines.
+
 - More variable cleanups based on compiler warnings generated by Tor Arntsen's
   autobuilds with MIPSPro.
 
index d84f17f..e9ddd36 100644 (file)
@@ -48,7 +48,6 @@ CFLAGS = /I "." /I "../include" /nologo /W3 /GX /D "WIN32" /D "VC6" /D "_MBCS" /
 LNKDLL    = link.exe /DLL  /def:libcurl.def\r
 LNKLIB    = link.exe /lib\r
 LFLAGS    = /nologo\r
-LINKLIBS  = ws2_32.lib winmm.lib\r
 SSLLIBS   = libeay32.lib ssleay32.lib\r
 #  RSAglue.lib was formerly needed in the SSLLIBS\r
 CFGSET    = FALSE\r
@@ -84,7 +83,6 @@ TARGET   =$(LIB_NAME).lib
 DIROBJ   =.\$(CFG)\r
 LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)/out32"\r
 LNK      = $(LNKLIB) $(LFLAGSSSL) /out:$(TARGET)\r
-LINKLIBS = $(LINKLIBS)\r
 CC       = $(CCNODBG) $(CFLAGSSSL)\r
 CFGSET   = TRUE\r
 !ENDIF\r
@@ -97,7 +95,6 @@ TARGET   =$(LIB_NAME).dll
 DIROBJ   =.\$(CFG)\r
 LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)/out32dll"\r
 LNK      = $(LNKDLL) $(LFLAGSSSL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME).lib"\r
-LINKLIBS = $(LINKLIBS) $(SSLLIBS)\r
 CC       = $(CCNODBG)  $(CFLAGSSSL)\r
 CFGSET   = TRUE\r
 RESOURCE = $(DIROBJ)\libcurl.res\r
@@ -110,7 +107,6 @@ TARGET   =$(LIB_NAME).lib
 DIROBJ   =.\$(CFG)\r
 LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)/out32dll"\r
 LNK      = $(LNKLIB) $(LFLAGSSSL) /out:$(TARGET)\r
-LINKLIBS = $(LINKLIBS) $(SSLLIBS)\r
 CC       = $(CCNODBG)  $(CFLAGSSSL)\r
 CFGSET   = TRUE\r
 RESOURCE = $(DIROBJ)\libcurl.res\r
@@ -147,7 +143,6 @@ RESOURCE = $(DIROBJ)\libcurl.res
 TARGET   = $(LIB_NAME_DEBUG).lib\r
 DIROBJ   =.\$(CFG)\r
 LNK      = $(LNKLIB) $(LFLAGSSSL) /out:$(TARGET)\r
-LINKLIBS = $(LINKLIBS)\r
 CC       = $(CCDEBUG) $(CFLAGSSSL)\r
 CFGSET   = TRUE\r
 !ENDIF\r
@@ -160,7 +155,6 @@ TARGET   =$(LIB_NAME_DEBUG).dll
 DIROBJ   =.\$(CFG)\r
 LFLAGSSSL = /LIBPATH:$(OPENSSL_PATH)/out32dll\r
 LNK      = $(LNKDLL) $(LFLAGSSSL) /DEBUG /out:$(TARGET) /IMPLIB:"$(LIB_NAME_DEBUG).lib" /PDB:"$(LIB_NAME_DEBUG).pdb"\r
-LINKLIBS = $(LINKLIBS) $(SSLLIBS)\r
 CC       = $(CCDEBUG) $(CFLAGSSSL)\r
 CFGSET   = TRUE\r
 RESOURCE = $(DIROBJ)\libcurl.res\r
@@ -234,7 +228,7 @@ all : $(TARGET)
 \r
 \r
 $(TARGET): $(X_OBJS)\r
-       $(LNK) $(LFLAGS) $(LINKLIBS) $(X_OBJS)\r
+       $(LNK) $(LFLAGS) $(X_OBJS)\r
 \r
 $(X_OBJS): $(DIROBJ)\r
 \r
index 5ecd105..4c4e271 100644 (file)
@@ -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. */ 
index 9944ba1..27c3668 100644 (file)
@@ -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
index 2faffb2..c925ad5 100644 (file)
 #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);
index 392df67..d0bf915 100644 (file)
@@ -30,8 +30,8 @@ ZLIB_PATH  = ../../zlib-1.1.4
 \r
 CFLAGS = /I "../lib" /I "../include" /I "$(ZLIB_PATH)" /nologo /W3 /GX /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
 LFLAGS = /nologo /libpath:"$(ZLIB_PATH)" /out:$(PROGRAM_NAME) /subsystem:console /machine:I386\r
-LINKLIBS = ws2_32.lib libcurl.lib winmm.lib zlib.lib\r
-LINKLIBS_DEBUG = ws2_32.lib libcurld.lib winmm.lib zlib.lib\r
+LINKLIBS = wsock32.lib libcurl.lib winmm.lib zlib.lib\r
+LINKLIBS_DEBUG = wsock32.lib libcurld.lib winmm.lib zlib.lib\r
 \r
 RELEASE_OBJS= \\r
        hugehelpr.obj \\r
@@ -58,6 +58,7 @@ OPENSSL_PATH   = ../../openssl-0.9.7a
 !ENDIF\r
 LFLAGSSSL = /LIBPATH:"$(OPENSSL_PATH)/out32"\r
 SSLLIBS   = libeay32.lib ssleay32.lib gdi32.lib \r
+CFLAGS = $(CFLAGS) -DUSE_SSLEAY\r
 LINKLIBS  = $(LINKLIBS) $(SSLLIBS)\r
 LINKLIBS_DEBUG  = $(LINKLIBS_DEBUG) $(SSLLIBS)\r
 LFLAGS = $(LFLAGS) $(LFLAGSSSL)\r
@@ -100,12 +101,13 @@ maind.obj: main.c
        $(CCD) $(CFLAGS) /Fo"$@" main.c\r
 \r
 clean:\r
-       -@erase homedir.obj\r
-       -@erase hugehelp.obj\r
-       -@erase main.obj\r
+       -@erase $(RELEASE_OBJS)\r
+       -@erase $(DEBUG_OBJS)\r
        -@erase vc60.idb\r
        -@erase vc60.pdb\r
        -@erase vc60.pch\r
+       -@erase vc70.idb\r
+       -@erase vc70.pch\r
        -@erase curl.ilk\r
        -@erase curl.pdb\r
 \r
index 2872fc7..414db7d 100644 (file)
@@ -2647,8 +2647,11 @@ operate(struct Configurable *config, int argc, char *argv[])
 
   errorbuffer[0]=0; /* prevent junk from being output */
 
-  main_init(); /* inits */
-
+  /* inits */
+  if (main_init() != CURLE_OK) {
+    helpf("error initializing curl library\n");
+    return CURLE_FAILED_INIT;
+  }
   config->showerror=TRUE;
   config->conf=CONF_DEFAULT;
   config->use_httpget=FALSE;