Fossil SCM

Implement an idle-timeout for windows.

drh 2020-04-09 17:18 idle-timeout
Commit aee7401958cf16b2707252ba67c5e496744532573e35f727e2876e50cba94bb7
2 files changed +3 -1 +22 -10
+3 -1
--- src/main.c
+++ src/main.c
@@ -2636,11 +2636,13 @@
26362636
** Options:
26372637
** --baseurl URL Use URL as the base (useful for reverse proxies)
26382638
** --create Create a new REPOSITORY if it does not already exist
26392639
** --extroot DIR Document root for the /ext extension mechanism
26402640
** --files GLOBLIST Comma-separated list of glob patterns for static files
2641
-** --idle-timeout N Exit if no HTTP requests received for N seconds
2641
+** --idle-timeout N Exit if no HTTP requests are received for N seconds.
2642
+** "0" means never. 0 is default for the "server"
2643
+** command and "60" is the default for the "ui" command.
26422644
** --localauth enable automatic login for requests from localhost
26432645
** --localhost listen on 127.0.0.1 only (always true for "ui")
26442646
** --https Indicates that the input is coming through a reverse
26452647
** proxy that has already translated HTTPS into HTTP.
26462648
** --max-latency N Do not let any single HTTP request run for more than N
26472649
--- src/main.c
+++ src/main.c
@@ -2636,11 +2636,13 @@
2636 ** Options:
2637 ** --baseurl URL Use URL as the base (useful for reverse proxies)
2638 ** --create Create a new REPOSITORY if it does not already exist
2639 ** --extroot DIR Document root for the /ext extension mechanism
2640 ** --files GLOBLIST Comma-separated list of glob patterns for static files
2641 ** --idle-timeout N Exit if no HTTP requests received for N seconds
 
 
2642 ** --localauth enable automatic login for requests from localhost
2643 ** --localhost listen on 127.0.0.1 only (always true for "ui")
2644 ** --https Indicates that the input is coming through a reverse
2645 ** proxy that has already translated HTTPS into HTTP.
2646 ** --max-latency N Do not let any single HTTP request run for more than N
2647
--- src/main.c
+++ src/main.c
@@ -2636,11 +2636,13 @@
2636 ** Options:
2637 ** --baseurl URL Use URL as the base (useful for reverse proxies)
2638 ** --create Create a new REPOSITORY if it does not already exist
2639 ** --extroot DIR Document root for the /ext extension mechanism
2640 ** --files GLOBLIST Comma-separated list of glob patterns for static files
2641 ** --idle-timeout N Exit if no HTTP requests are received for N seconds.
2642 ** "0" means never. 0 is default for the "server"
2643 ** command and "60" is the default for the "ui" command.
2644 ** --localauth enable automatic login for requests from localhost
2645 ** --localhost listen on 127.0.0.1 only (always true for "ui")
2646 ** --https Indicates that the input is coming through a reverse
2647 ** proxy that has already translated HTTPS into HTTP.
2648 ** --max-latency N Do not let any single HTTP request run for more than N
2649
+22 -10
--- src/winhttp.c
+++ src/winhttp.c
@@ -199,16 +199,18 @@
199199
}
200200
return 1;
201201
};
202202
203203
/*
204
-** Accepts connections on DualSocket.
204
+** Accepts connections on DualSocket. Return
205205
*/
206
-static void DualSocket_accept(DualSocket* pListen, DualSocket* pClient,
206
+static int DualSocket_accept(DualSocket* pListen, DualSocket* pClient,
207207
DualAddr* pClientAddr){
208208
fd_set rs;
209209
int rs_count = 0;
210
+ int rc = 0;
211
+ struct timeval delay;
210212
assert( pListen!=NULL && pClient!=NULL && pClientAddr!= NULL );
211213
DualSocket_init(pClient);
212214
DualAddr_init(pClientAddr);
213215
FD_ZERO(&rs);
214216
if( pListen->s4!=INVALID_SOCKET ){
@@ -217,21 +219,22 @@
217219
}
218220
if( pListen->s6!=INVALID_SOCKET ){
219221
FD_SET(pListen->s6, &rs);
220222
++rs_count;
221223
}
222
- if( select(rs_count, &rs, 0, 0, 0 /*blocking*/)==SOCKET_ERROR ){
223
- return;
224
- }
224
+ delay.tv_sec = 2;
225
+ delay.tv_usec = 0;
226
+ rc = select(rs_count, &rs, 0, 0, &delay);
225227
if( FD_ISSET(pListen->s4, &rs) ){
226228
pClient->s4 = accept(pListen->s4, (struct sockaddr*)&pClientAddr->a4.addr,
227229
&pClientAddr->a4.len);
228230
}
229231
if( FD_ISSET(pListen->s6, &rs) ){
230232
pClient->s6 = accept(pListen->s6, (struct sockaddr*)&pClientAddr->a6.addr,
231233
&pClientAddr->a6.len);
232234
}
235
+ return rc;
233236
}
234237
235238
/*
236239
** The HttpServer structure holds information about an instance of
237240
** the HTTP server itself.
@@ -514,16 +517,16 @@
514517
** that socket.
515518
*/
516519
void win32_http_server(
517520
int mnPort, int mxPort, /* Range of allowed TCP port numbers */
518521
const char *zBrowser, /* Command to launch browser. (Or NULL) */
519
- const char *zStopper, /* Stop server when this file is exists (Or NULL) */
522
+ const char *zStopper, /* Stop server when this file exists (Or NULL) */
520523
const char *zBaseUrl, /* The --baseurl option, or NULL */
521524
const char *zNotFound, /* The --notfound option, or NULL */
522525
const char *zFileGlob, /* The --fileglob option, or NULL */
523526
const char *zIpAddr, /* Bind to this IP address, if not NULL */
524
- int idleTimeout, /* Idle timeout in seconds. 0 means none */
527
+ int iIdleTimeout, /* Idle timeout in seconds. 0 means none */
525528
int flags /* One or more HTTP_SERVER_ flags */
526529
){
527530
HANDLE hStoppedEvent;
528531
WSADATA wd;
529532
DualSocket ds;
@@ -530,10 +533,11 @@
530533
int idCnt = 0;
531534
int iPort = mnPort;
532535
Blob options;
533536
wchar_t zTmpPath[MAX_PATH];
534537
const char *zSkin;
538
+ time_t stopTime = 0; /* When to stop due to idle timeout */
535539
#if USE_SEE
536540
const char *zSavedKey = 0;
537541
size_t savedKeySize = 0;
538542
#endif
539543
@@ -554,11 +558,11 @@
554558
blob_appendf(&options, " --localauth");
555559
}
556560
if( g.thTrace ){
557561
blob_appendf(&options, " --th-trace");
558562
}
559
- if( idleTimeout>0 ){
563
+ if( iIdleTimeout>0 ){
560564
blob_appendf(&options, " --keep-alive");
561565
}
562566
if( flags & HTTP_SERVER_REPOLIST ){
563567
blob_appendf(&options, " --repolist");
564568
}
@@ -636,18 +640,23 @@
636640
_beginthread(win32_server_stopper, 0, (void*)pServer);
637641
}
638642
/* Set the service status to running and pass the listener socket to the
639643
** service handling procedures. */
640644
win32_http_service_running(&ds);
645
+ if( iIdleTimeout>0 ) stopTime = time(0) + iIdleTimeout;
641646
for(;;){
642647
DualSocket client;
643648
DualAddr client_addr;
644649
HttpRequest *pRequest;
645650
int wsaError;
651
+ int nSock;
646652
647
- DualSocket_accept(&ds, &client, &client_addr);
648
- if( client.s4==INVALID_SOCKET && client.s6==INVALID_SOCKET ){
653
+ nSock = DualSocket_accept(&ds, &client, &client_addr);
654
+ if( nSock==SOCKET_ERROR
655
+ && client.s4==INVALID_SOCKET
656
+ && client.s6==INVALID_SOCKET
657
+ ){
649658
/* If the service control handler has closed the listener socket,
650659
** cleanup and return, otherwise report a fatal error. */
651660
wsaError = WSAGetLastError();
652661
DualSocket_close(&ds);
653662
if( (wsaError==WSAEINTR) || (wsaError==WSAENOTSOCK) ){
@@ -663,10 +672,11 @@
663672
pRequest->id = ++idCnt;
664673
pRequest->s = client.s4;
665674
memcpy(&pRequest->addr, &client_addr.a4, sizeof(client_addr.a4));
666675
pRequest->flags = flags;
667676
pRequest->zOptions = blob_str(&options);
677
+ if( iIdleTimeout>0 ) stopTime = time(0) + iIdleTimeout;
668678
if( flags & HTTP_SERVER_SCGI ){
669679
_beginthread(win32_scgi_request, 0, (void*)pRequest);
670680
}else{
671681
_beginthread(win32_http_request, 0, (void*)pRequest);
672682
}
@@ -676,16 +686,18 @@
676686
pRequest->id = ++idCnt;
677687
pRequest->s = client.s6;
678688
memcpy(&pRequest->addr, &client_addr.a6, sizeof(client_addr.a6));
679689
pRequest->flags = flags;
680690
pRequest->zOptions = blob_str(&options);
691
+ if( iIdleTimeout>0 ) stopTime = time(0) + iIdleTimeout;
681692
if( flags & HTTP_SERVER_SCGI ){
682693
_beginthread(win32_scgi_request, 0, (void*)pRequest);
683694
}else{
684695
_beginthread(win32_http_request, 0, (void*)pRequest);
685696
}
686697
}
698
+ if( iIdleTimeout>0 && stopTime<time(0) ) break;
687699
}
688700
DualSocket_close(&ds);
689701
WSACleanup();
690702
SetEvent(hStoppedEvent);
691703
CloseHandle(hStoppedEvent);
692704
--- src/winhttp.c
+++ src/winhttp.c
@@ -199,16 +199,18 @@
199 }
200 return 1;
201 };
202
203 /*
204 ** Accepts connections on DualSocket.
205 */
206 static void DualSocket_accept(DualSocket* pListen, DualSocket* pClient,
207 DualAddr* pClientAddr){
208 fd_set rs;
209 int rs_count = 0;
 
 
210 assert( pListen!=NULL && pClient!=NULL && pClientAddr!= NULL );
211 DualSocket_init(pClient);
212 DualAddr_init(pClientAddr);
213 FD_ZERO(&rs);
214 if( pListen->s4!=INVALID_SOCKET ){
@@ -217,21 +219,22 @@
217 }
218 if( pListen->s6!=INVALID_SOCKET ){
219 FD_SET(pListen->s6, &rs);
220 ++rs_count;
221 }
222 if( select(rs_count, &rs, 0, 0, 0 /*blocking*/)==SOCKET_ERROR ){
223 return;
224 }
225 if( FD_ISSET(pListen->s4, &rs) ){
226 pClient->s4 = accept(pListen->s4, (struct sockaddr*)&pClientAddr->a4.addr,
227 &pClientAddr->a4.len);
228 }
229 if( FD_ISSET(pListen->s6, &rs) ){
230 pClient->s6 = accept(pListen->s6, (struct sockaddr*)&pClientAddr->a6.addr,
231 &pClientAddr->a6.len);
232 }
 
233 }
234
235 /*
236 ** The HttpServer structure holds information about an instance of
237 ** the HTTP server itself.
@@ -514,16 +517,16 @@
514 ** that socket.
515 */
516 void win32_http_server(
517 int mnPort, int mxPort, /* Range of allowed TCP port numbers */
518 const char *zBrowser, /* Command to launch browser. (Or NULL) */
519 const char *zStopper, /* Stop server when this file is exists (Or NULL) */
520 const char *zBaseUrl, /* The --baseurl option, or NULL */
521 const char *zNotFound, /* The --notfound option, or NULL */
522 const char *zFileGlob, /* The --fileglob option, or NULL */
523 const char *zIpAddr, /* Bind to this IP address, if not NULL */
524 int idleTimeout, /* Idle timeout in seconds. 0 means none */
525 int flags /* One or more HTTP_SERVER_ flags */
526 ){
527 HANDLE hStoppedEvent;
528 WSADATA wd;
529 DualSocket ds;
@@ -530,10 +533,11 @@
530 int idCnt = 0;
531 int iPort = mnPort;
532 Blob options;
533 wchar_t zTmpPath[MAX_PATH];
534 const char *zSkin;
 
535 #if USE_SEE
536 const char *zSavedKey = 0;
537 size_t savedKeySize = 0;
538 #endif
539
@@ -554,11 +558,11 @@
554 blob_appendf(&options, " --localauth");
555 }
556 if( g.thTrace ){
557 blob_appendf(&options, " --th-trace");
558 }
559 if( idleTimeout>0 ){
560 blob_appendf(&options, " --keep-alive");
561 }
562 if( flags & HTTP_SERVER_REPOLIST ){
563 blob_appendf(&options, " --repolist");
564 }
@@ -636,18 +640,23 @@
636 _beginthread(win32_server_stopper, 0, (void*)pServer);
637 }
638 /* Set the service status to running and pass the listener socket to the
639 ** service handling procedures. */
640 win32_http_service_running(&ds);
 
641 for(;;){
642 DualSocket client;
643 DualAddr client_addr;
644 HttpRequest *pRequest;
645 int wsaError;
 
646
647 DualSocket_accept(&ds, &client, &client_addr);
648 if( client.s4==INVALID_SOCKET && client.s6==INVALID_SOCKET ){
 
 
 
649 /* If the service control handler has closed the listener socket,
650 ** cleanup and return, otherwise report a fatal error. */
651 wsaError = WSAGetLastError();
652 DualSocket_close(&ds);
653 if( (wsaError==WSAEINTR) || (wsaError==WSAENOTSOCK) ){
@@ -663,10 +672,11 @@
663 pRequest->id = ++idCnt;
664 pRequest->s = client.s4;
665 memcpy(&pRequest->addr, &client_addr.a4, sizeof(client_addr.a4));
666 pRequest->flags = flags;
667 pRequest->zOptions = blob_str(&options);
 
668 if( flags & HTTP_SERVER_SCGI ){
669 _beginthread(win32_scgi_request, 0, (void*)pRequest);
670 }else{
671 _beginthread(win32_http_request, 0, (void*)pRequest);
672 }
@@ -676,16 +686,18 @@
676 pRequest->id = ++idCnt;
677 pRequest->s = client.s6;
678 memcpy(&pRequest->addr, &client_addr.a6, sizeof(client_addr.a6));
679 pRequest->flags = flags;
680 pRequest->zOptions = blob_str(&options);
 
681 if( flags & HTTP_SERVER_SCGI ){
682 _beginthread(win32_scgi_request, 0, (void*)pRequest);
683 }else{
684 _beginthread(win32_http_request, 0, (void*)pRequest);
685 }
686 }
 
687 }
688 DualSocket_close(&ds);
689 WSACleanup();
690 SetEvent(hStoppedEvent);
691 CloseHandle(hStoppedEvent);
692
--- src/winhttp.c
+++ src/winhttp.c
@@ -199,16 +199,18 @@
199 }
200 return 1;
201 };
202
203 /*
204 ** Accepts connections on DualSocket. Return
205 */
206 static int DualSocket_accept(DualSocket* pListen, DualSocket* pClient,
207 DualAddr* pClientAddr){
208 fd_set rs;
209 int rs_count = 0;
210 int rc = 0;
211 struct timeval delay;
212 assert( pListen!=NULL && pClient!=NULL && pClientAddr!= NULL );
213 DualSocket_init(pClient);
214 DualAddr_init(pClientAddr);
215 FD_ZERO(&rs);
216 if( pListen->s4!=INVALID_SOCKET ){
@@ -217,21 +219,22 @@
219 }
220 if( pListen->s6!=INVALID_SOCKET ){
221 FD_SET(pListen->s6, &rs);
222 ++rs_count;
223 }
224 delay.tv_sec = 2;
225 delay.tv_usec = 0;
226 rc = select(rs_count, &rs, 0, 0, &delay);
227 if( FD_ISSET(pListen->s4, &rs) ){
228 pClient->s4 = accept(pListen->s4, (struct sockaddr*)&pClientAddr->a4.addr,
229 &pClientAddr->a4.len);
230 }
231 if( FD_ISSET(pListen->s6, &rs) ){
232 pClient->s6 = accept(pListen->s6, (struct sockaddr*)&pClientAddr->a6.addr,
233 &pClientAddr->a6.len);
234 }
235 return rc;
236 }
237
238 /*
239 ** The HttpServer structure holds information about an instance of
240 ** the HTTP server itself.
@@ -514,16 +517,16 @@
517 ** that socket.
518 */
519 void win32_http_server(
520 int mnPort, int mxPort, /* Range of allowed TCP port numbers */
521 const char *zBrowser, /* Command to launch browser. (Or NULL) */
522 const char *zStopper, /* Stop server when this file exists (Or NULL) */
523 const char *zBaseUrl, /* The --baseurl option, or NULL */
524 const char *zNotFound, /* The --notfound option, or NULL */
525 const char *zFileGlob, /* The --fileglob option, or NULL */
526 const char *zIpAddr, /* Bind to this IP address, if not NULL */
527 int iIdleTimeout, /* Idle timeout in seconds. 0 means none */
528 int flags /* One or more HTTP_SERVER_ flags */
529 ){
530 HANDLE hStoppedEvent;
531 WSADATA wd;
532 DualSocket ds;
@@ -530,10 +533,11 @@
533 int idCnt = 0;
534 int iPort = mnPort;
535 Blob options;
536 wchar_t zTmpPath[MAX_PATH];
537 const char *zSkin;
538 time_t stopTime = 0; /* When to stop due to idle timeout */
539 #if USE_SEE
540 const char *zSavedKey = 0;
541 size_t savedKeySize = 0;
542 #endif
543
@@ -554,11 +558,11 @@
558 blob_appendf(&options, " --localauth");
559 }
560 if( g.thTrace ){
561 blob_appendf(&options, " --th-trace");
562 }
563 if( iIdleTimeout>0 ){
564 blob_appendf(&options, " --keep-alive");
565 }
566 if( flags & HTTP_SERVER_REPOLIST ){
567 blob_appendf(&options, " --repolist");
568 }
@@ -636,18 +640,23 @@
640 _beginthread(win32_server_stopper, 0, (void*)pServer);
641 }
642 /* Set the service status to running and pass the listener socket to the
643 ** service handling procedures. */
644 win32_http_service_running(&ds);
645 if( iIdleTimeout>0 ) stopTime = time(0) + iIdleTimeout;
646 for(;;){
647 DualSocket client;
648 DualAddr client_addr;
649 HttpRequest *pRequest;
650 int wsaError;
651 int nSock;
652
653 nSock = DualSocket_accept(&ds, &client, &client_addr);
654 if( nSock==SOCKET_ERROR
655 && client.s4==INVALID_SOCKET
656 && client.s6==INVALID_SOCKET
657 ){
658 /* If the service control handler has closed the listener socket,
659 ** cleanup and return, otherwise report a fatal error. */
660 wsaError = WSAGetLastError();
661 DualSocket_close(&ds);
662 if( (wsaError==WSAEINTR) || (wsaError==WSAENOTSOCK) ){
@@ -663,10 +672,11 @@
672 pRequest->id = ++idCnt;
673 pRequest->s = client.s4;
674 memcpy(&pRequest->addr, &client_addr.a4, sizeof(client_addr.a4));
675 pRequest->flags = flags;
676 pRequest->zOptions = blob_str(&options);
677 if( iIdleTimeout>0 ) stopTime = time(0) + iIdleTimeout;
678 if( flags & HTTP_SERVER_SCGI ){
679 _beginthread(win32_scgi_request, 0, (void*)pRequest);
680 }else{
681 _beginthread(win32_http_request, 0, (void*)pRequest);
682 }
@@ -676,16 +686,18 @@
686 pRequest->id = ++idCnt;
687 pRequest->s = client.s6;
688 memcpy(&pRequest->addr, &client_addr.a6, sizeof(client_addr.a6));
689 pRequest->flags = flags;
690 pRequest->zOptions = blob_str(&options);
691 if( iIdleTimeout>0 ) stopTime = time(0) + iIdleTimeout;
692 if( flags & HTTP_SERVER_SCGI ){
693 _beginthread(win32_scgi_request, 0, (void*)pRequest);
694 }else{
695 _beginthread(win32_http_request, 0, (void*)pRequest);
696 }
697 }
698 if( iIdleTimeout>0 && stopTime<time(0) ) break;
699 }
700 DualSocket_close(&ds);
701 WSACleanup();
702 SetEvent(hStoppedEvent);
703 CloseHandle(hStoppedEvent);
704

Keyboard Shortcuts

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