2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
|
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() */
struct sockaddr_in6 inaddr; /* The socket address */
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 */
while( iPort<=mxPort ){
if( flags & HTTP_SERVER_UNIXSOCKET ){
/* Initialize a Unix socket named g.zSockName */
assert( g.zSockName!=0 );
memset(&uxaddr, 0, sizeof(uxaddr));
if( strlen(g.zSockName)>sizeof(uxaddr.sun_path) ){
|
>
>
|
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
|
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() */
struct sockaddr_in6 inaddr; /* The socket address */
struct sockaddr_in inaddr4; /* IPv4 address; needed by OpenBSD */
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 */
int bIPv4 = 0; /* Use IPv4 only; use inaddr4, not inaddr */
while( iPort<=mxPort ){
if( flags & HTTP_SERVER_UNIXSOCKET ){
/* Initialize a Unix socket named g.zSockName */
assert( g.zSockName!=0 );
memset(&uxaddr, 0, sizeof(uxaddr));
if( strlen(g.zSockName)>sizeof(uxaddr.sun_path) ){
|
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
|
if( g.zSockMode ){
file_set_mode(g.zSockName, listener, g.zSockMode, 0);
}else{
file_set_mode(g.zSockName, listener, "0660", 1);
}
}else{
/* Initialize a TCP/IP socket on port iPort */
memset(&inaddr, 0, sizeof(inaddr));
inaddr.sin6_family = AF_INET6;
if( zIpAddr ){
/* Bind to the specific IP address given by zIpAddr[] */
size_t nAddr = strlen(zIpAddr);
char z4to6[30];
if( nAddr<16 ){
/* The specified IP address might be in IPv4 notation (ex: 1.2.3.4)
** which inet_pton() does not understand. Convert in into a IPv6
** mapping of an IPv4 address: (::FFFF:1.2.3.4) */
memcpy(z4to6,"::ffff:", 7);
memcpy(z4to6+7, zIpAddr, nAddr+2);
}else{
z4to6[0] = 0;
}
/* Convert the zIpAddr text string into an actual IPv6 address */
if( inet_pton(AF_INET6, zIpAddr, &inaddr.sin6_addr)==0
&& (z4to6[0]==0 || inet_pton(AF_INET6, z4to6, &inaddr.sin6_addr)==0)
){
fossil_fatal("not a valid IP address: %s", zIpAddr);
}
}else if( flags & HTTP_SERVER_LOCALHOST ){
/* Bind to the loop-back IP address */
inet_pton(AF_INET6, "::ffff.127.0.0.1", &inaddr.sin6_addr);
}else{
/* Bind to any and all available IP addresses */
inaddr.sin6_addr = in6addr_any;
}
inaddr.sin6_port = htons(iPort);
listener = socket(AF_INET6, SOCK_STREAM, 0);
if( listener<0 ){
iPort++;
continue;
}
allowBothIpV4andV6(listener);
}
/* if we can't terminate nicely, at least allow the socket to be reused */
setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
if( flags & HTTP_SERVER_UNIXSOCKET ){
rc = bind(listener, (struct sockaddr*)&uxaddr, sizeof(uxaddr));
/* Set the owner of the socket if requested by --socket-owner. This
** must wait until after bind(), after the filesystem object has been
** created. See https://lkml.org/lkml/2004/11/1/84 and
** https://fossil-scm.org/forum/forumpost/7517680ef9684c57 */
if( g.zSockOwner ){
file_set_owner(g.zSockName, listener, g.zSockOwner);
}
}else{
rc = bind(listener, (struct sockaddr*)&inaddr, sizeof(inaddr));
}
if( rc<0 ){
close(listener);
iPort++;
continue;
|
>
>
>
>
>
>
>
>
|
|
>
|
<
|
<
|
<
<
<
<
<
<
>
|
<
|
|
|
<
<
|
|
<
<
<
>
>
>
>
>
>
>
>
|
|
>
>
<
>
>
|
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
|
if( g.zSockMode ){
file_set_mode(g.zSockName, listener, g.zSockMode, 0);
}else{
file_set_mode(g.zSockName, listener, "0660", 1);
}
}else{
/* Initialize a TCP/IP socket on port iPort */
if( (flags & HTTP_SERVER_LOCALHOST)!=0 && zIpAddr==0 ){
/* Map all loopback to 127.0.0.1, since this is the easiest way
** to support OpenBSD and its limitations without burdening
** Linux and MacOS with lots of extra code and complication. */
zIpAddr = "127.0.0.1";
}
if( zIpAddr ){
if( strchr(zIpAddr,':') ){
memset(&inaddr, 0, sizeof(inaddr));
inaddr.sin6_family = AF_INET6;
bIPv4 = 0;
if( inet_pton(AF_INET6, zIpAddr, &inaddr.sin6_addr)==0 ){
fossil_fatal("not a valid IPv6 address: %s", zIpAddr);
}
}else{
memset(&inaddr4, 0, sizeof(inaddr4));
inaddr4.sin_family = AF_INET;
bIPv4 = 1;
inaddr4.sin_addr.s_addr = inet_addr(zIpAddr);
if( inaddr4.sin_addr.s_addr == INADDR_NONE ){
fossil_fatal("not a valid IPv4 address: %s", zIpAddr);
}
}
}else{
/* Bind to any and all available IP addresses */
memset(&inaddr, 0, sizeof(inaddr));
inaddr.sin6_family = AF_INET6;
inaddr.sin6_addr = in6addr_any;
bIPv4 = 0;
}
if( bIPv4 ){
inaddr4.sin_port = htons(iPort);
listener = socket(AF_INET, SOCK_STREAM, 0);
}else{
inaddr.sin6_port = htons(iPort);
listener = socket(AF_INET6, SOCK_STREAM, 0);
allowBothIpV4andV6(listener);
}
if( listener<0 ){
iPort++;
continue;
}
}
/* if we can't terminate nicely, at least allow the socket to be reused */
setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
if( flags & HTTP_SERVER_UNIXSOCKET ){
rc = bind(listener, (struct sockaddr*)&uxaddr, sizeof(uxaddr));
/* Set the owner of the socket if requested by --socket-owner. This
** must wait until after bind(), after the filesystem object has been
** created. See https://lkml.org/lkml/2004/11/1/84 and
** https://fossil-scm.org/forum/forumpost/7517680ef9684c57 */
if( g.zSockOwner ){
file_set_owner(g.zSockName, listener, g.zSockOwner);
}
}else if( bIPv4 ){
rc = bind(listener, (struct sockaddr*)&inaddr4, sizeof(inaddr4));
}else{
rc = bind(listener, (struct sockaddr*)&inaddr, sizeof(inaddr));
}
if( rc<0 ){
close(listener);
iPort++;
continue;
|