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.

drh 2017-12-31 19:24 UTC trunk
Commit 76c7a9a782a4d047d7b05a332ce8dbe1f29a445262dcdfa54c90e68581a0721b
1 file changed +51 -15
+51 -15
--- src/winhttp.c
+++ src/winhttp.c
@@ -20,10 +20,12 @@
2020
** server to be run without any user logged on.
2121
*/
2222
#include "config.h"
2323
#ifdef _WIN32
2424
/* This code is for win32 only */
25
+#include <ws2tcpip.h>
26
+#include <mstcpip.h>
2527
#include <windows.h>
2628
#include <process.h>
2729
#include "winhttp.h"
2830
2931
/*
@@ -46,11 +48,11 @@
4648
*/
4749
typedef struct HttpRequest HttpRequest;
4850
struct HttpRequest {
4951
int id; /* ID counter */
5052
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 */
5254
int flags; /* Flags passed to win32_http_server() */
5355
const char *zOptions; /* --baseurl, --notfound, --localauth, --th-trace */
5456
};
5557
5658
/*
@@ -135,10 +137,12 @@
135137
HttpRequest *p = (HttpRequest*)pAppData;
136138
FILE *in = 0, *out = 0, *aux = 0;
137139
int amt, got, i;
138140
int wanted = 0;
139141
char *z;
142
+ char zIp[50];
143
+ DWORD nIp = sizeof(zIp);
140144
char zCmdFName[MAX_PATH];
141145
char zRequestFName[MAX_PATH];
142146
char zReplyFName[MAX_PATH];
143147
char zCmd[2000]; /* Command-line to process the request */
144148
char zHdr[4000]; /* The HTTP request header */
@@ -183,19 +187,22 @@
183187
/*
184188
** The repository name is only needed if there was no open checkout. This
185189
** is designed to allow the open checkout for the interactive user to work
186190
** with the local Fossil server started via the "ui" command.
187191
*/
192
+ if( WSAAddressToStringA((SOCKADDR*)&p->addr, sizeof(p->addr),
193
+ NULL, zIp, &nIp)!=0 ){
194
+ zIp[0] = 0;
195
+ }
188196
if( (p->flags & HTTP_SERVER_HAD_CHECKOUT)==0 ){
189197
assert( g.zRepositoryName && g.zRepositoryName[0] );
190198
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
193200
);
194201
}else{
195202
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
197204
);
198205
}
199206
aux = fossil_fopen(zCmdFName, "wb");
200207
if( aux==0 ) goto end_request;
201208
fwrite(zCmd, 1, strlen(zCmd), aux);
@@ -235,10 +242,12 @@
235242
static void win32_scgi_request(void *pAppData){
236243
HttpRequest *p = (HttpRequest*)pAppData;
237244
FILE *in = 0, *out = 0;
238245
int amt, got, nHdr, i;
239246
int wanted = 0;
247
+ char zIp[50];
248
+ DWORD nIp = sizeof(zIp);
240249
char zRequestFName[MAX_PATH];
241250
char zReplyFName[MAX_PATH];
242251
char zCmd[2000]; /* Command-line to process the request */
243252
char zHdr[4000]; /* The SCGI request header */
244253
@@ -265,13 +274,17 @@
265274
if( got<=0 ) break;
266275
fwrite(zHdr, 1, got, out);
267276
wanted += got;
268277
}
269278
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
+ }
270283
sqlite3_snprintf(sizeof(zCmd), zCmd,
271284
"\"%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,
273286
g.zRepositoryName, p->zOptions
274287
);
275288
in = fossil_fopen(zReplyFName, "w+b");
276289
fflush(out);
277290
fossil_system(zCmd);
@@ -311,11 +324,11 @@
311324
int flags /* One or more HTTP_SERVER_ flags */
312325
){
313326
HANDLE hStoppedEvent;
314327
WSADATA wd;
315328
SOCKET s = INVALID_SOCKET;
316
- SOCKADDR_IN addr;
329
+ SOCKADDR_IN6 addr;
317330
int idCnt = 0;
318331
int iPort = mnPort;
319332
Blob options;
320333
wchar_t zTmpPath[MAX_PATH];
321334
const char *zSkin;
@@ -357,25 +370,48 @@
357370
#endif
358371
if( WSAStartup(MAKEWORD(1,1), &wd) ){
359372
fossil_fatal("unable to initialize winsock");
360373
}
361374
while( iPort<=mxPort ){
362
- s = socket(AF_INET, SOCK_STREAM, 0);
375
+ DWORD ipv6only = 0;
376
+ s = socket(AF_INET6, SOCK_STREAM, 0);
363377
if( s==INVALID_SOCKET ){
364378
fossil_fatal("unable to create a socket");
365379
}
366
- addr.sin_family = AF_INET;
367
- addr.sin_port = htons(iPort);
380
+ setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only,
381
+ sizeof(ipv6only));
368382
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);
372402
}
373403
}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));
375408
}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));
377413
}
378414
if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){
379415
closesocket(s);
380416
iPort++;
381417
continue;
@@ -430,11 +466,11 @@
430466
/* Set the service status to running and pass the listener socket to the
431467
** service handling procedures. */
432468
win32_http_service_running(s);
433469
for(;;){
434470
SOCKET client;
435
- SOCKADDR_IN client_addr;
471
+ SOCKADDR_IN6 client_addr;
436472
HttpRequest *pRequest;
437473
int len = sizeof(client_addr);
438474
int wsaError;
439475
440476
client = accept(s, (struct sockaddr*)&client_addr, &len);
441477
--- 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

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button