Fossil SCM
Get "fossil server" working for IPv6 on MinGW, using hints from Olivier Mascia.
Commit
1627571be979436336fc7a0b5d088c60f8ed80e2fdefe8e99d604b7191c9c0d2
Parent
80b3b12715275e5…
1 file changed
+23
-27
+23
-27
| --- src/winhttp.c | ||
| +++ src/winhttp.c | ||
| @@ -21,14 +21,17 @@ | ||
| 21 | 21 | */ |
| 22 | 22 | #include "config.h" |
| 23 | 23 | #ifdef _WIN32 |
| 24 | 24 | /* This code is for win32 only */ |
| 25 | 25 | #include <ws2tcpip.h> |
| 26 | -#include <mstcpip.h> | |
| 27 | 26 | #include <windows.h> |
| 28 | 27 | #include <process.h> |
| 29 | 28 | #include "winhttp.h" |
| 29 | + | |
| 30 | +#ifndef IPV6_V6ONLY | |
| 31 | +# define IPV6_V6ONLY 27 /* Because this definition is missing in MinGW */ | |
| 32 | +#endif | |
| 30 | 33 | |
| 31 | 34 | /* |
| 32 | 35 | ** The HttpServer structure holds information about an instance of |
| 33 | 36 | ** the HTTP server itself. |
| 34 | 37 | */ |
| @@ -325,10 +328,11 @@ | ||
| 325 | 328 | ){ |
| 326 | 329 | HANDLE hStoppedEvent; |
| 327 | 330 | WSADATA wd; |
| 328 | 331 | SOCKET s = INVALID_SOCKET; |
| 329 | 332 | SOCKADDR_IN6 addr; |
| 333 | + int addrlen; | |
| 330 | 334 | int idCnt = 0; |
| 331 | 335 | int iPort = mnPort; |
| 332 | 336 | Blob options; |
| 333 | 337 | wchar_t zTmpPath[MAX_PATH]; |
| 334 | 338 | const char *zSkin; |
| @@ -366,49 +370,41 @@ | ||
| 366 | 370 | if( zSavedKey!=0 && savedKeySize>0 ){ |
| 367 | 371 | blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(), |
| 368 | 372 | zSavedKey, savedKeySize); |
| 369 | 373 | } |
| 370 | 374 | #endif |
| 371 | - if( WSAStartup(MAKEWORD(1,1), &wd) ){ | |
| 375 | + if( WSAStartup(MAKEWORD(2,0), &wd) ){ | |
| 372 | 376 | fossil_fatal("unable to initialize winsock"); |
| 377 | + } | |
| 378 | + if( flags & HTTP_SERVER_LOCALHOST ){ | |
| 379 | + zIpAddr = "127.0.0.1"; | |
| 373 | 380 | } |
| 374 | 381 | while( iPort<=mxPort ){ |
| 375 | 382 | DWORD ipv6only = 0; |
| 376 | 383 | s = socket(AF_INET6, SOCK_STREAM, 0); |
| 377 | 384 | if( s==INVALID_SOCKET ){ |
| 378 | 385 | fossil_fatal("unable to create a socket"); |
| 379 | 386 | } |
| 380 | 387 | setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, |
| 381 | 388 | sizeof(ipv6only)); |
| 389 | + memset(&addr, 0, sizeof(addr)); | |
| 390 | + addrlen = sizeof(addr); | |
| 382 | 391 | if( zIpAddr ){ |
| 383 | - int addrlen = sizeof(addr); | |
| 384 | - memset(&addr, 0, sizeof(addr)); | |
| 392 | + char* zIp; | |
| 393 | + if( strstr(zIpAddr, ".") ){ | |
| 394 | + zIp = mprintf("::ffff:%s", zIpAddr); | |
| 395 | + }else{ | |
| 396 | + zIp = mprintf("%s", zIpAddr); | |
| 397 | + } | |
| 385 | 398 | addr.sin6_family = AF_INET6; |
| 386 | - if (WSAStringToAddress((LPSTR)zIpAddr, AF_INET6, NULL, | |
| 399 | + if (WSAStringToAddress(zIp, AF_INET6, NULL, | |
| 387 | 400 | (struct sockaddr *)&addr, &addrlen) != 0){ |
| 388 | - SOCKADDR_IN addrv4; | |
| 389 | - SCOPE_ID scope; | |
| 390 | - int addrlen = sizeof(addrv4); | |
| 391 | - memset(&addrv4, 0, sizeof(addrv4)); | |
| 392 | - addrv4.sin_family = AF_INET; | |
| 393 | - if (WSAStringToAddress((LPSTR)zIpAddr, AF_INET, NULL, | |
| 394 | - (struct sockaddr *)&addrv4, &addrlen) != 0){ | |
| 395 | - fossil_fatal("not a valid IP address: %s", zIpAddr); | |
| 396 | - } | |
| 397 | - memset(&addr, 0, sizeof(addr)); | |
| 398 | - memset(&scope, 0, sizeof(scope)); | |
| 399 | - IN6ADDR_SETV4MAPPED(&addr, &addrv4.sin_addr, scope, htons(iPort)); | |
| 400 | - }else{ | |
| 401 | - ((SOCKADDR_IN6*)&addr)->sin6_port = htons(iPort); | |
| 402 | - } | |
| 403 | - }else if( flags & HTTP_SERVER_LOCALHOST ){ | |
| 404 | - SCOPE_ID scope; | |
| 405 | - memset(&addr, 0, sizeof(addr)); | |
| 406 | - memset(&scope, 0, sizeof(scope)); | |
| 407 | - IN6ADDR_SETV4MAPPED(&addr, &in4addr_loopback, scope, htons(iPort)); | |
| 408 | - }else{ | |
| 409 | - memset(&addr, 0, sizeof(addr)); | |
| 401 | + fossil_fatal("not a valid IP address: %s", zIpAddr); | |
| 402 | + } | |
| 403 | + ((SOCKADDR_IN6*)&addr)->sin6_port = htons(iPort); | |
| 404 | + fossil_free(zIp); | |
| 405 | + }else{ | |
| 410 | 406 | addr.sin6_family = AF_INET6; |
| 411 | 407 | addr.sin6_port = htons(iPort); |
| 412 | 408 | memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any)); |
| 413 | 409 | } |
| 414 | 410 | if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){ |
| 415 | 411 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -21,14 +21,17 @@ | |
| 21 | */ |
| 22 | #include "config.h" |
| 23 | #ifdef _WIN32 |
| 24 | /* This code is for win32 only */ |
| 25 | #include <ws2tcpip.h> |
| 26 | #include <mstcpip.h> |
| 27 | #include <windows.h> |
| 28 | #include <process.h> |
| 29 | #include "winhttp.h" |
| 30 | |
| 31 | /* |
| 32 | ** The HttpServer structure holds information about an instance of |
| 33 | ** the HTTP server itself. |
| 34 | */ |
| @@ -325,10 +328,11 @@ | |
| 325 | ){ |
| 326 | HANDLE hStoppedEvent; |
| 327 | WSADATA wd; |
| 328 | SOCKET s = INVALID_SOCKET; |
| 329 | SOCKADDR_IN6 addr; |
| 330 | int idCnt = 0; |
| 331 | int iPort = mnPort; |
| 332 | Blob options; |
| 333 | wchar_t zTmpPath[MAX_PATH]; |
| 334 | const char *zSkin; |
| @@ -366,49 +370,41 @@ | |
| 366 | if( zSavedKey!=0 && savedKeySize>0 ){ |
| 367 | blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(), |
| 368 | zSavedKey, savedKeySize); |
| 369 | } |
| 370 | #endif |
| 371 | if( WSAStartup(MAKEWORD(1,1), &wd) ){ |
| 372 | fossil_fatal("unable to initialize winsock"); |
| 373 | } |
| 374 | while( iPort<=mxPort ){ |
| 375 | DWORD ipv6only = 0; |
| 376 | s = socket(AF_INET6, SOCK_STREAM, 0); |
| 377 | if( s==INVALID_SOCKET ){ |
| 378 | fossil_fatal("unable to create a socket"); |
| 379 | } |
| 380 | setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, |
| 381 | sizeof(ipv6only)); |
| 382 | if( zIpAddr ){ |
| 383 | int addrlen = sizeof(addr); |
| 384 | memset(&addr, 0, sizeof(addr)); |
| 385 | addr.sin6_family = AF_INET6; |
| 386 | if (WSAStringToAddress((LPSTR)zIpAddr, AF_INET6, NULL, |
| 387 | (struct sockaddr *)&addr, &addrlen) != 0){ |
| 388 | SOCKADDR_IN addrv4; |
| 389 | SCOPE_ID scope; |
| 390 | int addrlen = sizeof(addrv4); |
| 391 | memset(&addrv4, 0, sizeof(addrv4)); |
| 392 | addrv4.sin_family = AF_INET; |
| 393 | if (WSAStringToAddress((LPSTR)zIpAddr, AF_INET, NULL, |
| 394 | (struct sockaddr *)&addrv4, &addrlen) != 0){ |
| 395 | fossil_fatal("not a valid IP address: %s", zIpAddr); |
| 396 | } |
| 397 | memset(&addr, 0, sizeof(addr)); |
| 398 | memset(&scope, 0, sizeof(scope)); |
| 399 | IN6ADDR_SETV4MAPPED(&addr, &addrv4.sin_addr, scope, htons(iPort)); |
| 400 | }else{ |
| 401 | ((SOCKADDR_IN6*)&addr)->sin6_port = htons(iPort); |
| 402 | } |
| 403 | }else if( flags & HTTP_SERVER_LOCALHOST ){ |
| 404 | SCOPE_ID scope; |
| 405 | memset(&addr, 0, sizeof(addr)); |
| 406 | memset(&scope, 0, sizeof(scope)); |
| 407 | IN6ADDR_SETV4MAPPED(&addr, &in4addr_loopback, scope, htons(iPort)); |
| 408 | }else{ |
| 409 | memset(&addr, 0, sizeof(addr)); |
| 410 | addr.sin6_family = AF_INET6; |
| 411 | addr.sin6_port = htons(iPort); |
| 412 | memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any)); |
| 413 | } |
| 414 | if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){ |
| 415 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -21,14 +21,17 @@ | |
| 21 | */ |
| 22 | #include "config.h" |
| 23 | #ifdef _WIN32 |
| 24 | /* This code is for win32 only */ |
| 25 | #include <ws2tcpip.h> |
| 26 | #include <windows.h> |
| 27 | #include <process.h> |
| 28 | #include "winhttp.h" |
| 29 | |
| 30 | #ifndef IPV6_V6ONLY |
| 31 | # define IPV6_V6ONLY 27 /* Because this definition is missing in MinGW */ |
| 32 | #endif |
| 33 | |
| 34 | /* |
| 35 | ** The HttpServer structure holds information about an instance of |
| 36 | ** the HTTP server itself. |
| 37 | */ |
| @@ -325,10 +328,11 @@ | |
| 328 | ){ |
| 329 | HANDLE hStoppedEvent; |
| 330 | WSADATA wd; |
| 331 | SOCKET s = INVALID_SOCKET; |
| 332 | SOCKADDR_IN6 addr; |
| 333 | int addrlen; |
| 334 | int idCnt = 0; |
| 335 | int iPort = mnPort; |
| 336 | Blob options; |
| 337 | wchar_t zTmpPath[MAX_PATH]; |
| 338 | const char *zSkin; |
| @@ -366,49 +370,41 @@ | |
| 370 | if( zSavedKey!=0 && savedKeySize>0 ){ |
| 371 | blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(), |
| 372 | zSavedKey, savedKeySize); |
| 373 | } |
| 374 | #endif |
| 375 | if( WSAStartup(MAKEWORD(2,0), &wd) ){ |
| 376 | fossil_fatal("unable to initialize winsock"); |
| 377 | } |
| 378 | if( flags & HTTP_SERVER_LOCALHOST ){ |
| 379 | zIpAddr = "127.0.0.1"; |
| 380 | } |
| 381 | while( iPort<=mxPort ){ |
| 382 | DWORD ipv6only = 0; |
| 383 | s = socket(AF_INET6, SOCK_STREAM, 0); |
| 384 | if( s==INVALID_SOCKET ){ |
| 385 | fossil_fatal("unable to create a socket"); |
| 386 | } |
| 387 | setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, |
| 388 | sizeof(ipv6only)); |
| 389 | memset(&addr, 0, sizeof(addr)); |
| 390 | addrlen = sizeof(addr); |
| 391 | if( zIpAddr ){ |
| 392 | char* zIp; |
| 393 | if( strstr(zIpAddr, ".") ){ |
| 394 | zIp = mprintf("::ffff:%s", zIpAddr); |
| 395 | }else{ |
| 396 | zIp = mprintf("%s", zIpAddr); |
| 397 | } |
| 398 | addr.sin6_family = AF_INET6; |
| 399 | if (WSAStringToAddress(zIp, AF_INET6, NULL, |
| 400 | (struct sockaddr *)&addr, &addrlen) != 0){ |
| 401 | fossil_fatal("not a valid IP address: %s", zIpAddr); |
| 402 | } |
| 403 | ((SOCKADDR_IN6*)&addr)->sin6_port = htons(iPort); |
| 404 | fossil_free(zIp); |
| 405 | }else{ |
| 406 | addr.sin6_family = AF_INET6; |
| 407 | addr.sin6_port = htons(iPort); |
| 408 | memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any)); |
| 409 | } |
| 410 | if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){ |
| 411 |