github.com/kisexp/xdchain@v0.0.0-20211206025815-490d6b732aa7/node/endpoints.go (about)

     1  // Copyright 2018 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package node
    18  
    19  import (
    20  	"context"
    21  	"crypto/tls"
    22  	"fmt"
    23  	"net"
    24  	"net/http"
    25  	"time"
    26  
    27  	"github.com/kisexp/xdchain/log"
    28  	"github.com/kisexp/xdchain/plugin/security"
    29  	"github.com/kisexp/xdchain/rpc"
    30  )
    31  
    32  // StartHTTPEndpoint starts the HTTP RPC endpoint.
    33  func StartHTTPEndpoint(endpoint string, timeouts rpc.HTTPTimeouts, handler http.Handler, tlsConfigSource security.TLSConfigurationSource) (*http.Server, net.Addr, bool, error) {
    34  	// start the HTTP listener
    35  	var (
    36  		listener     net.Listener
    37  		err          error
    38  		isTlsEnabled bool
    39  	)
    40  	if isTlsEnabled, listener, err = startListener(endpoint, tlsConfigSource); err != nil {
    41  		return nil, nil, isTlsEnabled, err
    42  	}
    43  	// make sure timeout values are meaningful
    44  	CheckTimeouts(&timeouts)
    45  	// Bundle and start the HTTP server
    46  	httpSrv := &http.Server{
    47  		Handler:      handler,
    48  		ReadTimeout:  timeouts.ReadTimeout,
    49  		WriteTimeout: timeouts.WriteTimeout,
    50  		IdleTimeout:  timeouts.IdleTimeout,
    51  
    52  		// Ensure to Disable HTTP/2
    53  		// this configuration and customized tls.Config is to follow: https://blog.bracebin.com/achieving-perfect-ssl-labs-score-with-go
    54  		TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)),
    55  	}
    56  	go httpSrv.Serve(listener)
    57  	return httpSrv, listener.Addr(), isTlsEnabled, err
    58  }
    59  
    60  // checkModuleAvailability checks that all names given in modules are actually
    61  // available API services. It assumes that the MetadataApi module ("rpc") is always available;
    62  // the registration of this "rpc" module happens in NewServer() and is thus common to all endpoints.
    63  func checkModuleAvailability(modules []string, apis []rpc.API) (bad, available []string) {
    64  	availableSet := make(map[string]struct{})
    65  	for _, api := range apis {
    66  		if _, ok := availableSet[api.Namespace]; !ok {
    67  			availableSet[api.Namespace] = struct{}{}
    68  			available = append(available, api.Namespace)
    69  		}
    70  	}
    71  	for _, name := range modules {
    72  		if _, ok := availableSet[name]; !ok && name != rpc.MetadataApi {
    73  			bad = append(bad, name)
    74  		}
    75  	}
    76  	return bad, available
    77  }
    78  
    79  // Quorum
    80  // Produce net.Listener instance with TLS support if tlsConfigSource provides the config
    81  func startListener(endpoint string, tlsConfigSource security.TLSConfigurationSource) (bool, net.Listener, error) {
    82  	var tlsConfig *tls.Config
    83  	var err error
    84  	var listener net.Listener
    85  	isTlsEnabled := true
    86  	if tlsConfigSource != nil {
    87  		if tlsConfig, err = tlsConfigSource.Get(context.Background()); err != nil {
    88  			isTlsEnabled = false
    89  		}
    90  	} else {
    91  		isTlsEnabled = false
    92  		err = fmt.Errorf("no TLSConfigurationSource found")
    93  	}
    94  	if isTlsEnabled {
    95  		if listener, err = tls.Listen("tcp", endpoint, tlsConfig); err != nil {
    96  			return isTlsEnabled, nil, err
    97  		}
    98  	} else {
    99  		log.Info("Security: TLS not enabled", "endpoint", endpoint, "reason", err)
   100  		if listener, err = net.Listen("tcp", endpoint); err != nil {
   101  			return isTlsEnabled, nil, err
   102  		}
   103  	}
   104  	return isTlsEnabled, listener, nil
   105  }
   106  
   107  // CheckTimeouts ensures that timeout values are meaningful
   108  func CheckTimeouts(timeouts *rpc.HTTPTimeouts) {
   109  	if timeouts.ReadTimeout < time.Second {
   110  		log.Warn("Sanitizing invalid HTTP read timeout", "provided", timeouts.ReadTimeout, "updated", rpc.DefaultHTTPTimeouts.ReadTimeout)
   111  		timeouts.ReadTimeout = rpc.DefaultHTTPTimeouts.ReadTimeout
   112  	}
   113  	if timeouts.WriteTimeout < time.Second {
   114  		log.Warn("Sanitizing invalid HTTP write timeout", "provided", timeouts.WriteTimeout, "updated", rpc.DefaultHTTPTimeouts.WriteTimeout)
   115  		timeouts.WriteTimeout = rpc.DefaultHTTPTimeouts.WriteTimeout
   116  	}
   117  	if timeouts.IdleTimeout < time.Second {
   118  		log.Warn("Sanitizing invalid HTTP idle timeout", "provided", timeouts.IdleTimeout, "updated", rpc.DefaultHTTPTimeouts.IdleTimeout)
   119  		timeouts.IdleTimeout = rpc.DefaultHTTPTimeouts.IdleTimeout
   120  	}
   121  }