Fossil

Diff
Login

Differences From Artifact [29dcebc0e5]:

To Artifact [6c239b3853]:


78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92







-
+







# include <arpa/inet.h>
# include <sys/times.h>
# include <sys/time.h>
# include <sys/wait.h>
# include <sys/select.h>
# include <errno.h>
#endif
#ifdef __EMX__
#if defined(__EMX__) || defined(__morphos__)
  typedef int socklen_t;
#endif
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
2081
2082
2083
2084
2085
2086
2087

2088
2089

2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101

2102

2103
2104
2105

2106
2107
2108
2109
2110



2111
2112
2113
2114
2115
2116
2117
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125







+


+












+

+



+





+
+
+







/*
** All possible forms of an IP address.  Needed to work around GCC strict
** aliasing rules.
*/
typedef union {
  struct sockaddr sa;              /* Abstract superclass */
  struct sockaddr_in sa4;          /* IPv4 */
#ifdef AF_INET6
  struct sockaddr_in6 sa6;         /* IPv6 */
  struct sockaddr_storage sas;     /* Should be the maximum of the above 3 */
#endif
} address;

/*
** Determine the IP address on the other side of a connection.
** Return a pointer to a string.  Or return 0 if unable.
**
** The string is held in a static buffer that is overwritten on
** each call.
*/
char *cgi_remote_ip(int fd){
  address remoteAddr;
  socklen_t size = sizeof(remoteAddr);
#ifdef AF_INET6
  static char zHost[NI_MAXHOST];
#endif
  if( getpeername(0, &remoteAddr.sa, &size) ){
    return 0;
  }
#ifdef AF_INET6
  if( getnameinfo(&remoteAddr.sa, size, zHost, sizeof(zHost), 0, 0,
                  NI_NUMERICHOST) ){
    return 0;
  }
  return zHost;
#else
  return inet_ntoa(((struct sockaddr_in *)&remoteAddr.sa)->sin_addr);
#endif
}

/*
** This routine handles a single HTTP request which is coming in on
** g.httpIn and which replies on g.httpOut
**
** The HTTP request is read from g.httpIn and is used to initialize
2548
2549
2550
2551
2552
2553
2554

2555

2556
2557
2558
2559
2560
2561
2562
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572







+

+







  int connection;              /* An incoming connection */
  int nRequest = 0;            /* Number of requests handled so far */
  fd_set readfds;              /* Set of file descriptors for select() */
  socklen_t lenaddr;           /* Length of the inaddr structure */
  int child;                   /* PID of the child process */
  int nchildren = 0;           /* Number of child processes */
  struct timeval delay;        /* How long to wait inside select() */
#ifdef AF_INET6
  struct sockaddr_in6 inaddr6; /* Address for IPv6 */
#endif
  struct sockaddr_in inaddr4;  /* Address for IPv4 */
  struct sockaddr_un uxaddr;   /* The address for unix-domain sockets */
  int opt = 1;                 /* setsockopt flag */
  int rc;                      /* Result code from system calls */
  int iPort = mnPort;          /* Port to try to use */
  const char *zRequestType;    /* Type of requests to listen for */

2613
2614
2615
2616
2617
2618
2619

2620
2621
2622
2623
2624
2625
2626
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637







+







    ** https://fossil-scm.org/forum/forumpost/7517680ef9684c57 */
    if( g.zSockOwner ){
      file_set_owner(g.zSockName, listen4, g.zSockOwner);
    }
    fossil_print("Listening for %s requests on unix socket %s\n",
                 zRequestType, g.zSockName);
    fflush(stdout);
#ifdef AF_INET6
  }else if( zIpAddr && strchr(zIpAddr,':')!=0 ){
    /* CASE 2: TCP on IPv6 IP address specified by zIpAddr and on port iPort.
    */
    assert( mnPort==mxPort );
    memset(&inaddr6, 0, sizeof(inaddr6));
    inaddr6.sin6_family = AF_INET6;
    inaddr6.sin6_port = htons(iPort);
2642
2643
2644
2645
2646
2647
2648

2649
2650
2651
2652
2653
2654
2655
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667







+







                   zIpAddr, mnPort);
    }
    mxListen = listen6;
    listen4 = -1;
    fossil_print("Listening for %s requests on [%s]:%d\n",
                 zRequestType, zIpAddr, iPort);
    fflush(stdout);
#endif
  }else if( zIpAddr && zIpAddr[0] ){
    /* CASE 3: TCP on IPv4 IP address specified by zIpAddr and on port iPort.
    */
    assert( mnPort==mxPort );
    memset(&inaddr4, 0, sizeof(inaddr4));
    inaddr4.sin_family = AF_INET;
    inaddr4.sin_port = htons(iPort);
2704
2705
2706
2707
2708
2709
2710

2711
2712
2713
2714
2715
2716
2717
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730







+







      }
      if( listen4<0 ){
        iPort++;
        continue;
      }
      mxListen = listen4;

#ifdef AF_INET6
      /* If we get here, that means we found an open TCP port at iPort for
      ** IPv4.  Try to set up a corresponding IPv6 socket on the same port.
      */
      memset(&inaddr6, 0, sizeof(inaddr6));
      inaddr6.sin6_family = AF_INET6;
      inaddr6.sin6_port = htons(iPort);
      if( flags & HTTP_SERVER_LOCALHOST ){
2731
2732
2733
2734
2735
2736
2737



2738
2739
2740
2741
2742
2743
2744
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760







+
+
+







      }
      if( listen6<0 ){
        zProto = "IPv4 only";
      }else{
        zProto = "IPv4 and IPv6";
        if( listen6>listen4 ) mxListen = listen6;
      }
#else
      zProto = "IPv4 only";
#endif

      fossil_print("Listening for %s requests on TCP port %s%d, %s\n",
                   zRequestType, 
                   (flags & HTTP_SERVER_LOCALHOST)!=0 ? "localhost:" : "",
                   iPort, zProto);
      fflush(stdout);
      break;
2788
2789
2790
2791
2792
2793
2794

2795
2796
2797

2798
2799
2800
2801

2802
2803
2804
2805
2806



2807
2808
2809
2810
2811
2812
2813
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835







+



+




+





+
+
+







    assert( listen4>0 || listen6>0 );
    if( listen4>0 ) FD_SET( listen4, &readfds);
    if( listen6>0 ) FD_SET( listen6, &readfds);
    select( mxListen+1, &readfds, 0, 0, &delay);
    if( listen4>0 && FD_ISSET(listen4, &readfds) ){
      lenaddr = sizeof(inaddr4);
      connection = accept(listen4, (struct sockaddr*)&inaddr4, &lenaddr);
#ifdef AF_INET6
    }else if( listen6>0 && FD_ISSET(listen6, &readfds) ){
      lenaddr = sizeof(inaddr6);
      connection = accept(listen6, (struct sockaddr*)&inaddr6, &lenaddr);
#endif
    }else{
      connection = -1;
    }
    if( connection>=0 ){
#ifndef __morphos__
      if( flags & HTTP_SERVER_NOFORK ){
        child = 0;
      }else{
        child = fork();
      }
#else
      child = 0;
#endif
      if( child!=0 ){
        if( child>0 ){
          nchildren++;
          nRequest++;
        }
        close(connection);
      }else{