Fossil SCM
Changes from Olivier Mascia to implement IPV6 support for "fossil server" on Windows. Currently does not compile on MinGW due to a missing header file.
Commit
76c7a9a782a4d047d7b05a332ce8dbe1f29a445262dcdfa54c90e68581a0721b
Parent
c105c2fd401703d…
1 file changed
+51
-15
+51
-15
| --- src/winhttp.c | ||
| +++ src/winhttp.c | ||
| @@ -20,10 +20,12 @@ | ||
| 20 | 20 | ** server to be run without any user logged on. |
| 21 | 21 | */ |
| 22 | 22 | #include "config.h" |
| 23 | 23 | #ifdef _WIN32 |
| 24 | 24 | /* This code is for win32 only */ |
| 25 | +#include <ws2tcpip.h> | |
| 26 | +#include <mstcpip.h> | |
| 25 | 27 | #include <windows.h> |
| 26 | 28 | #include <process.h> |
| 27 | 29 | #include "winhttp.h" |
| 28 | 30 | |
| 29 | 31 | /* |
| @@ -46,11 +48,11 @@ | ||
| 46 | 48 | */ |
| 47 | 49 | typedef struct HttpRequest HttpRequest; |
| 48 | 50 | struct HttpRequest { |
| 49 | 51 | int id; /* ID counter */ |
| 50 | 52 | SOCKET s; /* Socket on which to receive data */ |
| 51 | - SOCKADDR_IN addr; /* Address from which data is coming */ | |
| 53 | + SOCKADDR_IN6 addr; /* Address from which data is coming */ | |
| 52 | 54 | int flags; /* Flags passed to win32_http_server() */ |
| 53 | 55 | const char *zOptions; /* --baseurl, --notfound, --localauth, --th-trace */ |
| 54 | 56 | }; |
| 55 | 57 | |
| 56 | 58 | /* |
| @@ -135,10 +137,12 @@ | ||
| 135 | 137 | HttpRequest *p = (HttpRequest*)pAppData; |
| 136 | 138 | FILE *in = 0, *out = 0, *aux = 0; |
| 137 | 139 | int amt, got, i; |
| 138 | 140 | int wanted = 0; |
| 139 | 141 | char *z; |
| 142 | + char zIp[50]; | |
| 143 | + DWORD nIp = sizeof(zIp); | |
| 140 | 144 | char zCmdFName[MAX_PATH]; |
| 141 | 145 | char zRequestFName[MAX_PATH]; |
| 142 | 146 | char zReplyFName[MAX_PATH]; |
| 143 | 147 | char zCmd[2000]; /* Command-line to process the request */ |
| 144 | 148 | char zHdr[4000]; /* The HTTP request header */ |
| @@ -183,19 +187,22 @@ | ||
| 183 | 187 | /* |
| 184 | 188 | ** The repository name is only needed if there was no open checkout. This |
| 185 | 189 | ** is designed to allow the open checkout for the interactive user to work |
| 186 | 190 | ** with the local Fossil server started via the "ui" command. |
| 187 | 191 | */ |
| 192 | + if( WSAAddressToStringA((SOCKADDR*)&p->addr, sizeof(p->addr), | |
| 193 | + NULL, zIp, &nIp)!=0 ){ | |
| 194 | + zIp[0] = 0; | |
| 195 | + } | |
| 188 | 196 | if( (p->flags & HTTP_SERVER_HAD_CHECKOUT)==0 ){ |
| 189 | 197 | assert( g.zRepositoryName && g.zRepositoryName[0] ); |
| 190 | 198 | sqlite3_snprintf(sizeof(zCmd), zCmd, "%s%s\n%s\n%s\n%s", |
| 191 | - get_utf8_bom(0), zRequestFName, zReplyFName, inet_ntoa(p->addr.sin_addr), | |
| 192 | - g.zRepositoryName | |
| 199 | + get_utf8_bom(0), zRequestFName, zReplyFName, zIp, g.zRepositoryName | |
| 193 | 200 | ); |
| 194 | 201 | }else{ |
| 195 | 202 | sqlite3_snprintf(sizeof(zCmd), zCmd, "%s%s\n%s\n%s", |
| 196 | - get_utf8_bom(0), zRequestFName, zReplyFName, inet_ntoa(p->addr.sin_addr) | |
| 203 | + get_utf8_bom(0), zRequestFName, zReplyFName, zIp | |
| 197 | 204 | ); |
| 198 | 205 | } |
| 199 | 206 | aux = fossil_fopen(zCmdFName, "wb"); |
| 200 | 207 | if( aux==0 ) goto end_request; |
| 201 | 208 | fwrite(zCmd, 1, strlen(zCmd), aux); |
| @@ -235,10 +242,12 @@ | ||
| 235 | 242 | static void win32_scgi_request(void *pAppData){ |
| 236 | 243 | HttpRequest *p = (HttpRequest*)pAppData; |
| 237 | 244 | FILE *in = 0, *out = 0; |
| 238 | 245 | int amt, got, nHdr, i; |
| 239 | 246 | int wanted = 0; |
| 247 | + char zIp[50]; | |
| 248 | + DWORD nIp = sizeof(zIp); | |
| 240 | 249 | char zRequestFName[MAX_PATH]; |
| 241 | 250 | char zReplyFName[MAX_PATH]; |
| 242 | 251 | char zCmd[2000]; /* Command-line to process the request */ |
| 243 | 252 | char zHdr[4000]; /* The SCGI request header */ |
| 244 | 253 | |
| @@ -265,13 +274,17 @@ | ||
| 265 | 274 | if( got<=0 ) break; |
| 266 | 275 | fwrite(zHdr, 1, got, out); |
| 267 | 276 | wanted += got; |
| 268 | 277 | } |
| 269 | 278 | assert( g.zRepositoryName && g.zRepositoryName[0] ); |
| 279 | + if (WSAAddressToStringA((SOCKADDR*)&p->addr, sizeof(p->addr), | |
| 280 | + NULL, zIp, &nIp)!=0){ | |
| 281 | + zIp[0] = 0; | |
| 282 | + } | |
| 270 | 283 | sqlite3_snprintf(sizeof(zCmd), zCmd, |
| 271 | 284 | "\"%s\" http \"%s\" \"%s\" %s \"%s\" --scgi --nossl%s", |
| 272 | - g.nameOfExe, zRequestFName, zReplyFName, inet_ntoa(p->addr.sin_addr), | |
| 285 | + g.nameOfExe, zRequestFName, zReplyFName, zIp, | |
| 273 | 286 | g.zRepositoryName, p->zOptions |
| 274 | 287 | ); |
| 275 | 288 | in = fossil_fopen(zReplyFName, "w+b"); |
| 276 | 289 | fflush(out); |
| 277 | 290 | fossil_system(zCmd); |
| @@ -311,11 +324,11 @@ | ||
| 311 | 324 | int flags /* One or more HTTP_SERVER_ flags */ |
| 312 | 325 | ){ |
| 313 | 326 | HANDLE hStoppedEvent; |
| 314 | 327 | WSADATA wd; |
| 315 | 328 | SOCKET s = INVALID_SOCKET; |
| 316 | - SOCKADDR_IN addr; | |
| 329 | + SOCKADDR_IN6 addr; | |
| 317 | 330 | int idCnt = 0; |
| 318 | 331 | int iPort = mnPort; |
| 319 | 332 | Blob options; |
| 320 | 333 | wchar_t zTmpPath[MAX_PATH]; |
| 321 | 334 | const char *zSkin; |
| @@ -357,25 +370,48 @@ | ||
| 357 | 370 | #endif |
| 358 | 371 | if( WSAStartup(MAKEWORD(1,1), &wd) ){ |
| 359 | 372 | fossil_fatal("unable to initialize winsock"); |
| 360 | 373 | } |
| 361 | 374 | while( iPort<=mxPort ){ |
| 362 | - s = socket(AF_INET, SOCK_STREAM, 0); | |
| 375 | + DWORD ipv6only = 0; | |
| 376 | + s = socket(AF_INET6, SOCK_STREAM, 0); | |
| 363 | 377 | if( s==INVALID_SOCKET ){ |
| 364 | 378 | fossil_fatal("unable to create a socket"); |
| 365 | 379 | } |
| 366 | - addr.sin_family = AF_INET; | |
| 367 | - addr.sin_port = htons(iPort); | |
| 380 | + setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, | |
| 381 | + sizeof(ipv6only)); | |
| 368 | 382 | if( zIpAddr ){ |
| 369 | - addr.sin_addr.s_addr = inet_addr(zIpAddr); | |
| 370 | - if( addr.sin_addr.s_addr == (-1) ){ | |
| 371 | - fossil_fatal("not a valid IP address: %s", 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 | + memset(&addrv4, 0, sizeof(addrv4)); | |
| 391 | + addrv4.sin_family = AF_INET; | |
| 392 | + int addrlen = sizeof(addrv4); | |
| 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); | |
| 372 | 402 | } |
| 373 | 403 | }else if( flags & HTTP_SERVER_LOCALHOST ){ |
| 374 | - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | |
| 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)); | |
| 375 | 408 | }else{ |
| 376 | - addr.sin_addr.s_addr = htonl(INADDR_ANY); | |
| 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)); | |
| 377 | 413 | } |
| 378 | 414 | if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){ |
| 379 | 415 | closesocket(s); |
| 380 | 416 | iPort++; |
| 381 | 417 | continue; |
| @@ -430,11 +466,11 @@ | ||
| 430 | 466 | /* Set the service status to running and pass the listener socket to the |
| 431 | 467 | ** service handling procedures. */ |
| 432 | 468 | win32_http_service_running(s); |
| 433 | 469 | for(;;){ |
| 434 | 470 | SOCKET client; |
| 435 | - SOCKADDR_IN client_addr; | |
| 471 | + SOCKADDR_IN6 client_addr; | |
| 436 | 472 | HttpRequest *pRequest; |
| 437 | 473 | int len = sizeof(client_addr); |
| 438 | 474 | int wsaError; |
| 439 | 475 | |
| 440 | 476 | client = accept(s, (struct sockaddr*)&client_addr, &len); |
| 441 | 477 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -20,10 +20,12 @@ | |
| 20 | ** server to be run without any user logged on. |
| 21 | */ |
| 22 | #include "config.h" |
| 23 | #ifdef _WIN32 |
| 24 | /* This code is for win32 only */ |
| 25 | #include <windows.h> |
| 26 | #include <process.h> |
| 27 | #include "winhttp.h" |
| 28 | |
| 29 | /* |
| @@ -46,11 +48,11 @@ | |
| 46 | */ |
| 47 | typedef struct HttpRequest HttpRequest; |
| 48 | struct HttpRequest { |
| 49 | int id; /* ID counter */ |
| 50 | SOCKET s; /* Socket on which to receive data */ |
| 51 | SOCKADDR_IN addr; /* Address from which data is coming */ |
| 52 | int flags; /* Flags passed to win32_http_server() */ |
| 53 | const char *zOptions; /* --baseurl, --notfound, --localauth, --th-trace */ |
| 54 | }; |
| 55 | |
| 56 | /* |
| @@ -135,10 +137,12 @@ | |
| 135 | HttpRequest *p = (HttpRequest*)pAppData; |
| 136 | FILE *in = 0, *out = 0, *aux = 0; |
| 137 | int amt, got, i; |
| 138 | int wanted = 0; |
| 139 | char *z; |
| 140 | char zCmdFName[MAX_PATH]; |
| 141 | char zRequestFName[MAX_PATH]; |
| 142 | char zReplyFName[MAX_PATH]; |
| 143 | char zCmd[2000]; /* Command-line to process the request */ |
| 144 | char zHdr[4000]; /* The HTTP request header */ |
| @@ -183,19 +187,22 @@ | |
| 183 | /* |
| 184 | ** The repository name is only needed if there was no open checkout. This |
| 185 | ** is designed to allow the open checkout for the interactive user to work |
| 186 | ** with the local Fossil server started via the "ui" command. |
| 187 | */ |
| 188 | if( (p->flags & HTTP_SERVER_HAD_CHECKOUT)==0 ){ |
| 189 | assert( g.zRepositoryName && g.zRepositoryName[0] ); |
| 190 | sqlite3_snprintf(sizeof(zCmd), zCmd, "%s%s\n%s\n%s\n%s", |
| 191 | get_utf8_bom(0), zRequestFName, zReplyFName, inet_ntoa(p->addr.sin_addr), |
| 192 | g.zRepositoryName |
| 193 | ); |
| 194 | }else{ |
| 195 | sqlite3_snprintf(sizeof(zCmd), zCmd, "%s%s\n%s\n%s", |
| 196 | get_utf8_bom(0), zRequestFName, zReplyFName, inet_ntoa(p->addr.sin_addr) |
| 197 | ); |
| 198 | } |
| 199 | aux = fossil_fopen(zCmdFName, "wb"); |
| 200 | if( aux==0 ) goto end_request; |
| 201 | fwrite(zCmd, 1, strlen(zCmd), aux); |
| @@ -235,10 +242,12 @@ | |
| 235 | static void win32_scgi_request(void *pAppData){ |
| 236 | HttpRequest *p = (HttpRequest*)pAppData; |
| 237 | FILE *in = 0, *out = 0; |
| 238 | int amt, got, nHdr, i; |
| 239 | int wanted = 0; |
| 240 | char zRequestFName[MAX_PATH]; |
| 241 | char zReplyFName[MAX_PATH]; |
| 242 | char zCmd[2000]; /* Command-line to process the request */ |
| 243 | char zHdr[4000]; /* The SCGI request header */ |
| 244 | |
| @@ -265,13 +274,17 @@ | |
| 265 | if( got<=0 ) break; |
| 266 | fwrite(zHdr, 1, got, out); |
| 267 | wanted += got; |
| 268 | } |
| 269 | assert( g.zRepositoryName && g.zRepositoryName[0] ); |
| 270 | sqlite3_snprintf(sizeof(zCmd), zCmd, |
| 271 | "\"%s\" http \"%s\" \"%s\" %s \"%s\" --scgi --nossl%s", |
| 272 | g.nameOfExe, zRequestFName, zReplyFName, inet_ntoa(p->addr.sin_addr), |
| 273 | g.zRepositoryName, p->zOptions |
| 274 | ); |
| 275 | in = fossil_fopen(zReplyFName, "w+b"); |
| 276 | fflush(out); |
| 277 | fossil_system(zCmd); |
| @@ -311,11 +324,11 @@ | |
| 311 | int flags /* One or more HTTP_SERVER_ flags */ |
| 312 | ){ |
| 313 | HANDLE hStoppedEvent; |
| 314 | WSADATA wd; |
| 315 | SOCKET s = INVALID_SOCKET; |
| 316 | SOCKADDR_IN addr; |
| 317 | int idCnt = 0; |
| 318 | int iPort = mnPort; |
| 319 | Blob options; |
| 320 | wchar_t zTmpPath[MAX_PATH]; |
| 321 | const char *zSkin; |
| @@ -357,25 +370,48 @@ | |
| 357 | #endif |
| 358 | if( WSAStartup(MAKEWORD(1,1), &wd) ){ |
| 359 | fossil_fatal("unable to initialize winsock"); |
| 360 | } |
| 361 | while( iPort<=mxPort ){ |
| 362 | s = socket(AF_INET, SOCK_STREAM, 0); |
| 363 | if( s==INVALID_SOCKET ){ |
| 364 | fossil_fatal("unable to create a socket"); |
| 365 | } |
| 366 | addr.sin_family = AF_INET; |
| 367 | addr.sin_port = htons(iPort); |
| 368 | if( zIpAddr ){ |
| 369 | addr.sin_addr.s_addr = inet_addr(zIpAddr); |
| 370 | if( addr.sin_addr.s_addr == (-1) ){ |
| 371 | fossil_fatal("not a valid IP address: %s", zIpAddr); |
| 372 | } |
| 373 | }else if( flags & HTTP_SERVER_LOCALHOST ){ |
| 374 | addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 375 | }else{ |
| 376 | addr.sin_addr.s_addr = htonl(INADDR_ANY); |
| 377 | } |
| 378 | if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){ |
| 379 | closesocket(s); |
| 380 | iPort++; |
| 381 | continue; |
| @@ -430,11 +466,11 @@ | |
| 430 | /* Set the service status to running and pass the listener socket to the |
| 431 | ** service handling procedures. */ |
| 432 | win32_http_service_running(s); |
| 433 | for(;;){ |
| 434 | SOCKET client; |
| 435 | SOCKADDR_IN client_addr; |
| 436 | HttpRequest *pRequest; |
| 437 | int len = sizeof(client_addr); |
| 438 | int wsaError; |
| 439 | |
| 440 | client = accept(s, (struct sockaddr*)&client_addr, &len); |
| 441 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -20,10 +20,12 @@ | |
| 20 | ** server to be run without any user logged on. |
| 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 | /* |
| @@ -46,11 +48,11 @@ | |
| 48 | */ |
| 49 | typedef struct HttpRequest HttpRequest; |
| 50 | struct HttpRequest { |
| 51 | int id; /* ID counter */ |
| 52 | SOCKET s; /* Socket on which to receive data */ |
| 53 | SOCKADDR_IN6 addr; /* Address from which data is coming */ |
| 54 | int flags; /* Flags passed to win32_http_server() */ |
| 55 | const char *zOptions; /* --baseurl, --notfound, --localauth, --th-trace */ |
| 56 | }; |
| 57 | |
| 58 | /* |
| @@ -135,10 +137,12 @@ | |
| 137 | HttpRequest *p = (HttpRequest*)pAppData; |
| 138 | FILE *in = 0, *out = 0, *aux = 0; |
| 139 | int amt, got, i; |
| 140 | int wanted = 0; |
| 141 | char *z; |
| 142 | char zIp[50]; |
| 143 | DWORD nIp = sizeof(zIp); |
| 144 | char zCmdFName[MAX_PATH]; |
| 145 | char zRequestFName[MAX_PATH]; |
| 146 | char zReplyFName[MAX_PATH]; |
| 147 | char zCmd[2000]; /* Command-line to process the request */ |
| 148 | char zHdr[4000]; /* The HTTP request header */ |
| @@ -183,19 +187,22 @@ | |
| 187 | /* |
| 188 | ** The repository name is only needed if there was no open checkout. This |
| 189 | ** is designed to allow the open checkout for the interactive user to work |
| 190 | ** with the local Fossil server started via the "ui" command. |
| 191 | */ |
| 192 | if( WSAAddressToStringA((SOCKADDR*)&p->addr, sizeof(p->addr), |
| 193 | NULL, zIp, &nIp)!=0 ){ |
| 194 | zIp[0] = 0; |
| 195 | } |
| 196 | if( (p->flags & HTTP_SERVER_HAD_CHECKOUT)==0 ){ |
| 197 | assert( g.zRepositoryName && g.zRepositoryName[0] ); |
| 198 | sqlite3_snprintf(sizeof(zCmd), zCmd, "%s%s\n%s\n%s\n%s", |
| 199 | get_utf8_bom(0), zRequestFName, zReplyFName, zIp, g.zRepositoryName |
| 200 | ); |
| 201 | }else{ |
| 202 | sqlite3_snprintf(sizeof(zCmd), zCmd, "%s%s\n%s\n%s", |
| 203 | get_utf8_bom(0), zRequestFName, zReplyFName, zIp |
| 204 | ); |
| 205 | } |
| 206 | aux = fossil_fopen(zCmdFName, "wb"); |
| 207 | if( aux==0 ) goto end_request; |
| 208 | fwrite(zCmd, 1, strlen(zCmd), aux); |
| @@ -235,10 +242,12 @@ | |
| 242 | static void win32_scgi_request(void *pAppData){ |
| 243 | HttpRequest *p = (HttpRequest*)pAppData; |
| 244 | FILE *in = 0, *out = 0; |
| 245 | int amt, got, nHdr, i; |
| 246 | int wanted = 0; |
| 247 | char zIp[50]; |
| 248 | DWORD nIp = sizeof(zIp); |
| 249 | char zRequestFName[MAX_PATH]; |
| 250 | char zReplyFName[MAX_PATH]; |
| 251 | char zCmd[2000]; /* Command-line to process the request */ |
| 252 | char zHdr[4000]; /* The SCGI request header */ |
| 253 | |
| @@ -265,13 +274,17 @@ | |
| 274 | if( got<=0 ) break; |
| 275 | fwrite(zHdr, 1, got, out); |
| 276 | wanted += got; |
| 277 | } |
| 278 | assert( g.zRepositoryName && g.zRepositoryName[0] ); |
| 279 | if (WSAAddressToStringA((SOCKADDR*)&p->addr, sizeof(p->addr), |
| 280 | NULL, zIp, &nIp)!=0){ |
| 281 | zIp[0] = 0; |
| 282 | } |
| 283 | sqlite3_snprintf(sizeof(zCmd), zCmd, |
| 284 | "\"%s\" http \"%s\" \"%s\" %s \"%s\" --scgi --nossl%s", |
| 285 | g.nameOfExe, zRequestFName, zReplyFName, zIp, |
| 286 | g.zRepositoryName, p->zOptions |
| 287 | ); |
| 288 | in = fossil_fopen(zReplyFName, "w+b"); |
| 289 | fflush(out); |
| 290 | fossil_system(zCmd); |
| @@ -311,11 +324,11 @@ | |
| 324 | int flags /* One or more HTTP_SERVER_ flags */ |
| 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; |
| @@ -357,25 +370,48 @@ | |
| 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 | memset(&addrv4, 0, sizeof(addrv4)); |
| 391 | addrv4.sin_family = AF_INET; |
| 392 | int addrlen = sizeof(addrv4); |
| 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 | closesocket(s); |
| 416 | iPort++; |
| 417 | continue; |
| @@ -430,11 +466,11 @@ | |
| 466 | /* Set the service status to running and pass the listener socket to the |
| 467 | ** service handling procedures. */ |
| 468 | win32_http_service_running(s); |
| 469 | for(;;){ |
| 470 | SOCKET client; |
| 471 | SOCKADDR_IN6 client_addr; |
| 472 | HttpRequest *pRequest; |
| 473 | int len = sizeof(client_addr); |
| 474 | int wsaError; |
| 475 | |
| 476 | client = accept(s, (struct sockaddr*)&client_addr, &len); |
| 477 |