Fossil

Check-in [1627571b]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Get "fossil server" working for IPv6 on MinGW, using hints from Olivier Mascia.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | win-server-ipv6
Files: files | file ages | folders
SHA3-256:1627571be979436336fc7a0b5d088c60f8ed80e2fdefe8e99d604b7191c9c0d2
User & Date: drh 2018-01-01 18:48:44
Context
2018-01-01
18:56
The "fossil server" command on windows now listens for both IPv4 and IPv6 connections. check-in: 21d5038f user: drh tags: trunk
18:48
Get "fossil server" working for IPv6 on MinGW, using hints from Olivier Mascia. Closed-Leaf check-in: 1627571b user: drh tags: win-server-ipv6
2017-12-31
20:02
Fix a C89 variable declaration that prevents compiling on older versions of MSVC. check-in: 80b3b127 user: drh tags: win-server-ipv6
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/winhttp.c.

19
20
21
22
23
24
25
26
27
28
29




30
31
32
33
34
35
36
...
323
324
325
326
327
328
329

330
331
332
333
334
335
336
...
364
365
366
367
368
369
370
371
372



373
374
375
376
377
378
379
380
381
382
383
384






385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407

408
409
410
411
412
413
414
415
416
** for windows. It also implements a Windows Service which allows the HTTP
** server to be run without any user logged on.
*/
#include "config.h"
#ifdef _WIN32
/* This code is for win32 only */
#include <ws2tcpip.h>
#include <mstcpip.h>
#include <windows.h>
#include <process.h>
#include "winhttp.h"





/*
** The HttpServer structure holds information about an instance of
** the HTTP server itself.
*/
typedef struct HttpServer HttpServer;
struct HttpServer {
................................................................................
  const char *zIpAddr,      /* Bind to this IP address, if not NULL */
  int flags                 /* One or more HTTP_SERVER_ flags */
){
  HANDLE hStoppedEvent;
  WSADATA wd;
  SOCKET s = INVALID_SOCKET;
  SOCKADDR_IN6 addr;

  int idCnt = 0;
  int iPort = mnPort;
  Blob options;
  wchar_t zTmpPath[MAX_PATH];
  const char *zSkin;
#if USE_SEE
  const char *zSavedKey = 0;
................................................................................
  zSavedKey = db_get_saved_encryption_key();
  savedKeySize = db_get_saved_encryption_key_size();
  if( zSavedKey!=0 && savedKeySize>0 ){
    blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(),
                 zSavedKey, savedKeySize);
  }
#endif
  if( WSAStartup(MAKEWORD(1,1), &wd) ){
    fossil_fatal("unable to initialize winsock");



  }
  while( iPort<=mxPort ){
    DWORD ipv6only = 0;
    s = socket(AF_INET6, SOCK_STREAM, 0);
    if( s==INVALID_SOCKET ){
      fossil_fatal("unable to create a socket");
    }
    setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only,
               sizeof(ipv6only));
    if( zIpAddr ){
      int addrlen = sizeof(addr);
      memset(&addr, 0, sizeof(addr));






      addr.sin6_family = AF_INET6;
      if (WSAStringToAddress((LPSTR)zIpAddr, AF_INET6, NULL,
                             (struct sockaddr *)&addr, &addrlen) != 0){
        SOCKADDR_IN addrv4;
        SCOPE_ID scope;
        int addrlen = sizeof(addrv4);
        memset(&addrv4, 0, sizeof(addrv4));
        addrv4.sin_family = AF_INET;
        if (WSAStringToAddress((LPSTR)zIpAddr, AF_INET, NULL,
                               (struct sockaddr *)&addrv4, &addrlen) != 0){
          fossil_fatal("not a valid IP address: %s", zIpAddr);
        }
        memset(&addr, 0, sizeof(addr));
        memset(&scope, 0, sizeof(scope));
        IN6ADDR_SETV4MAPPED(&addr, &addrv4.sin_addr, scope, htons(iPort));
      }else{
        ((SOCKADDR_IN6*)&addr)->sin6_port = htons(iPort);
      }
    }else if( flags & HTTP_SERVER_LOCALHOST ){
      SCOPE_ID scope;
      memset(&addr, 0, sizeof(addr));
      memset(&scope, 0, sizeof(scope));
      IN6ADDR_SETV4MAPPED(&addr, &in4addr_loopback, scope, htons(iPort));

    }else{
      memset(&addr, 0, sizeof(addr));
      addr.sin6_family = AF_INET6;
      addr.sin6_port = htons(iPort);
      memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
    }
    if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){
      closesocket(s);
      iPort++;







<



>
>
>
>







 







>







 







|

>
>
>









|
|
|
>
>
>
>
>
>

|

<
<
<
<
<
<
<
|
|
<
<
<
<
|
<
<
<
<
<
<
>

<







19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35
36
37
38
39
...
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
...
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400







401
402




403






404
405

406
407
408
409
410
411
412
** for windows. It also implements a Windows Service which allows the HTTP
** server to be run without any user logged on.
*/
#include "config.h"
#ifdef _WIN32
/* This code is for win32 only */
#include <ws2tcpip.h>

#include <windows.h>
#include <process.h>
#include "winhttp.h"

#ifndef IPV6_V6ONLY
# define IPV6_V6ONLY 27  /* Because this definition is missing in MinGW */
#endif

/*
** The HttpServer structure holds information about an instance of
** the HTTP server itself.
*/
typedef struct HttpServer HttpServer;
struct HttpServer {
................................................................................
  const char *zIpAddr,      /* Bind to this IP address, if not NULL */
  int flags                 /* One or more HTTP_SERVER_ flags */
){
  HANDLE hStoppedEvent;
  WSADATA wd;
  SOCKET s = INVALID_SOCKET;
  SOCKADDR_IN6 addr;
  int addrlen;
  int idCnt = 0;
  int iPort = mnPort;
  Blob options;
  wchar_t zTmpPath[MAX_PATH];
  const char *zSkin;
#if USE_SEE
  const char *zSavedKey = 0;
................................................................................
  zSavedKey = db_get_saved_encryption_key();
  savedKeySize = db_get_saved_encryption_key_size();
  if( zSavedKey!=0 && savedKeySize>0 ){
    blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(),
                 zSavedKey, savedKeySize);
  }
#endif
  if( WSAStartup(MAKEWORD(2,0), &wd) ){
    fossil_fatal("unable to initialize winsock");
  }
  if( flags & HTTP_SERVER_LOCALHOST ){
    zIpAddr = "127.0.0.1";
  }
  while( iPort<=mxPort ){
    DWORD ipv6only = 0;
    s = socket(AF_INET6, SOCK_STREAM, 0);
    if( s==INVALID_SOCKET ){
      fossil_fatal("unable to create a socket");
    }
    setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only,
               sizeof(ipv6only));
    memset(&addr, 0, sizeof(addr));
    addrlen = sizeof(addr);
    if( zIpAddr ){
      char* zIp;
      if( strstr(zIpAddr, ".") ){
        zIp = mprintf("::ffff:%s", zIpAddr);
      }else{
        zIp = mprintf("%s", zIpAddr);
      }
      addr.sin6_family = AF_INET6;
      if (WSAStringToAddress(zIp, AF_INET6, NULL,
                             (struct sockaddr *)&addr, &addrlen) != 0){







        fossil_fatal("not a valid IP address: %s", zIpAddr);
      }




      ((SOCKADDR_IN6*)&addr)->sin6_port = htons(iPort);






      fossil_free(zIp);
    }else{

      addr.sin6_family = AF_INET6;
      addr.sin6_port = htons(iPort);
      memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
    }
    if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){
      closesocket(s);
      iPort++;