Check-in [d8ceb4ad47]
Not logged in
Overview

SHA1 Hash:d8ceb4ad476342bedd30559eb679a7118a8833a2
Date: 2008-11-10 01:13:35
User: drh
Comment:The "ui" and "server" commands no longer quit if they cannot open TCP port 8080. They keep trying with consecutive ports until they find one that works - up to 100 ports.
Timelines: ancestors | descendants | both | trunk
Other Links: files | ZIP archive | manifest

Tags And Properties
Changes
[hide diffs]

Modified src/cgi.c from [ec3c5c4267] to [40d3404d8c].

@@ -1182,13 +1182,13 @@
 ** The parent never returns from this procedure.
 **
 ** Return 0 to each child as it runs.  If unable to establish a
 ** listening socket, return non-zero.
 */
-int cgi_http_server(int iPort, char *zBrowser){
+int cgi_http_server(int mnPort, int mxPort, char *zBrowser){
 #ifdef __MINGW32__
-  fprintf(stderr,"server not yet available in windows version of fossil\n");
+  /* Use win32_http_server() instead */
   exit(1);
 #else
   int listener;                /* The server socket */
   int connection;              /* A socket for each individual connection */
   fd_set readfds;              /* Set of file descriptors for select() */
@@ -1196,29 +1196,49 @@
   int child;                   /* PID of the child process */
   int nchildren = 0;           /* Number of child processes */
   struct timeval delay;        /* How long to wait inside select() */
   struct sockaddr_in inaddr;   /* The socket address */
   int opt = 1;                 /* setsockopt flag */
+  int iPort = mnPort;
+
+  while( iPort<mxPort ){
+    memset(&inaddr, 0, sizeof(inaddr));
+    inaddr.sin_family = AF_INET;
+    inaddr.sin_addr.s_addr = INADDR_ANY;
+    inaddr.sin_port = htons(iPort);
+    listener = socket(AF_INET, SOCK_STREAM, 0);
+    if( listener<0 ){
+      iPort++;
+      continue;
+    }
 
-  memset(&inaddr, 0, sizeof(inaddr));
-  inaddr.sin_family = AF_INET;
-  inaddr.sin_addr.s_addr = INADDR_ANY;
-  inaddr.sin_port = htons(iPort);
-  listener = socket(AF_INET, SOCK_STREAM, 0);
-  if( listener<0 ){
-    return 1;
-  }
+    /* if we can't terminate nicely, at least allow the socket to be reused */
+    setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
 
-  /* if we can't terminate nicely, at least allow the socket to be reused */
-  setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
-
-  if( bind(listener, (struct sockaddr*)&inaddr, sizeof(inaddr))<0 ){
-    close(listener);
-    return 1;
+    if( bind(listener, (struct sockaddr*)&inaddr, sizeof(inaddr))<0 ){
+      close(listener);
+      iPort++;
+      continue;
+    }
+    break;
+  }
+  if( iPort>mxPort ){
+    if( mnPort==mxPort ){
+      fossil_fatal("unable to open listening socket on ports %d", mnPort);
+    }else{
+      fossil_fatal("unable to open listening socket on any"
+                   " ports %d..%d", mnPort, mxPort);
+    }
   }
+  if( iPort>mxPort ) return 1;
   listen(listener,10);
+  if( iPort>mnPort ){
+    printf("Listening for HTTP requests on TCP port %d\n", iPort);
+    fflush(stdout);
+  }
   if( zBrowser ){
+    zBrowser = mprintf(zBrowser, iPort);
     system(zBrowser);
   }
   while( 1 ){
     if( nchildren>MAX_PARALLEL ){
       /* Slow down if connections are arriving too fast */

Modified src/main.c from [7ce5037b83] to [936fc223a3].

@@ -704,11 +704,11 @@
 **
 ** The "ui" command automatically starts a web browser after initializing
 ** the web server.
 */
 void cmd_webserver(void){
-  int iPort;
+  int iPort, mxPort;
   const char *zPort;
   char *zBrowser;
   char *zBrowserCmd = 0;
 
   g.thTrace = find_option("th-trace", 0, 0)!=0;
@@ -721,26 +721,27 @@
     db_must_be_within_tree();
   }else{
     db_open_repository(g.argv[2]);
   }
   if( zPort ){
-    iPort = atoi(zPort);
+    iPort = mxPort = atoi(zPort);
   }else{
     iPort = db_get_int("http-port", 8080);
+    mxPort = iPort+100;
   }
 #ifndef __MINGW32__
   /* Unix implementation */
   if( g.argv[1][0]=='u' ){
 #if !defined(__DARWIN__) && !defined(__APPLE__)
     zBrowser = db_get("web-browser", "firefox");
 #else
     zBrowser = db_get("web-browser", "open");
 #endif
-    zBrowserCmd = mprintf("%s http://localhost:%d/ &", zBrowser, iPort);
+    zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
   }
   db_close();
-  if( cgi_http_server(iPort, zBrowserCmd) ){
+  if( cgi_http_server(iPort, mxPort, zBrowserCmd) ){
     fossil_fatal("unable to listen on TCP socket %d", iPort);
   }
   g.httpIn = stdin;
   g.httpOut = stdout;
   if( g.fHttpTrace ){
@@ -756,11 +757,11 @@
   process_one_web_page();
 #else
   /* Win32 implementation */
   if( g.argv[1][0]=='u' ){
     zBrowser = db_get("web-browser", "start");
-    zBrowserCmd = mprintf("%s http://127.0.0.1:%d/", zBrowser, iPort);
+    zBrowserCmd = mprintf("%s http://127.0.0.1:%%d/", zBrowser);
   }
   db_close();
-  win32_http_server(iPort, zBrowserCmd);
+  win32_http_server(iPort, mxPort, zBrowserCmd);
 #endif
 }

Modified src/winhttp.c from [572742e69b] to [dafbf1595e].

@@ -134,37 +134,52 @@
 
 /*
 ** Start a listening socket and process incoming HTTP requests on
 ** that socket.
 */
-void win32_http_server(int iPort, char *zBrowser){
+void win32_http_server(int mnPort, int mxPort, char *zBrowser){
   WSADATA wd;
   SOCKET s;
   SOCKADDR_IN addr;
   int idCnt = 0;
+  int iPort = mnPort;
 
   if( WSAStartup(MAKEWORD(1,1), &wd) ){
     fossil_fatal("unable to initialize winsock");
   }
-  zTempPrefix = mprintf("fossil_server_P%d_", iPort);
-  s = socket(AF_INET, SOCK_STREAM, 0);
-  if( s==INVALID_SOCKET ){
-    fossil_fatal("unable to create a socket");
+  while( iPort<mxPort ){
+    s = socket(AF_INET, SOCK_STREAM, 0);
+    if( s==INVALID_SOCKET ){
+      fossil_fatal("unable to create a socket");
+    }
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(iPort);
+    addr.sin_addr.s_addr = htonl(INADDR_ANY);
+    if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){
+      closesocket(s);
+      iPort++;
+      continue;
+    }
+    if( listen(s, SOMAXCONN)==SOCKET_ERROR ){
+      closesocket(s);
+      iPort++;
+      continue;
+    }
+    break;
   }
-  addr.sin_family = AF_INET;
-  addr.sin_port = htons(iPort);
-  addr.sin_addr.s_addr = htonl(INADDR_ANY);
-  if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){
-    closesocket(s);
-    fossil_fatal("unable to bind");
+  if( iPort>mxPort ){
+    if( mnPort==mxPort ){
+      fossil_fatal("unable to open listening socket on ports %d", mnPort);
+    }else{
+      fossil_fatal("unable to open listening socket on any"
+                   " ports %d..%d", mnPort, mxPort);
+    }
   }
-  if( listen(s, SOMAXCONN)==SOCKET_ERROR ){
-    closesocket(s);
-    fossil_fatal("unable to listen");
-  }
+  zTempPrefix = mprintf("fossil_server_P%d_", iPort);
   printf("Listening for HTTP requests on TCP port %d\n", iPort);
   if( zBrowser ){
+    zBrowser = mprintf(zBrowser, iPort);
     printf("Launch webbrowser: %s\n", zBrowser);
     system(zBrowser);
   }
   printf("Type Ctrl-C to stop the HTTP server\n");
   for(;;){