2019-08-13 18:08:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
package server
|
|
|
|
|
|
|
|
|
|
|
|
import "bytes"
|
2019-08-15 06:46:15 +00:00
|
|
|
import "context"
|
2019-08-14 18:55:05 +00:00
|
|
|
import "crypto/tls"
|
2019-08-13 18:08:16 +00:00
|
|
|
import "flag"
|
|
|
|
import "fmt"
|
|
|
|
import "io"
|
2021-12-16 15:40:25 +00:00
|
|
|
import "io/ioutil"
|
2019-08-13 18:08:16 +00:00
|
|
|
import "log"
|
|
|
|
import "net"
|
|
|
|
import "net/http"
|
|
|
|
import "os"
|
|
|
|
import "os/signal"
|
|
|
|
import "runtime"
|
|
|
|
import "runtime/debug"
|
|
|
|
import "runtime/pprof"
|
|
|
|
import "strconv"
|
2019-08-16 17:50:25 +00:00
|
|
|
import "strings"
|
2019-08-13 18:08:16 +00:00
|
|
|
import "sync"
|
2021-12-18 09:35:58 +00:00
|
|
|
import "sync/atomic"
|
2019-08-13 18:08:16 +00:00
|
|
|
import "syscall"
|
|
|
|
import "time"
|
|
|
|
import "unsafe"
|
|
|
|
|
|
|
|
import "github.com/colinmarc/cdb"
|
|
|
|
|
|
|
|
import "github.com/valyala/fasthttp"
|
|
|
|
import "github.com/valyala/fasthttp/reuseport"
|
|
|
|
|
2021-12-16 21:10:11 +00:00
|
|
|
import "github.com/lucas-clemente/quic-go"
|
|
|
|
import "github.com/lucas-clemente/quic-go/http3"
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
import . "github.com/volution/kawipiko/lib/common"
|
|
|
|
import . "github.com/volution/kawipiko/lib/server"
|
|
|
|
|
2021-12-16 11:32:05 +00:00
|
|
|
import _ "embed"
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type server struct {
|
2021-12-17 23:29:57 +00:00
|
|
|
httpPlain1Server *fasthttp.Server
|
|
|
|
httpPlain2Server *http.Server
|
|
|
|
httpTls1Server *fasthttp.Server
|
|
|
|
httpTls2Server *http.Server
|
|
|
|
httpQuicServer *http3.Server
|
2019-08-13 18:08:16 +00:00
|
|
|
cdbReader *cdb.CDB
|
2021-12-19 12:06:39 +00:00
|
|
|
cachedReferences map[string][2]uint64
|
|
|
|
cachedDataMeta map[uint64][]byte
|
|
|
|
cachedDataContent map[uint64][]byte
|
2019-08-13 18:08:16 +00:00
|
|
|
securityHeadersEnabled bool
|
|
|
|
securityHeadersTls bool
|
2021-12-16 13:21:09 +00:00
|
|
|
http1Disabled bool
|
|
|
|
http2Disabled bool
|
2021-12-16 21:10:11 +00:00
|
|
|
http3AltSvc string
|
2019-08-14 18:55:05 +00:00
|
|
|
quiet bool
|
2021-12-19 12:06:39 +00:00
|
|
|
debug bool
|
2019-08-13 18:08:16 +00:00
|
|
|
dummy bool
|
2021-12-17 23:56:34 +00:00
|
|
|
dummyEmpty bool
|
|
|
|
dummyDelay time.Duration
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-12-18 09:35:58 +00:00
|
|
|
func (_server *server) ServeUnwrapped (_context *fasthttp.RequestCtx) () {
|
2019-08-13 18:08:16 +00:00
|
|
|
|
2021-12-16 13:45:05 +00:00
|
|
|
|
2019-08-14 18:55:05 +00:00
|
|
|
if _server.dummy {
|
2021-12-17 23:56:34 +00:00
|
|
|
if !_server.dummyEmpty {
|
|
|
|
_server.ServeDummy (_context)
|
2021-12-18 15:30:45 +00:00
|
|
|
} else {
|
|
|
|
_context.Response.SetStatusCode (fasthttp.StatusOK)
|
2021-12-17 23:56:34 +00:00
|
|
|
}
|
|
|
|
if _server.dummyDelay != 0 {
|
|
|
|
time.Sleep (_server.dummyDelay)
|
|
|
|
}
|
2019-08-14 18:55:05 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-12-16 13:45:05 +00:00
|
|
|
|
|
|
|
_request := (*fasthttp.Request) (NoEscape (unsafe.Pointer (&_context.Request)))
|
|
|
|
_requestHeaders := (*fasthttp.RequestHeader) (NoEscape (unsafe.Pointer (&_request.Header)))
|
2019-08-13 18:08:16 +00:00
|
|
|
_response := (*fasthttp.Response) (NoEscape (unsafe.Pointer (&_context.Response)))
|
2021-12-16 13:45:05 +00:00
|
|
|
_responseHeaders := (*fasthttp.ResponseHeader) (NoEscape (unsafe.Pointer (&_response.Header)))
|
|
|
|
|
2021-12-16 17:05:00 +00:00
|
|
|
_requestMethod := _requestHeaders.Method ()
|
2021-12-16 15:17:42 +00:00
|
|
|
_requestUri := _requestHeaders.RequestURI ()
|
|
|
|
_requestUriString_0 := BytesToString (_requestUri)
|
|
|
|
_requestUriString := NoEscapeString (&_requestUriString_0)
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
|
|
|
|
|
2021-12-16 17:05:00 +00:00
|
|
|
|
2021-12-19 12:06:39 +00:00
|
|
|
_pathBuffer := [256]byte {}
|
|
|
|
_keyBufferLarge := [256 + 16]byte {}
|
|
|
|
_keyBufferSmall := [8]byte {}
|
2019-08-13 18:08:16 +00:00
|
|
|
|
|
|
|
_path := _pathBuffer[:0]
|
2021-12-16 15:17:42 +00:00
|
|
|
_path = append (_path, _requestUri ...)
|
2019-08-13 18:08:16 +00:00
|
|
|
if _pathLimit := bytes.IndexByte (_path, '?'); _pathLimit > 0 {
|
|
|
|
_path = _path[: _pathLimit]
|
|
|
|
}
|
2021-12-16 15:18:02 +00:00
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
// FIXME: Decode path according to `decodeArgAppendNoPlus`!
|
|
|
|
|
|
|
|
_pathLen := len (_path)
|
|
|
|
|
2021-12-16 17:05:00 +00:00
|
|
|
if ! bytes.Equal (StringToBytes (http.MethodGet), _requestMethod) {
|
2021-12-16 15:28:29 +00:00
|
|
|
if !_server.quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ww] [bce7a75b] [http-x..] invalid method `%s` for `%s`!\n", BytesToString (_requestHeaders.Method ()), *_requestUriString)
|
2021-12-16 15:28:29 +00:00
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
_server.ServeError (_context, http.StatusMethodNotAllowed, nil, true)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if (_pathLen == 0) || (_path[0] != '/') {
|
2021-12-16 15:28:29 +00:00
|
|
|
if !_server.quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ww] [fa6b1923] [http-x..] invalid path `%s`!\n", *_requestUriString)
|
2021-12-16 15:28:29 +00:00
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
_server.ServeError (_context, http.StatusBadRequest, nil, true)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-12-16 15:18:02 +00:00
|
|
|
_pathIsRoot := _pathLen == 1
|
|
|
|
_pathHasSlash := !_pathIsRoot && (_path[_pathLen - 1] == '/')
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
if bytes.HasPrefix (_path, StringToBytes ("/__/")) {
|
|
|
|
if bytes.Equal (_path, StringToBytes ("/__/heartbeat")) || bytes.HasPrefix (_path, StringToBytes ("/__/heartbeat/")) {
|
|
|
|
_server.ServeStatic (_context, http.StatusOK, HeartbeatDataOk, HeartbeatContentType, HeartbeatContentEncoding, false)
|
|
|
|
return
|
2021-12-16 15:18:02 +00:00
|
|
|
} else if bytes.Equal (_path, StringToBytes ("/__/about")) || bytes.Equal (_path, StringToBytes ("/__/about/")) {
|
2019-08-13 18:08:16 +00:00
|
|
|
_server.ServeStatic (_context, http.StatusOK, AboutBannerData, AboutBannerContentType, AboutBannerContentEncoding, true)
|
|
|
|
return
|
2021-12-16 15:18:02 +00:00
|
|
|
} else if bytes.HasPrefix (_path, StringToBytes ("/__/banners/errors/")) {
|
|
|
|
_code := _path[len ("/__/banners/errors/") :]
|
2021-12-16 17:05:00 +00:00
|
|
|
if _code, _error := strconv.Atoi (BytesToString (*NoEscapeBytes (&_code))); _error == nil {
|
2019-08-13 18:08:16 +00:00
|
|
|
_banner, _bannerFound := ErrorBannersData[uint (_code)]
|
|
|
|
if (_code > 0) && _bannerFound {
|
|
|
|
_server.ServeStatic (_context, http.StatusOK, _banner, ErrorBannerContentType, ErrorBannerContentEncoding, true)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2021-12-16 15:18:02 +00:00
|
|
|
_server.ServeError (_context, http.StatusBadRequest, nil, true)
|
2019-08-13 18:08:16 +00:00
|
|
|
return
|
|
|
|
} else {
|
2021-12-16 15:18:02 +00:00
|
|
|
_server.ServeError (_context, http.StatusBadRequest, nil, true)
|
2019-08-13 18:08:16 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-19 12:06:39 +00:00
|
|
|
var _referencesFound bool
|
|
|
|
var _referencesValues [2]uint64
|
|
|
|
var _referencesBuffer []byte
|
2019-08-13 18:08:16 +00:00
|
|
|
|
|
|
|
var _namespaceAndPathSuffixes = [][2]string {
|
|
|
|
{NamespaceFilesContent, ""},
|
|
|
|
{NamespaceFilesContent, "/"},
|
|
|
|
{NamespaceFoldersContent, ""},
|
|
|
|
}
|
|
|
|
|
2021-12-19 12:06:39 +00:00
|
|
|
if !_referencesFound {
|
2019-08-13 18:08:16 +00:00
|
|
|
_loop_1 : for _namespaceAndPathSuffixIndex := range _namespaceAndPathSuffixes {
|
|
|
|
_namespaceAndPathSuffix := _namespaceAndPathSuffixes[_namespaceAndPathSuffixIndex]
|
|
|
|
_namespace := _namespaceAndPathSuffix[0]
|
|
|
|
_pathSuffix := _namespaceAndPathSuffix[1]
|
|
|
|
|
|
|
|
switch {
|
|
|
|
case !_pathIsRoot && !_pathHasSlash :
|
2021-12-16 15:18:02 +00:00
|
|
|
// NOP
|
2019-08-13 18:08:16 +00:00
|
|
|
case _pathSuffix == "/" :
|
|
|
|
continue _loop_1
|
|
|
|
case _pathSuffix == "" :
|
2021-12-16 15:18:02 +00:00
|
|
|
// NOP
|
2019-08-13 18:08:16 +00:00
|
|
|
case _pathSuffix[0] == '/' :
|
|
|
|
_pathSuffix = _pathSuffix[1:]
|
|
|
|
}
|
|
|
|
_pathSuffixHasSlash := (len (_pathSuffix) != 0) && (_pathSuffix[0] == '/')
|
|
|
|
|
2021-12-19 12:06:39 +00:00
|
|
|
if _server.cachedReferences != nil {
|
2021-12-16 17:05:00 +00:00
|
|
|
_key := _keyBufferLarge[:0]
|
2021-12-19 17:19:36 +00:00
|
|
|
_key = append (_key, KeyNamespacePrefix (_namespace), ':')
|
2019-08-13 18:08:16 +00:00
|
|
|
_key = append (_key, _path ...)
|
|
|
|
_key = append (_key, _pathSuffix ...)
|
2021-12-19 12:06:39 +00:00
|
|
|
_referencesValues, _referencesFound = _server.cachedReferences[BytesToString (*NoEscapeBytes (&_key))]
|
2019-08-13 18:08:16 +00:00
|
|
|
} else {
|
2021-12-16 17:05:00 +00:00
|
|
|
_key := _keyBufferLarge[:0]
|
2021-12-19 17:19:36 +00:00
|
|
|
_key = append (_key, KeyNamespacePrefix (_namespace), ':')
|
2019-08-13 18:08:16 +00:00
|
|
|
_key = append (_key, _path ...)
|
|
|
|
_key = append (_key, _pathSuffix ...)
|
|
|
|
if _value, _error := _server.cdbReader.GetWithCdbHash (_key); _error == nil {
|
2021-12-19 12:06:39 +00:00
|
|
|
_referencesBuffer = _value
|
|
|
|
_referencesFound = _value != nil
|
2019-08-13 18:08:16 +00:00
|
|
|
} else {
|
|
|
|
_server.ServeError (_context, http.StatusInternalServerError, _error, false)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-19 12:06:39 +00:00
|
|
|
if _referencesFound {
|
2019-08-13 18:08:16 +00:00
|
|
|
if ((_namespace == NamespaceFoldersContent) || _pathSuffixHasSlash) && (!_pathIsRoot && !_pathHasSlash) {
|
|
|
|
_path = append (_path, '/')
|
|
|
|
_server.ServeRedirect (_context, http.StatusTemporaryRedirect, _path, true)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
break _loop_1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-19 12:06:39 +00:00
|
|
|
if !_referencesFound {
|
2019-08-13 18:08:16 +00:00
|
|
|
if bytes.Equal (StringToBytes ("/favicon.ico"), _path) {
|
|
|
|
_server.ServeStatic (_context, http.StatusOK, FaviconData, FaviconContentType, FaviconContentEncoding, true)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-19 12:06:39 +00:00
|
|
|
if !_referencesFound {
|
2019-08-13 18:08:16 +00:00
|
|
|
_loop_2 : for
|
|
|
|
_pathLimit := bytes.LastIndexByte (_path, '/');
|
|
|
|
_pathLimit >= 0;
|
|
|
|
_pathLimit = bytes.LastIndexByte (_path[: _pathLimit], '/') {
|
|
|
|
|
2021-12-19 12:06:39 +00:00
|
|
|
if _server.cachedReferences != nil {
|
2021-12-16 17:05:00 +00:00
|
|
|
_key := _keyBufferLarge[:0]
|
2021-12-19 17:19:36 +00:00
|
|
|
_key = append (_key, NamespaceFilesContentPrefix, ':')
|
2019-08-13 18:08:16 +00:00
|
|
|
_key = append (_key, _path[: _pathLimit] ...)
|
|
|
|
_key = append (_key, "/*" ...)
|
2021-12-19 12:06:39 +00:00
|
|
|
_referencesValues, _referencesFound = _server.cachedReferences[BytesToString (*NoEscapeBytes (&_key))]
|
2019-08-13 18:08:16 +00:00
|
|
|
} else {
|
2021-12-16 17:05:00 +00:00
|
|
|
_key := _keyBufferLarge[:0]
|
2021-12-19 17:19:36 +00:00
|
|
|
_key = append (_key, NamespaceFilesContentPrefix, ':')
|
2019-08-13 18:08:16 +00:00
|
|
|
_key = append (_key, _path[: _pathLimit] ...)
|
|
|
|
_key = append (_key, "/*" ...)
|
|
|
|
if _value, _error := _server.cdbReader.GetWithCdbHash (_key); _error == nil {
|
2021-12-19 12:06:39 +00:00
|
|
|
_referencesBuffer = _value
|
|
|
|
_referencesFound = _value != nil
|
2019-08-13 18:08:16 +00:00
|
|
|
} else {
|
|
|
|
_server.ServeError (_context, http.StatusInternalServerError, _error, false)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-19 12:06:39 +00:00
|
|
|
if _referencesFound {
|
2019-08-13 18:08:16 +00:00
|
|
|
break _loop_2
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-19 12:06:39 +00:00
|
|
|
if !_referencesFound {
|
2021-12-16 15:28:29 +00:00
|
|
|
if !_server.quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ww] [7416f61d] [http-x..] not found `%s`!\n", *_requestUriString)
|
2021-12-16 15:28:29 +00:00
|
|
|
}
|
2021-12-19 10:34:55 +00:00
|
|
|
_server.ServeError (_context, http.StatusNotFound, nil, false)
|
2019-08-13 18:08:16 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-12-19 12:06:39 +00:00
|
|
|
var _keyMeta, _keyData uint64
|
|
|
|
if _referencesBuffer != nil {
|
|
|
|
if _keyMeta_0, _keyData_0, _error := DecodeKeysPair (_referencesBuffer); _error == nil {
|
|
|
|
_keyMeta = _keyMeta_0
|
|
|
|
_keyData = _keyData_0
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ee] [7ee6c981] [cdb.....] invalid data fingerprints for `%s`!\n", *_requestUriString)
|
2021-12-19 12:06:39 +00:00
|
|
|
_server.ServeError (_context, http.StatusInternalServerError, nil, false)
|
|
|
|
return
|
2021-12-16 15:28:29 +00:00
|
|
|
}
|
2021-12-19 12:06:39 +00:00
|
|
|
} else {
|
|
|
|
_keyMeta = _referencesValues[0]
|
|
|
|
_keyData = _referencesValues[1]
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var _data []byte
|
|
|
|
if _server.cachedDataContent != nil {
|
2021-12-19 12:06:39 +00:00
|
|
|
_data, _ = _server.cachedDataContent[_keyData]
|
2019-08-13 18:08:16 +00:00
|
|
|
} else {
|
2021-12-19 12:06:39 +00:00
|
|
|
_key := _keyBufferSmall[:8]
|
|
|
|
if _error := EncodeKeyToBytes_0 (NamespaceDataContent, _keyData, _key); _error != nil {
|
|
|
|
_server.ServeError (_context, http.StatusInternalServerError, _error, false)
|
|
|
|
return
|
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
if _value, _error := _server.cdbReader.GetWithCdbHash (_key); _error == nil {
|
|
|
|
_data = _value
|
|
|
|
} else {
|
|
|
|
_server.ServeError (_context, http.StatusInternalServerError, _error, false)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if _data == nil {
|
2021-12-16 15:28:29 +00:00
|
|
|
if !_server.quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ee] [0165c193] [cdb.....] missing data content for `%s`!\n", *_requestUriString)
|
2021-12-16 15:28:29 +00:00
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
_server.ServeError (_context, http.StatusInternalServerError, nil, false)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var _dataMetaRaw []byte
|
|
|
|
if _server.cachedDataMeta != nil {
|
2021-12-19 12:06:39 +00:00
|
|
|
_dataMetaRaw, _ = _server.cachedDataMeta[_keyMeta]
|
2019-08-13 18:08:16 +00:00
|
|
|
} else {
|
2021-12-19 12:06:39 +00:00
|
|
|
_key := _keyBufferSmall[:8]
|
|
|
|
if _error := EncodeKeyToBytes_0 (NamespaceDataMetadata, _keyMeta, _key); _error != nil {
|
|
|
|
_server.ServeError (_context, http.StatusInternalServerError, _error, false)
|
|
|
|
return
|
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
if _value, _error := _server.cdbReader.GetWithCdbHash (_key); _error == nil {
|
|
|
|
_dataMetaRaw = _value
|
|
|
|
} else {
|
|
|
|
_server.ServeError (_context, http.StatusInternalServerError, _error, false)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if _dataMetaRaw == nil {
|
2021-12-16 15:28:29 +00:00
|
|
|
if !_server.quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ee] [e8702411] [cdb.....] missing data metadata for `%s`!\n", *_requestUriString)
|
2021-12-16 15:28:29 +00:00
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
_server.ServeError (_context, http.StatusInternalServerError, nil, false)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
_responseStatus := http.StatusOK
|
|
|
|
|
2021-12-19 10:34:55 +00:00
|
|
|
_headersInvalid := false
|
|
|
|
_handleHeader := func (_name []byte, _value []byte) () {
|
2021-11-17 19:35:35 +00:00
|
|
|
if _name[0] != '!' {
|
|
|
|
_responseHeaders.AddBytesKV (_name, _value)
|
|
|
|
} else {
|
|
|
|
switch BytesToString (_name) {
|
|
|
|
case "!Status" :
|
|
|
|
if _value, _error := strconv.Atoi (BytesToString (_value)); _error == nil {
|
|
|
|
if (_value >= 200) && (_value <= 599) {
|
|
|
|
_responseStatus = _value
|
|
|
|
} else {
|
2021-12-16 15:28:29 +00:00
|
|
|
if !_server.quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ee] [c2f7ec36] [cdb.....] invalid data metadata for `%s`!\n", *_requestUriString)
|
2021-12-16 15:28:29 +00:00
|
|
|
}
|
2021-12-19 10:34:55 +00:00
|
|
|
_headersInvalid = true
|
|
|
|
}
|
2021-12-16 15:42:47 +00:00
|
|
|
} else {
|
|
|
|
if !_server.quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ee] [beedae55] [cdb.....] invalid data metadata for `%s`!\n", *_requestUriString)
|
2021-11-17 19:35:35 +00:00
|
|
|
}
|
2021-12-19 10:34:55 +00:00
|
|
|
_headersInvalid = true
|
2021-12-16 15:42:47 +00:00
|
|
|
}
|
2021-11-17 19:35:35 +00:00
|
|
|
default :
|
2021-12-16 15:28:29 +00:00
|
|
|
if !_server.quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ee] [7acc7d90] [cdb.....] invalid data metadata for `%s`!\n", *_requestUriString)
|
2021-12-16 15:28:29 +00:00
|
|
|
}
|
2021-12-19 10:34:55 +00:00
|
|
|
_headersInvalid = true
|
2021-11-17 19:35:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-19 17:19:36 +00:00
|
|
|
if _error := MetadataDecodeBinaryIterate (_dataMetaRaw, _handleHeader); _error != nil {
|
2021-11-17 19:35:35 +00:00
|
|
|
_server.ServeError (_context, http.StatusInternalServerError, _error, false)
|
|
|
|
return
|
|
|
|
}
|
2021-12-19 10:34:55 +00:00
|
|
|
if _headersInvalid {
|
|
|
|
_server.ServeError (_context, http.StatusInternalServerError, nil, false)
|
|
|
|
return
|
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
|
2021-12-16 15:45:16 +00:00
|
|
|
if _server.securityHeadersTls {
|
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("Strict-Transport-Security"), StringToBytes ("max-age=31536000"))
|
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("Content-Security-Policy"), StringToBytes ("upgrade-insecure-requests"))
|
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
if _server.securityHeadersEnabled {
|
2021-12-16 15:45:16 +00:00
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("Referrer-Policy"), StringToBytes ("strict-origin-when-cross-origin"))
|
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("X-Content-Type-Options"), StringToBytes ("nosniff"))
|
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("X-XSS-Protection"), StringToBytes ("1; mode=block"))
|
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("X-Frame-Options"), StringToBytes ("sameorigin"))
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
2021-12-16 21:10:11 +00:00
|
|
|
if _server.http3AltSvc != "" {
|
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("Alt-Svc"), StringToBytes (_server.http3AltSvc))
|
|
|
|
}
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
if _server.debug {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[dd] [b15f3cad] [http-x..] serving for `%s`...\n", *_requestUriString)
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
2021-12-17 23:56:34 +00:00
|
|
|
if _server.dummyDelay != 0 {
|
|
|
|
time.Sleep (_server.dummyDelay)
|
2019-08-15 17:26:22 +00:00
|
|
|
}
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
_response.SetStatusCode (_responseStatus)
|
|
|
|
_response.SetBodyRaw (_data)
|
2021-12-18 20:37:05 +00:00
|
|
|
|
|
|
|
atomic.AddUint64 (&_statsRequestsBody, uint64 (len (_data)))
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (_server *server) ServeStatic (_context *fasthttp.RequestCtx, _status uint, _data []byte, _contentType string, _contentEncoding string, _cache bool) () {
|
|
|
|
|
|
|
|
_response := (*fasthttp.Response) (NoEscape (unsafe.Pointer (&_context.Response)))
|
2021-12-16 13:45:05 +00:00
|
|
|
_responseHeaders := (*fasthttp.ResponseHeader) (NoEscape (unsafe.Pointer (&_response.Header)))
|
2019-08-13 18:08:16 +00:00
|
|
|
|
2021-11-17 19:35:35 +00:00
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("Content-Type"), StringToBytes (_contentType))
|
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("Content-Encoding"), StringToBytes (_contentEncoding))
|
2019-08-13 18:08:16 +00:00
|
|
|
|
|
|
|
if _cache {
|
2021-11-17 19:35:35 +00:00
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("Cache-Control"), StringToBytes ("public, immutable, max-age=3600"))
|
2019-08-13 18:08:16 +00:00
|
|
|
} else {
|
2021-12-17 16:54:25 +00:00
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("Cache-Control"), StringToBytes ("no-store, max-age=0"))
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
2021-12-16 21:10:11 +00:00
|
|
|
if _server.http3AltSvc != "" {
|
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("Alt-Svc"), StringToBytes (_server.http3AltSvc))
|
|
|
|
}
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
_response.SetStatusCode (int (_status))
|
|
|
|
_response.SetBodyRaw (_data)
|
2021-12-18 20:37:05 +00:00
|
|
|
|
|
|
|
atomic.AddUint64 (&_statsRequestsBody, uint64 (len (_data)))
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (_server *server) ServeRedirect (_context *fasthttp.RequestCtx, _status uint, _path []byte, _cache bool) () {
|
|
|
|
|
|
|
|
_response := (*fasthttp.Response) (NoEscape (unsafe.Pointer (&_context.Response)))
|
2021-12-16 13:45:05 +00:00
|
|
|
_responseHeaders := (*fasthttp.ResponseHeader) (NoEscape (unsafe.Pointer (&_response.Header)))
|
2019-08-13 18:08:16 +00:00
|
|
|
|
|
|
|
_responseHeaders.SetCanonical (StringToBytes ("Location"), _path)
|
|
|
|
|
|
|
|
if _cache {
|
2021-11-17 19:35:35 +00:00
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("Cache-Control"), StringToBytes ("public, immutable, max-age=3600"))
|
2019-08-13 18:08:16 +00:00
|
|
|
} else {
|
2021-12-17 16:54:25 +00:00
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("Cache-Control"), StringToBytes ("no-store, max-age=0"))
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
2021-12-16 21:10:11 +00:00
|
|
|
if _server.http3AltSvc != "" {
|
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("Alt-Svc"), StringToBytes (_server.http3AltSvc))
|
|
|
|
}
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
_response.SetStatusCode (int (_status))
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (_server *server) ServeError (_context *fasthttp.RequestCtx, _status uint, _error error, _cache bool) () {
|
|
|
|
|
|
|
|
_response := (*fasthttp.Response) (NoEscape (unsafe.Pointer (&_context.Response)))
|
2021-12-16 13:45:05 +00:00
|
|
|
_responseHeaders := (*fasthttp.ResponseHeader) (NoEscape (unsafe.Pointer (&_response.Header)))
|
2019-08-13 18:08:16 +00:00
|
|
|
|
2021-11-17 19:35:35 +00:00
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("Content-Type"), StringToBytes (ErrorBannerContentType))
|
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("Content-Encoding"), StringToBytes (ErrorBannerContentEncoding))
|
2019-08-13 18:08:16 +00:00
|
|
|
|
|
|
|
if _cache {
|
2021-11-17 19:35:35 +00:00
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("Cache-Control"), StringToBytes ("public, immutable, max-age=3600"))
|
2019-08-13 18:08:16 +00:00
|
|
|
} else {
|
2021-12-17 16:54:25 +00:00
|
|
|
_responseHeaders.AddBytesKV (StringToBytes ("Cache-Control"), StringToBytes ("no-store, max-age=0"))
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if _banner, _bannerFound := ErrorBannersData[_status]; _bannerFound {
|
|
|
|
_response.SetBodyRaw (_banner)
|
2021-12-18 20:37:05 +00:00
|
|
|
atomic.AddUint64 (&_statsRequestsBody, uint64 (len (_banner)))
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_response.SetStatusCode (int (_status))
|
|
|
|
|
2021-12-16 15:28:29 +00:00
|
|
|
if (_error != nil) && !_server.quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
LogError (_error, "[23d6cb35] [http-x..] failed handling request!")
|
2021-12-16 15:28:29 +00:00
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (_server *server) ServeDummy (_context *fasthttp.RequestCtx) () {
|
2021-11-17 19:35:35 +00:00
|
|
|
_server.ServeStatic (_context, http.StatusOK, DummyData, DummyContentType, DummyContentEncoding, false)
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-12-18 09:35:58 +00:00
|
|
|
func (_server *server) ServeWrapped (_context *fasthttp.RequestCtx) () {
|
|
|
|
_context.Response.SetStatusCode (-1)
|
|
|
|
_server.ServeUnwrapped (_context)
|
|
|
|
_status := _context.Response.StatusCode ()
|
|
|
|
_invalid := false
|
|
|
|
switch {
|
|
|
|
case _status < 100 :
|
|
|
|
_invalid = true
|
|
|
|
case _status < 200 :
|
2021-12-18 20:38:39 +00:00
|
|
|
atomic.AddUint64 (&_statsResponses1xx, 1)
|
2021-12-18 09:35:58 +00:00
|
|
|
case _status < 300 :
|
2021-12-18 20:38:39 +00:00
|
|
|
atomic.AddUint64 (&_statsResponses2xx, 1)
|
2021-12-18 09:35:58 +00:00
|
|
|
case _status < 400 :
|
2021-12-18 20:38:39 +00:00
|
|
|
atomic.AddUint64 (&_statsResponses3xx, 1)
|
2021-12-18 09:35:58 +00:00
|
|
|
case _status < 500 :
|
2021-12-18 20:38:39 +00:00
|
|
|
atomic.AddUint64 (&_statsResponses4xx, 1)
|
2021-12-18 09:35:58 +00:00
|
|
|
case _status < 600 :
|
2021-12-18 20:38:39 +00:00
|
|
|
atomic.AddUint64 (&_statsResponses5xx, 1)
|
2021-12-18 09:35:58 +00:00
|
|
|
default :
|
|
|
|
_invalid = true
|
|
|
|
}
|
|
|
|
if _invalid {
|
|
|
|
if !_server.quiet {
|
|
|
|
log.Printf ("[ee] [3db6b217] [http-x..] invalid status code `%d`!\n", _status)
|
|
|
|
}
|
|
|
|
_context.Response.Reset ()
|
|
|
|
_context.Response.SetStatusCode (http.StatusInternalServerError)
|
2021-12-18 20:38:39 +00:00
|
|
|
atomic.AddUint64 (&_statsResponses5xx, 1)
|
2021-12-18 09:35:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (_server *server) ServeFast (_context *fasthttp.RequestCtx) () {
|
|
|
|
|
|
|
|
atomic.AddUint64 (&_statsRequestsFast, 1)
|
|
|
|
atomic.AddUint64 (&_statsRequestsTotal, 1)
|
|
|
|
|
|
|
|
_server.ServeWrapped (_context)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-08-14 18:55:05 +00:00
|
|
|
func (_server *server) ServeHTTP (_response http.ResponseWriter, _request *http.Request) () {
|
|
|
|
|
2021-12-18 09:35:58 +00:00
|
|
|
atomic.AddUint64 (&_statsRequestsSlow, 1)
|
|
|
|
atomic.AddUint64 (&_statsRequestsTotal, 1)
|
|
|
|
|
2021-12-16 13:21:09 +00:00
|
|
|
_requestProtoUnsupported := false
|
|
|
|
switch _request.ProtoMajor {
|
|
|
|
case 1 :
|
|
|
|
_requestProtoUnsupported = _server.http1Disabled || (_request.ProtoMinor < 0) || (_request.ProtoMinor > 1)
|
2021-12-16 21:10:11 +00:00
|
|
|
if _server.debug && !_requestProtoUnsupported {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[dd] [670e36d4] [go-http.] using Go HTTP/1 for `%s`...", _request.URL.Path)
|
2021-12-16 21:10:11 +00:00
|
|
|
}
|
2021-12-16 13:21:09 +00:00
|
|
|
case 2 :
|
|
|
|
_requestProtoUnsupported = _server.http2Disabled || (_request.ProtoMinor != 0)
|
2021-12-16 21:10:11 +00:00
|
|
|
if _server.debug && !_requestProtoUnsupported {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[dd] [524cd64b] [go-http.] using Go HTTP/2 for `%s`...", _request.URL.Path)
|
2021-12-16 21:10:11 +00:00
|
|
|
}
|
|
|
|
case 3 :
|
2021-12-17 23:29:57 +00:00
|
|
|
_requestProtoUnsupported = (_server.httpQuicServer == nil) || (_request.ProtoMinor != 0)
|
2021-12-16 21:10:11 +00:00
|
|
|
if _server.debug && !_requestProtoUnsupported {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[dd] [be95da51] [go-http.] using QUIC HTTP/3 for `%s`...", _request.URL.Path)
|
2021-12-16 21:10:11 +00:00
|
|
|
}
|
2021-12-16 13:21:09 +00:00
|
|
|
default :
|
|
|
|
_requestProtoUnsupported = true
|
|
|
|
}
|
|
|
|
if _requestProtoUnsupported {
|
|
|
|
_request.Close = true
|
2021-12-16 13:41:26 +00:00
|
|
|
_response.WriteHeader (http.StatusHTTPVersionNotSupported)
|
2021-12-16 21:10:11 +00:00
|
|
|
if !_server.quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ww] [4c44e3c0] [go-http.] protocol HTTP/%d not supported for `%s`!", _request.ProtoMajor, _request.URL.Path)
|
2021-12-16 21:10:11 +00:00
|
|
|
}
|
2021-12-18 20:38:39 +00:00
|
|
|
atomic.AddUint64 (&_statsResponses5xx, 1)
|
2021-12-16 13:41:26 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if _server.dummy {
|
2021-12-17 23:56:34 +00:00
|
|
|
if !_server.dummyEmpty {
|
2021-12-18 00:02:46 +00:00
|
|
|
_responseHeaders := NewHttpResponseWriterHeadersBuffer (http.StatusOK)
|
|
|
|
_responseHeaders.IncludeString ("Content-Type", DummyContentType)
|
|
|
|
_responseHeaders.IncludeString ("Content-Encoding", DummyContentEncoding)
|
|
|
|
_responseHeaders.IncludeString ("Cache-Control", "no-store, max-age=0")
|
|
|
|
_responseHeaders.WriteTo (_response)
|
2021-12-17 23:56:34 +00:00
|
|
|
_response.Write (DummyData)
|
2021-12-18 20:37:05 +00:00
|
|
|
atomic.AddUint64 (&_statsRequestsBody, uint64 (len (DummyData)))
|
2021-12-17 23:56:34 +00:00
|
|
|
}
|
|
|
|
if _server.dummyDelay != 0 {
|
|
|
|
time.Sleep (_server.dummyDelay)
|
|
|
|
}
|
2021-12-18 20:38:39 +00:00
|
|
|
atomic.AddUint64 (&_statsResponses2xx, 1)
|
2021-12-16 13:21:09 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-12-16 10:33:14 +00:00
|
|
|
// FIXME: Reimplemnet this to eliminate the HTTP-encode-followed-by-HTTP-decode!
|
|
|
|
|
2021-12-17 15:43:11 +00:00
|
|
|
var _context *fasthttp.RequestCtx
|
|
|
|
if _context_0 := _requestContextsPool.Get (); _context_0 != nil {
|
|
|
|
_context = _context_0.(*fasthttp.RequestCtx)
|
|
|
|
} else {
|
|
|
|
_context = new (fasthttp.RequestCtx)
|
|
|
|
}
|
|
|
|
defer _requestContextsPool.Put (_context)
|
2019-08-14 18:55:05 +00:00
|
|
|
|
2021-12-17 15:22:36 +00:00
|
|
|
_context.Request.Reset ()
|
2019-08-14 18:55:05 +00:00
|
|
|
_context.Request.Header.SetMethod (_request.Method)
|
|
|
|
_context.Request.Header.SetRequestURI (_request.URL.Path)
|
|
|
|
|
2021-12-17 15:22:36 +00:00
|
|
|
_context.Response.Reset ()
|
2019-08-14 18:55:05 +00:00
|
|
|
|
2021-12-18 09:35:58 +00:00
|
|
|
_server.ServeWrapped (_context)
|
2019-08-14 18:55:05 +00:00
|
|
|
|
2021-12-17 20:18:47 +00:00
|
|
|
_responseHeaders := NewHttpResponseWriterHeadersBuffer (_context.Response.Header.StatusCode ())
|
|
|
|
|
2019-08-14 18:55:05 +00:00
|
|
|
_context.Response.Header.VisitAll (
|
2021-12-17 20:18:47 +00:00
|
|
|
func (_key []byte, _value []byte) () {
|
|
|
|
switch BytesToString (_key) {
|
2021-12-17 15:22:36 +00:00
|
|
|
case "Connection", "Content-Length", "Date" :
|
2019-08-14 18:55:05 +00:00
|
|
|
// NOP
|
|
|
|
default :
|
2021-12-18 00:02:46 +00:00
|
|
|
_responseHeaders.IncludeBytes (_key, _value)
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2021-12-17 20:18:47 +00:00
|
|
|
_responseHeaders.WriteTo (_response)
|
2021-12-17 19:58:36 +00:00
|
|
|
|
|
|
|
_response.Write (_context.Response.Body ())
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-17 15:43:11 +00:00
|
|
|
var _requestContextsPool sync.Pool
|
|
|
|
|
|
|
|
|
2019-08-14 18:55:05 +00:00
|
|
|
|
|
|
|
|
2021-12-16 15:40:25 +00:00
|
|
|
func (_server *server) Printf (_format string, _arguments ... interface{}) () {
|
|
|
|
if !_server.quiet {
|
2021-12-17 21:11:35 +00:00
|
|
|
log.Printf ("[ee] [47765179] [fasthttp] | " + _format, _arguments ...)
|
2021-12-16 15:40:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
func Main () () {
|
2021-12-15 17:56:55 +00:00
|
|
|
|
|
|
|
log.SetPrefix (fmt.Sprintf ("[%8d] ", os.Getpid ()))
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
Main_0 (main_0)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-16 12:37:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
func main_0 () (error) {
|
|
|
|
|
|
|
|
|
2021-12-16 12:37:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
var _bindPlain1 string
|
|
|
|
var _bindPlain2 string
|
|
|
|
var _bindTls1 string
|
2019-08-15 06:46:15 +00:00
|
|
|
var _bindTls2 string
|
2021-12-16 21:10:11 +00:00
|
|
|
var _bindQuic string
|
2021-12-16 13:21:09 +00:00
|
|
|
var _http1Disabled bool
|
|
|
|
var _http2Disabled bool
|
2021-12-16 21:10:11 +00:00
|
|
|
var _http3AltSvc string
|
2019-08-15 12:00:45 +00:00
|
|
|
var _tlsPrivate string
|
|
|
|
var _tlsPublic string
|
2019-08-13 18:08:16 +00:00
|
|
|
var _archivePath string
|
|
|
|
var _archiveInmem bool
|
|
|
|
var _archiveMmap bool
|
|
|
|
var _archivePreload bool
|
|
|
|
var _indexPaths bool
|
|
|
|
var _indexDataMeta bool
|
|
|
|
var _indexDataContent bool
|
|
|
|
var _securityHeadersEnabled bool
|
|
|
|
var _securityHeadersTls bool
|
|
|
|
var _timeoutDisabled bool
|
|
|
|
var _processes uint
|
|
|
|
var _threads uint
|
|
|
|
var _slave uint
|
2019-08-14 18:55:05 +00:00
|
|
|
var _quiet bool
|
2021-12-19 12:06:39 +00:00
|
|
|
var _report bool
|
|
|
|
var _debug bool
|
2019-08-13 18:08:16 +00:00
|
|
|
var _dummy bool
|
2021-12-17 23:56:34 +00:00
|
|
|
var _dummyEmpty bool
|
|
|
|
var _dummyDelay time.Duration
|
2021-12-16 11:56:27 +00:00
|
|
|
var _profileCpu string
|
|
|
|
var _profileMem string
|
|
|
|
var _limitMemory uint
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
var _isFirst bool
|
|
|
|
var _isMaster bool
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
_flags := flag.NewFlagSet ("kawipiko-server", flag.ContinueOnError)
|
|
|
|
|
|
|
|
_flags.Usage = func () () {
|
2021-12-16 11:32:05 +00:00
|
|
|
fmt.Fprintf (os.Stderr, "%s", usageText)
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
_bindPlain1_0 := _flags.String ("bind", "", "")
|
|
|
|
_bindPlain2_0 := _flags.String ("bind-2", "", "")
|
|
|
|
_bindTls1_0 := _flags.String ("bind-tls", "", "")
|
2019-08-15 06:46:15 +00:00
|
|
|
_bindTls2_0 := _flags.String ("bind-tls-2", "", "")
|
2021-12-16 21:10:11 +00:00
|
|
|
_bindQuic_0 := _flags.String ("bind-quic", "", "")
|
2021-12-16 13:21:09 +00:00
|
|
|
_http1Disabled_0 := _flags.Bool ("http1-disable", false, "")
|
|
|
|
_http2Disabled_0 := _flags.Bool ("http2-disable", false, "")
|
2021-12-16 21:10:11 +00:00
|
|
|
_http3AltSvc_0 := _flags.String ("http3-alt-svc", "", "")
|
2019-08-13 18:08:16 +00:00
|
|
|
_archivePath_0 := _flags.String ("archive", "", "")
|
|
|
|
_archiveInmem_0 := _flags.Bool ("archive-inmem", false, "")
|
|
|
|
_archiveMmap_0 := _flags.Bool ("archive-mmap", false, "")
|
|
|
|
_archivePreload_0 := _flags.Bool ("archive-preload", false, "")
|
|
|
|
_indexAll_0 := _flags.Bool ("index-all", false, "")
|
|
|
|
_indexPaths_0 := _flags.Bool ("index-paths", false, "")
|
|
|
|
_indexDataMeta_0 := _flags.Bool ("index-data-meta", false, "")
|
|
|
|
_indexDataContent_0 := _flags.Bool ("index-data-content", false, "")
|
|
|
|
_timeoutDisabled_0 := _flags.Bool ("timeout-disable", false, "")
|
|
|
|
_securityHeadersTls_0 := _flags.Bool ("security-headers-tls", false, "")
|
|
|
|
_securityHeadersDisabled_0 := _flags.Bool ("security-headers-disable", false, "")
|
2019-08-15 12:00:45 +00:00
|
|
|
_tlsPrivate_0 := _flags.String ("tls-private", "", "")
|
|
|
|
_tlsPublic_0 := _flags.String ("tls-public", "", "")
|
|
|
|
_tlsBundle_0 := _flags.String ("tls-bundle", "", "")
|
2019-08-13 18:08:16 +00:00
|
|
|
_processes_0 := _flags.Uint ("processes", 0, "")
|
|
|
|
_threads_0 := _flags.Uint ("threads", 0, "")
|
|
|
|
_slave_0 := _flags.Uint ("slave", 0, "")
|
2019-08-14 18:55:05 +00:00
|
|
|
_quiet_0 := _flags.Bool ("quiet", false, "")
|
2021-12-19 12:06:39 +00:00
|
|
|
_report_0 := _flags.Bool ("report", false, "")
|
|
|
|
_debug_0 := _flags.Bool ("debug", false, "")
|
2019-08-13 18:08:16 +00:00
|
|
|
_dummy_0 := _flags.Bool ("dummy", false, "")
|
2021-12-17 23:56:34 +00:00
|
|
|
_dummyEmpty_0 := _flags.Bool ("dummy-empty", false, "")
|
|
|
|
_dummyDelay_0 := _flags.Duration ("dummy-delay", 0, "")
|
2021-12-16 11:56:27 +00:00
|
|
|
_profileCpu_0 := _flags.String ("profile-cpu", "", "")
|
|
|
|
_profileMem_0 := _flags.String ("profile-mem", "", "")
|
|
|
|
_limitMemory_0 := _flags.Uint ("limit-memory", 0, "")
|
2019-08-13 18:08:16 +00:00
|
|
|
|
|
|
|
FlagsParse (_flags, 0, 0)
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
_bindPlain1 = *_bindPlain1_0
|
|
|
|
_bindPlain2 = *_bindPlain2_0
|
|
|
|
_bindTls1 = *_bindTls1_0
|
2019-08-15 06:46:15 +00:00
|
|
|
_bindTls2 = *_bindTls2_0
|
2021-12-16 21:10:11 +00:00
|
|
|
_bindQuic = *_bindQuic_0
|
2021-12-16 13:21:09 +00:00
|
|
|
_http1Disabled = *_http1Disabled_0
|
|
|
|
_http2Disabled = *_http2Disabled_0
|
2021-12-16 21:10:11 +00:00
|
|
|
_http3AltSvc = *_http3AltSvc_0
|
2019-08-13 18:08:16 +00:00
|
|
|
_archivePath = *_archivePath_0
|
|
|
|
_archiveInmem = *_archiveInmem_0
|
|
|
|
_archiveMmap = *_archiveMmap_0
|
|
|
|
_archivePreload = *_archivePreload_0
|
|
|
|
_indexAll := *_indexAll_0
|
|
|
|
_indexPaths = _indexAll || *_indexPaths_0
|
|
|
|
_indexDataMeta = _indexAll || *_indexDataMeta_0
|
|
|
|
_indexDataContent = _indexAll || *_indexDataContent_0
|
|
|
|
_securityHeadersTls = *_securityHeadersTls_0
|
|
|
|
_securityHeadersEnabled = ! *_securityHeadersDisabled_0
|
|
|
|
_timeoutDisabled = *_timeoutDisabled_0
|
|
|
|
_processes = *_processes_0
|
|
|
|
_threads = *_threads_0
|
|
|
|
_slave = *_slave_0
|
2021-12-19 12:06:39 +00:00
|
|
|
_quiet = *_quiet_0 && !*_debug_0
|
|
|
|
_report = *_report_0
|
2019-08-13 18:08:16 +00:00
|
|
|
_debug = *_debug_0
|
|
|
|
_dummy = *_dummy_0
|
2021-12-17 23:56:34 +00:00
|
|
|
_dummyEmpty = *_dummyEmpty_0
|
|
|
|
_dummyDelay = *_dummyDelay_0
|
2019-08-13 18:08:16 +00:00
|
|
|
_profileCpu = *_profileCpu_0
|
|
|
|
_profileMem = *_profileMem_0
|
2021-12-16 11:56:27 +00:00
|
|
|
_limitMemory = *_limitMemory_0
|
2019-08-13 18:08:16 +00:00
|
|
|
|
|
|
|
if _slave == 0 {
|
|
|
|
_isMaster = true
|
|
|
|
}
|
|
|
|
if _slave <= 1 {
|
|
|
|
_isFirst = true
|
|
|
|
}
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
if (_bindPlain1 == "") && (_bindPlain2 == "") && (_bindTls1 == "") && (_bindTls2 == "") && (_bindQuic == "") {
|
2019-08-13 18:08:16 +00:00
|
|
|
AbortError (nil, "[6edd9512] expected bind address argument!")
|
|
|
|
}
|
2019-08-15 12:00:45 +00:00
|
|
|
if (*_tlsBundle_0 != "") && ((*_tlsPrivate_0 != "") || (*_tlsPublic_0 != "")) {
|
|
|
|
AbortError (nil, "[717f5f84] TLS bundle and TLS private/public are mutually exclusive!")
|
|
|
|
}
|
|
|
|
if (*_tlsBundle_0 != "") {
|
|
|
|
_tlsPrivate = *_tlsBundle_0
|
|
|
|
_tlsPublic = *_tlsBundle_0
|
|
|
|
} else {
|
|
|
|
_tlsPrivate = *_tlsPrivate_0
|
|
|
|
_tlsPublic = *_tlsPublic_0
|
|
|
|
}
|
|
|
|
if ((_tlsPrivate != "") && (_tlsPublic == "")) || ((_tlsPublic != "") && (_tlsPrivate == "")) {
|
|
|
|
AbortError (nil, "[6e5b42e4] TLS private/public must be specified together!")
|
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if ((_tlsPrivate != "") || (_tlsPublic != "")) && ((_bindTls1 == "") && (_bindTls2 == "") && (_bindQuic == "")) {
|
2019-08-15 12:00:45 +00:00
|
|
|
AbortError (nil, "[4e31f251] TLS certificate specified, but TLS not enabled!")
|
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
if _http1Disabled && ((_bindPlain1 != "") || (_bindPlain2 != "")) {
|
|
|
|
AbortError (nil, "[bd16d596] HTTP/1 is mandatory with `--bind` or `--bind-2`!")
|
2021-12-16 13:21:09 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _http1Disabled && (_bindTls1 != "") {
|
2021-12-16 13:21:09 +00:00
|
|
|
AbortError (nil, "[f498816a] HTTP/1 is mandatory with `--bind-tls`!")
|
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _http1Disabled && (_bindPlain1 == "") && (_bindPlain2 == "") && (_bindTls1 == "") && (_bindTls2 == "") {
|
2021-12-17 15:01:15 +00:00
|
|
|
log.Printf ("[ww] [6bc56c8e] HTTP/1 is not available!\n")
|
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _http2Disabled && (_bindTls1 == "") && (_bindTls2 == "") {
|
2021-12-17 15:01:15 +00:00
|
|
|
log.Printf ("[ww] [1ed4864c] HTTP/2 is not available!\n")
|
2021-12-16 13:21:09 +00:00
|
|
|
}
|
2021-12-16 21:10:11 +00:00
|
|
|
if (_http3AltSvc != "") && (_bindQuic == "") {
|
2021-12-17 15:01:15 +00:00
|
|
|
log.Printf ("[ww] [93510d2a] HTTP/3 Alt-Svc is not available!\n")
|
2021-12-16 21:10:11 +00:00
|
|
|
}
|
|
|
|
if (_http3AltSvc == "") && (_bindQuic != "") {
|
2021-12-17 15:01:15 +00:00
|
|
|
log.Printf ("[ww] [225bda04] HTTP/3 Alt-Svc is mandatory with QUIC!\n")
|
2021-12-16 21:10:11 +00:00
|
|
|
}
|
|
|
|
if (_http3AltSvc != "") {
|
|
|
|
if strings.HasPrefix (_http3AltSvc, "h3=") {
|
|
|
|
// NOP
|
|
|
|
} else if _host, _port, _error := net.SplitHostPort (_http3AltSvc); _error == nil {
|
|
|
|
_endpoint := net.JoinHostPort (_host, _port)
|
2021-12-16 21:36:29 +00:00
|
|
|
_http3AltSvc = fmt.Sprintf ("h3=\"%s\", h3-29=\"%s\"", _endpoint, _endpoint)
|
2021-12-16 21:10:11 +00:00
|
|
|
} else {
|
|
|
|
AbortError (nil, "[1a5476b1] HTTP/3 Alt-Svc is invalid!")
|
|
|
|
}
|
2021-12-17 19:58:36 +00:00
|
|
|
CanonicalHeaderValueRegister (_http3AltSvc)
|
2021-12-16 21:10:11 +00:00
|
|
|
}
|
2021-12-16 13:21:09 +00:00
|
|
|
|
2021-12-17 23:56:34 +00:00
|
|
|
_dummy = _dummy || _dummyEmpty
|
2019-08-13 18:08:16 +00:00
|
|
|
if !_dummy {
|
|
|
|
if _archivePath == "" {
|
|
|
|
AbortError (nil, "[eefe1a38] expected archive file argument!")
|
|
|
|
}
|
|
|
|
if _archiveInmem && _archiveMmap {
|
|
|
|
AbortError (nil, "[a2101041] archive 'memory-loaded' and 'memory-mapped' are mutually exclusive!")
|
|
|
|
}
|
|
|
|
if _archiveInmem && _archivePreload {
|
|
|
|
log.Printf ("[ww] [3e8a40e4] archive 'memory-loaded' implies preloading!\n")
|
|
|
|
_archivePreload = false
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if _isMaster {
|
|
|
|
log.Printf ("[ww] [8e014192] running in dummy mode; all archive related arguments are ignored!\n")
|
|
|
|
}
|
|
|
|
_archivePath = ""
|
|
|
|
_archiveInmem = false
|
|
|
|
_archiveMmap = false
|
|
|
|
_archivePreload = false
|
|
|
|
_indexPaths = false
|
|
|
|
_indexDataMeta = false
|
|
|
|
_indexDataContent = false
|
|
|
|
}
|
2021-12-17 23:56:34 +00:00
|
|
|
if !_dummy && (_dummyDelay != 0) {
|
2019-08-15 17:26:22 +00:00
|
|
|
if _isMaster {
|
2021-12-17 23:56:34 +00:00
|
|
|
log.Printf ("[ww] [e9296c03] running with a response delay of `%s`!\n", _dummyDelay)
|
2019-08-15 17:26:22 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
|
|
|
|
if _processes < 1 {
|
|
|
|
_processes = 1
|
|
|
|
}
|
|
|
|
if _threads < 1 {
|
|
|
|
_threads = 1
|
|
|
|
}
|
|
|
|
|
|
|
|
if _processes > 1024 {
|
|
|
|
AbortError (nil, "[45736c1d] maximum number of allowed processes is 1024!")
|
|
|
|
}
|
|
|
|
if _threads > 1024 {
|
|
|
|
AbortError (nil, "[c5df3c8d] maximum number of allowed threads is 1024!")
|
|
|
|
}
|
|
|
|
if (_processes * _threads) > 1024 {
|
|
|
|
AbortError (nil, "[b0177488] maximum number of allowed threads in total is 1024!")
|
|
|
|
}
|
2021-12-16 11:56:27 +00:00
|
|
|
|
2021-12-16 13:21:09 +00:00
|
|
|
if (_limitMemory != 0) && ((_limitMemory > (16 * 1024)) || (_limitMemory < 128)) {
|
2021-12-16 11:56:27 +00:00
|
|
|
AbortError (nil, "[2781f54c] maximum memory limit is between 128 and 16384 MiB!")
|
|
|
|
}
|
2021-12-16 21:10:11 +00:00
|
|
|
|
|
|
|
if (_processes > 1) && ((_profileCpu != "") || (_profileMem != "")) {
|
|
|
|
AbortError (nil, "[cd18d250] multi-process and profiling are mutually exclusive!")
|
|
|
|
}
|
|
|
|
if (_processes > 1) && (_bindQuic != "") {
|
|
|
|
AbortError (nil, "[d6db77ba] QUIC is only available with a single process!")
|
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-16 12:37:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
runtime.GOMAXPROCS (int (_threads))
|
|
|
|
|
|
|
|
debug.SetGCPercent (50)
|
|
|
|
debug.SetMaxThreads (int (128 * (_threads / 64 + 1)))
|
2021-12-18 00:02:46 +00:00
|
|
|
debug.SetMaxStack (32 * 1024)
|
2019-08-13 18:08:16 +00:00
|
|
|
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpReduceMemory := false
|
2019-08-13 18:08:16 +00:00
|
|
|
|
2021-12-16 12:37:12 +00:00
|
|
|
|
2021-12-16 11:56:27 +00:00
|
|
|
if _limitMemory > 0 {
|
2021-12-16 12:37:12 +00:00
|
|
|
if !_quiet && _isMaster {
|
2021-12-16 15:17:42 +00:00
|
|
|
log.Printf ("[ii] [2c130d70] limiting memory to %d MiB;\n", _limitMemory)
|
2021-12-16 12:37:12 +00:00
|
|
|
}
|
2021-12-21 19:32:40 +00:00
|
|
|
if _error := setrlimit (_limitMemory); _error != nil {
|
|
|
|
AbortError (_error, "[4da96378] failed to configure memory limit!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-16 12:37:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
if _processes > 1 {
|
|
|
|
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [06f8c944] [master..] sub-processes starting (`%d` processes with `%d` threads each)...\n", _processes, _threads)
|
2019-08-13 18:08:16 +00:00
|
|
|
|
|
|
|
_processesJoin := & sync.WaitGroup {}
|
|
|
|
|
|
|
|
_processesPid := make ([]*os.Process, _processes)
|
|
|
|
|
|
|
|
_processName := os.Args[0]
|
|
|
|
_processArguments := make ([]string, 0, len (os.Args))
|
2021-12-17 23:29:57 +00:00
|
|
|
if _bindPlain1 != "" {
|
|
|
|
_processArguments = append (_processArguments, "--bind", _bindPlain1)
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _bindPlain2 != "" {
|
|
|
|
_processArguments = append (_processArguments, "--bind-2", _bindPlain2)
|
|
|
|
}
|
|
|
|
if _bindTls1 != "" {
|
|
|
|
_processArguments = append (_processArguments, "--bind-tls", _bindTls1)
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
2019-08-15 06:46:15 +00:00
|
|
|
if _bindTls2 != "" {
|
|
|
|
_processArguments = append (_processArguments, "--bind-tls-2", _bindTls2)
|
|
|
|
}
|
2021-12-16 13:21:09 +00:00
|
|
|
if _http1Disabled {
|
|
|
|
_processArguments = append (_processArguments, "--http1-disabled")
|
|
|
|
}
|
|
|
|
if _http2Disabled {
|
|
|
|
_processArguments = append (_processArguments, "--http2-disabled")
|
|
|
|
}
|
2021-12-16 21:10:11 +00:00
|
|
|
if _http3AltSvc != "" {
|
|
|
|
_processArguments = append (_processArguments, "--http3-alt-svc", _http3AltSvc)
|
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
if _archivePath != "" {
|
|
|
|
_processArguments = append (_processArguments, "--archive", _archivePath)
|
|
|
|
}
|
|
|
|
if _archiveInmem {
|
|
|
|
_processArguments = append (_processArguments, "--archive-inmem")
|
|
|
|
}
|
|
|
|
if _archiveMmap {
|
|
|
|
_processArguments = append (_processArguments, "--archive-mmap")
|
|
|
|
}
|
|
|
|
if _archivePreload {
|
|
|
|
_processArguments = append (_processArguments, "--archive-preload")
|
|
|
|
}
|
|
|
|
if _indexPaths {
|
|
|
|
_processArguments = append (_processArguments, "--index-paths")
|
|
|
|
}
|
|
|
|
if _indexDataMeta {
|
|
|
|
_processArguments = append (_processArguments, "--index-data-meta")
|
|
|
|
}
|
|
|
|
if _indexDataContent {
|
|
|
|
_processArguments = append (_processArguments, "--index-data-content")
|
|
|
|
}
|
|
|
|
if _securityHeadersTls {
|
|
|
|
_processArguments = append (_processArguments, "--security-headers-tls")
|
|
|
|
}
|
|
|
|
if !_securityHeadersEnabled {
|
|
|
|
_processArguments = append (_processArguments, "--security-headers-disable")
|
|
|
|
}
|
2019-08-15 12:00:45 +00:00
|
|
|
if _tlsPrivate != "" {
|
2021-12-16 12:37:12 +00:00
|
|
|
_processArguments = append (_processArguments, "--tls-private", _tlsPrivate)
|
2019-08-15 12:00:45 +00:00
|
|
|
}
|
|
|
|
if _tlsPublic != "" {
|
2021-12-16 12:37:12 +00:00
|
|
|
_processArguments = append (_processArguments, "--tls-public", _tlsPublic)
|
2019-08-15 12:00:45 +00:00
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
if _timeoutDisabled {
|
|
|
|
_processArguments = append (_processArguments, "--timeout-disable")
|
|
|
|
}
|
2021-12-16 12:37:12 +00:00
|
|
|
if _limitMemory != 0 {
|
|
|
|
_processArguments = append (_processArguments, "--limit-memory", fmt.Sprintf ("%d", _limitMemory))
|
|
|
|
}
|
2019-08-14 18:55:05 +00:00
|
|
|
if _quiet {
|
|
|
|
_processArguments = append (_processArguments, "--quiet")
|
|
|
|
}
|
2021-12-19 12:06:39 +00:00
|
|
|
if _report {
|
|
|
|
_processArguments = append (_processArguments, "--report")
|
|
|
|
}
|
2021-12-16 15:40:25 +00:00
|
|
|
if _debug {
|
|
|
|
_processArguments = append (_processArguments, "--debug")
|
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
if _dummy {
|
|
|
|
_processArguments = append (_processArguments, "--dummy")
|
|
|
|
}
|
2021-12-17 23:56:34 +00:00
|
|
|
if _dummyEmpty {
|
|
|
|
_processArguments = append (_processArguments, "--dummy-empty")
|
|
|
|
}
|
|
|
|
if _dummyDelay != 0 {
|
|
|
|
_processArguments = append (_processArguments, "--dummy-delay", fmt.Sprintf ("%s", _dummyDelay))
|
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
_processArguments = append (_processArguments, "--threads", fmt.Sprintf ("%d", _threads))
|
|
|
|
|
|
|
|
_processAttributes := & os.ProcAttr {
|
|
|
|
Env : []string {},
|
|
|
|
Files : []*os.File {
|
|
|
|
os.Stdin,
|
|
|
|
os.Stdout,
|
|
|
|
os.Stderr,
|
|
|
|
},
|
|
|
|
Sys : nil,
|
|
|
|
}
|
|
|
|
|
|
|
|
for _processIndex, _ := range _processesPid {
|
|
|
|
_processArguments := append ([]string { _processName, "--slave", fmt.Sprintf ("%d", _processIndex + 1) }, _processArguments ...)
|
|
|
|
if _processPid, _error := os.StartProcess (_processName, _processArguments, _processAttributes); _error == nil {
|
|
|
|
_processesJoin.Add (1)
|
|
|
|
_processesPid[_processIndex] = _processPid
|
2019-08-14 18:55:05 +00:00
|
|
|
if !_quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [63cb22f8] [master..] sub-process `%d` started (with `%d` threads);\n", _processPid.Pid, _threads)
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
go func (_index int, _processPid *os.Process) () {
|
|
|
|
if _processStatus, _error := _processPid.Wait (); _error == nil {
|
|
|
|
if _processStatus.Success () {
|
|
|
|
if _debug {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [66b60b81] [master..] sub-process `%d` succeeded;\n", _processPid.Pid)
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ww] [5d25046b] [master..] sub-process `%d` failed: `%s`; ignoring!\n", _processPid.Pid, _processStatus)
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
LogError (_error, fmt.Sprintf ("[f1bfc927] [master..] failed waiting for sub-process `%d`; ignoring!", _processPid.Pid))
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
_processesPid[_processIndex] = nil
|
|
|
|
_processesJoin.Done ()
|
|
|
|
} (_processIndex, _processPid)
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
LogError (_error, "[8892b34d] [master..] failed starting sub-process; ignoring!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
_signals := make (chan os.Signal, 32)
|
|
|
|
signal.Notify (_signals, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
go func () () {
|
|
|
|
for {
|
|
|
|
_signal := <- _signals
|
|
|
|
if _debug {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [a9243ecb] [master..] signaling sub-processes...\n")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
for _, _processPid := range _processesPid {
|
|
|
|
if _processPid != nil {
|
|
|
|
if _error := _processPid.Signal (_signal); _error != nil {
|
2021-12-17 21:27:55 +00:00
|
|
|
LogError (_error, fmt.Sprintf ("[ab681164] [master..] failed signaling sub-process `%d`; ignoring!", _processPid.Pid))
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} ()
|
|
|
|
}
|
|
|
|
|
|
|
|
_processesJoin.Wait ()
|
|
|
|
|
2019-08-14 18:55:05 +00:00
|
|
|
if !_quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [b949bafc] [master..] sub-processes terminated;\n")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if _isMaster {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [6602a54a] [master..] starting (with `%d` threads)...\n", _threads)
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-16 12:37:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
var _cdbReader *cdb.CDB
|
|
|
|
if _archivePath != "" {
|
|
|
|
|
2019-08-14 18:55:05 +00:00
|
|
|
if !_quiet && (_debug || _isFirst) {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [3b788396] [cdb.....] opening archive file `%s`...\n", _archivePath)
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var _cdbFile *os.File
|
|
|
|
if _cdbFile_0, _error := os.Open (_archivePath); _error == nil {
|
|
|
|
_cdbFile = _cdbFile_0
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[9e0b5ed3] [cdb.....] failed opening archive file!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var _cdbFileSize int
|
|
|
|
{
|
|
|
|
var _cdbFileSize_0 int64
|
|
|
|
if _cdbFileStat, _error := _cdbFile.Stat (); _error == nil {
|
|
|
|
_cdbFileSize_0 = _cdbFileStat.Size ()
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[0ccf0a3b] [cdb.....] failed opening archive file!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
if _cdbFileSize_0 < 1024 {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (nil, "[6635a2a8] [cdb.....] failed opening archive: file is too small (or empty)!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
2021-11-17 21:08:49 +00:00
|
|
|
if _cdbFileSize_0 >= (4 * 1024 * 1024 * 1024) {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (nil, "[545bf6ce] [cdb.....] failed opening archive: file is too large!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
_cdbFileSize = int (_cdbFileSize_0)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _archivePreload {
|
2019-08-14 18:55:05 +00:00
|
|
|
if !_quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [13f4ebf7] [cdb.....] preloading archive file...\n")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
_buffer := [16 * 1024]byte {}
|
|
|
|
_loop : for {
|
|
|
|
switch _, _error := _cdbFile.Read (_buffer[:]); _error {
|
|
|
|
case io.EOF :
|
|
|
|
break _loop
|
|
|
|
case nil :
|
|
|
|
continue _loop
|
|
|
|
default :
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[a1c3b922] [cdb.....] failed preloading archive file...")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if _archiveInmem || _archiveMmap {
|
|
|
|
|
|
|
|
var _cdbData []byte
|
|
|
|
|
|
|
|
if _archiveInmem {
|
|
|
|
|
|
|
|
if _debug {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [216e584b] [cdb.....] opening memory-loaded archive...\n")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_cdbData = make ([]byte, _cdbFileSize)
|
|
|
|
if _, _error := io.ReadFull (_cdbFile, _cdbData); _error != nil {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[73039784] [cdb.....] failed loading archive file!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} else if _archiveMmap {
|
|
|
|
|
|
|
|
if _debug {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [f47fae8a] [cdb.....] opening memory-mapped archive...\n")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if _cdbData_0, _error := syscall.Mmap (int (_cdbFile.Fd ()), 0, int (_cdbFileSize), syscall.PROT_READ, syscall.MAP_SHARED); _error == nil {
|
|
|
|
_cdbData = _cdbData_0
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[c0e2632c] [cdb.....] failed mapping archive file!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if _archivePreload {
|
|
|
|
if _debug {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [d96b06c9] [cdb.....] preloading memory-loaded archive...\n")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
_buffer := [16 * 1024]byte {}
|
|
|
|
_bufferOffset := 0
|
|
|
|
for {
|
|
|
|
if _bufferOffset == _cdbFileSize {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
_bufferOffset += copy (_buffer[:], _cdbData[_bufferOffset:])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2021-12-16 12:37:12 +00:00
|
|
|
panic ("[e4fffcd8]")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if _error := _cdbFile.Close (); _error != nil {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[5e0449c2] [cdb.....] failed closing archive file!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if _cdbReader_0, _error := cdb.NewFromBufferWithHasher (_cdbData, nil); _error == nil {
|
|
|
|
_cdbReader = _cdbReader_0
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[27e4813e] [cdb.....] failed opening archive!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
2019-08-14 18:55:05 +00:00
|
|
|
if !_quiet && (_debug || _isFirst) {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ww] [dd697a66] [cdb.....] using `read`-based archive (with significant performance impact)!\n")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if _cdbReader_0, _error := cdb.NewFromReaderWithHasher (_cdbFile, nil); _error == nil {
|
|
|
|
_cdbReader = _cdbReader_0
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[35832022] [cdb.....] failed opening archive!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if _schemaVersion, _error := _cdbReader.GetWithCdbHash ([]byte (NamespaceSchemaVersion)); _error == nil {
|
|
|
|
if _schemaVersion == nil {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (nil, "[09316866] [cdb.....] missing archive schema version!")
|
2019-08-13 18:08:16 +00:00
|
|
|
} else if string (_schemaVersion) != CurrentSchemaVersion {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (nil, "[e6482cf7] [cdb.....] invalid archive schema version!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[87cae197] [cdb.....] failed opening archive!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-16 12:37:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-12-19 12:06:39 +00:00
|
|
|
var _cachedReferences map[string][2]uint64
|
2019-08-13 18:08:16 +00:00
|
|
|
if _indexPaths {
|
2021-12-19 12:06:39 +00:00
|
|
|
_cachedReferences = make (map[string][2]uint64, 128 * 1024)
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
2021-12-19 12:06:39 +00:00
|
|
|
var _cachedDataMeta map[uint64][]byte
|
2019-08-13 18:08:16 +00:00
|
|
|
if _indexDataMeta {
|
2021-12-19 12:06:39 +00:00
|
|
|
_cachedDataMeta = make (map[uint64][]byte, 128 * 1024)
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
2021-12-19 12:06:39 +00:00
|
|
|
var _cachedDataContent map[uint64][]byte
|
2019-08-13 18:08:16 +00:00
|
|
|
if _indexDataContent {
|
2021-12-19 12:06:39 +00:00
|
|
|
_cachedDataContent = make (map[uint64][]byte, 128 * 1024)
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if _indexPaths || _indexDataMeta || _indexDataContent {
|
2019-08-14 18:55:05 +00:00
|
|
|
if !_quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [fa5338fd] [cdb.....] indexing archive...\n")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
2021-12-19 12:06:39 +00:00
|
|
|
var _filesIndexKey string
|
|
|
|
if _key_0, _error := PrepareKeyToString (NamespaceFilesIndex, 1); _error == nil {
|
|
|
|
_filesIndexKey = _key_0
|
|
|
|
} else {
|
|
|
|
AbortError (_error, "[5289ee67] [cdb.....] failed indexing archive!")
|
|
|
|
}
|
|
|
|
if _filesIndex, _error := _cdbReader.GetWithCdbHash (StringToBytes (_filesIndexKey)); _error == nil {
|
2019-08-13 18:08:16 +00:00
|
|
|
if _filesIndex != nil {
|
|
|
|
_keyBuffer := [1024]byte {}
|
|
|
|
for {
|
|
|
|
_offset := bytes.IndexByte (_filesIndex, '\n')
|
|
|
|
if _offset == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if _offset == -1 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
_filePath := _filesIndex[: _offset]
|
|
|
|
_filesIndex = _filesIndex[_offset + 1 :]
|
2021-12-19 12:06:39 +00:00
|
|
|
var _fileReferences []byte
|
2019-08-13 18:08:16 +00:00
|
|
|
{
|
|
|
|
_key := _keyBuffer[:0]
|
2021-12-19 17:19:36 +00:00
|
|
|
_key = append (_key, NamespaceFilesContentPrefix, ':')
|
2019-08-13 18:08:16 +00:00
|
|
|
_key = append (_key, _filePath ...)
|
2021-12-19 12:06:39 +00:00
|
|
|
if _references_0, _error := _cdbReader.GetWithCdbHash (_key); _error == nil {
|
|
|
|
if _references_0 != nil {
|
|
|
|
_fileReferences = _references_0
|
2019-08-13 18:08:16 +00:00
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[460b3cf1] [cdb.....] failed indexing archive!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[216f2075] [cdb.....] failed indexing archive!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-19 12:06:39 +00:00
|
|
|
var _keyDataMeta, _keyDataContent uint64
|
|
|
|
if _keyDataMeta_0, _keyDataContent_0, _error := DecodeKeysPair (_fileReferences); _error == nil {
|
|
|
|
_keyDataMeta = _keyDataMeta_0
|
|
|
|
_keyDataContent = _keyDataContent_0
|
|
|
|
} else {
|
|
|
|
AbortError (_error, "[7d1a366f] [cdb.....] failed indexing archive!")
|
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
if _indexPaths {
|
2021-12-19 17:19:36 +00:00
|
|
|
_key := _keyBuffer[:0]
|
|
|
|
_key = append (_key, NamespaceFilesContentPrefix, ':')
|
|
|
|
_key = append (_key, _filePath ...)
|
|
|
|
_cachedReferences[string (_key)] = [2]uint64 { _keyDataMeta, _keyDataContent }
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
if _indexDataMeta {
|
2021-12-19 12:06:39 +00:00
|
|
|
if _, _wasCached := _cachedDataMeta[_keyDataMeta]; !_wasCached {
|
|
|
|
_key := _keyBuffer[:8]
|
|
|
|
if _error := EncodeKeyToBytes_0 (NamespaceDataMetadata, _keyDataMeta, _key); _error != nil {
|
|
|
|
AbortError (_error, "[b8cd07f4] [cdb.....] failed indexing archive!")
|
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
if _dataMeta, _error := _cdbReader.GetWithCdbHash (_key); _error == nil {
|
|
|
|
if _dataMeta != nil {
|
2021-12-19 12:06:39 +00:00
|
|
|
_cachedDataMeta[_keyDataMeta] = _dataMeta
|
2019-08-13 18:08:16 +00:00
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[6df556bf] [cdb.....] failed indexing archive!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[0d730134] [cdb.....] failed indexing archive!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if _indexDataContent {
|
2021-12-19 12:06:39 +00:00
|
|
|
if _, _wasCached := _cachedDataContent[_keyDataContent]; !_wasCached {
|
|
|
|
_key := _keyBuffer[:8]
|
|
|
|
if _error := EncodeKeyToBytes_0 (NamespaceDataContent, _keyDataContent, _key); _error != nil {
|
|
|
|
AbortError (_error, "[580e387e] [cdb.....] failed indexing archive!")
|
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
if _dataContent, _error := _cdbReader.GetWithCdbHash (_key); _error == nil {
|
|
|
|
if _dataContent != nil {
|
2021-12-19 12:06:39 +00:00
|
|
|
_cachedDataContent[_keyDataContent] = _dataContent
|
2019-08-13 18:08:16 +00:00
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[4e27fe46] [cdb.....] failed indexing archive!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[532845ad] [cdb.....] failed indexing archive!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-19 12:06:39 +00:00
|
|
|
if !_quiet {
|
|
|
|
if _indexPaths {
|
|
|
|
log.Printf ("[ii] [6b7ec5d9] [cdb.....] cached %d file references;\n", len (_cachedReferences))
|
|
|
|
}
|
|
|
|
if _indexDataMeta {
|
|
|
|
log.Printf ("[ii] [5ec4f113] [cdb.....] cached %d meta-data blocks;\n", len (_cachedDataMeta))
|
|
|
|
}
|
|
|
|
if _indexDataContent {
|
|
|
|
log.Printf ("[ii] [d9680a2f] [cdb.....] cached %d content blocks;\n", len (_cachedDataContent))
|
|
|
|
}
|
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ww] [30314f31] [cdb.....] missing archive files index; ignoring!\n")
|
2021-12-19 10:34:55 +00:00
|
|
|
_indexPaths = false
|
|
|
|
_indexDataMeta = false
|
|
|
|
_indexDataContent = false
|
2021-12-19 12:06:39 +00:00
|
|
|
_cachedReferences = nil
|
2021-12-19 10:34:55 +00:00
|
|
|
_cachedDataMeta = nil
|
|
|
|
_cachedDataContent = nil
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[82299b3d] [cdb.....] failed indexing arcdive!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if _indexPaths && _indexDataMeta && _indexDataContent {
|
|
|
|
if _error := _cdbReader.Close (); _error == nil {
|
|
|
|
_cdbReader = nil
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[d7aa79e1] [cdb.....] failed closing archive!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-16 12:37:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
if _profileCpu != "" {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [70c210f3] [pprof...] profiling CPU to `%s`...\n", _profileCpu)
|
2019-08-13 18:08:16 +00:00
|
|
|
_stream, _error := os.Create (_profileCpu)
|
|
|
|
if _error != nil {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[fd4e0009] [pprof...] failed opening CPU profile!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
_error = pprof.StartCPUProfile (_stream)
|
|
|
|
if _error != nil {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[ac721629] [pprof...] failed starting CPU profile!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
defer pprof.StopCPUProfile ()
|
|
|
|
}
|
|
|
|
if _profileMem != "" {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [9196ee90] [pprof...] profiling MEM to `%s`...\n", _profileMem)
|
2019-08-13 18:08:16 +00:00
|
|
|
_stream, _error := os.Create (_profileMem)
|
|
|
|
if _error != nil {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[907d08b5] [pprof...] failed opening MEM profile!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
_profile := pprof.Lookup ("heap")
|
|
|
|
defer func () () {
|
|
|
|
runtime.GC ()
|
|
|
|
if _profile != nil {
|
|
|
|
if _error := _profile.WriteTo (_stream, 0); _error != nil {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[4b1e5112] [pprof...] failed writing MEM profile!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (nil, "[385dc8f0] [pprof...] failed loading MEM profile!")
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
_stream.Close ()
|
|
|
|
} ()
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-16 12:37:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_server := & server {
|
|
|
|
cdbReader : _cdbReader,
|
2021-12-19 12:06:39 +00:00
|
|
|
cachedReferences : _cachedReferences,
|
2021-12-16 12:37:12 +00:00
|
|
|
cachedDataMeta : _cachedDataMeta,
|
|
|
|
cachedDataContent : _cachedDataContent,
|
|
|
|
securityHeadersTls : _securityHeadersTls,
|
|
|
|
securityHeadersEnabled : _securityHeadersEnabled,
|
2021-12-16 13:21:09 +00:00
|
|
|
http1Disabled : _http1Disabled,
|
|
|
|
http2Disabled : _http2Disabled,
|
2021-12-16 21:10:11 +00:00
|
|
|
http3AltSvc : _http3AltSvc,
|
2021-12-16 12:37:12 +00:00
|
|
|
quiet : _quiet,
|
2021-12-16 15:40:25 +00:00
|
|
|
debug : _debug,
|
2021-12-16 12:37:12 +00:00
|
|
|
dummy : _dummy,
|
2021-12-17 23:56:34 +00:00
|
|
|
dummyEmpty : _dummyEmpty,
|
|
|
|
dummyDelay : _dummyDelay,
|
2021-12-16 12:37:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
_tls1Config := & tls.Config {
|
2019-08-15 07:06:06 +00:00
|
|
|
Certificates : nil,
|
|
|
|
MinVersion : tls.VersionTLS12,
|
2021-12-17 12:03:55 +00:00
|
|
|
MaxVersion : tls.VersionTLS13,
|
2019-08-15 07:06:06 +00:00
|
|
|
CipherSuites : []uint16 {
|
|
|
|
// NOTE: https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
|
2021-12-17 12:03:55 +00:00
|
|
|
// NOTE: https://github.com/golang/go/issues/29349
|
2019-08-15 07:06:06 +00:00
|
|
|
// NOTE: TLSv1.3
|
2021-12-17 12:03:55 +00:00
|
|
|
tls.TLS_CHACHA20_POLY1305_SHA256,
|
2019-08-15 07:06:06 +00:00
|
|
|
tls.TLS_AES_128_GCM_SHA256,
|
|
|
|
tls.TLS_AES_256_GCM_SHA384,
|
|
|
|
// NOTE: TLSv1.2
|
2021-12-17 12:03:55 +00:00
|
|
|
// NOTE: https://datatracker.ietf.org/doc/html/rfc7540#section-9.2.2
|
2019-08-15 07:06:06 +00:00
|
|
|
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
|
|
|
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
2021-12-17 12:03:55 +00:00
|
|
|
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
2019-08-15 07:06:06 +00:00
|
|
|
},
|
|
|
|
Renegotiation : tls.RenegotiateNever,
|
|
|
|
SessionTicketsDisabled : true,
|
|
|
|
DynamicRecordSizingDisabled : true,
|
2019-08-15 07:41:08 +00:00
|
|
|
NextProtos : []string { "http/1.1", "http/1.0" },
|
2019-08-15 07:06:06 +00:00
|
|
|
}
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
if (_bindTls1 != "") || (_bindTls2 != "") {
|
2019-08-15 12:00:45 +00:00
|
|
|
if _tlsPrivate != "" {
|
|
|
|
if _certificate, _error := tls.LoadX509KeyPair (_tlsPublic, _tlsPrivate); _error == nil {
|
2021-12-17 23:29:57 +00:00
|
|
|
_tls1Config.Certificates = append (_tls1Config.Certificates, _certificate)
|
2019-08-15 12:00:45 +00:00
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[ecdf443d] [tls.....] failed loading TLS certificate!")
|
2019-08-15 12:00:45 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if len (_tls1Config.Certificates) == 0 {
|
2019-08-15 12:00:45 +00:00
|
|
|
if !_quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [344ba198] [tls.....] no TLS certificate specified; using self-signed!\n")
|
2019-08-15 12:00:45 +00:00
|
|
|
}
|
|
|
|
if _certificate, _error := tls.X509KeyPair ([]byte (DefaultTlsCertificatePublic), []byte (DefaultTlsCertificatePrivate)); _error == nil {
|
2021-12-17 23:29:57 +00:00
|
|
|
_tls1Config.Certificates = append (_tls1Config.Certificates, _certificate)
|
2019-08-15 12:00:45 +00:00
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[98ba6d23] [tls.....] failed parsing TLS certificate!")
|
2019-08-15 12:00:45 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-15 06:46:15 +00:00
|
|
|
}
|
|
|
|
|
2021-12-16 12:37:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpPlain1Server := & fasthttp.Server {
|
2019-08-13 18:08:16 +00:00
|
|
|
|
|
|
|
Name : "kawipiko",
|
2021-12-18 09:35:58 +00:00
|
|
|
Handler : _server.ServeFast,
|
2019-08-13 18:08:16 +00:00
|
|
|
GetOnly : true,
|
|
|
|
|
|
|
|
NoDefaultServerHeader : true,
|
|
|
|
NoDefaultContentType : true,
|
|
|
|
NoDefaultDate : true,
|
|
|
|
DisableHeaderNamesNormalizing : true,
|
|
|
|
|
|
|
|
Concurrency : 16 * 1024 + 128,
|
|
|
|
MaxRequestsPerConn : 256 * 1024,
|
|
|
|
|
|
|
|
ReadBufferSize : 16 * 1024,
|
|
|
|
WriteBufferSize : 16 * 1024,
|
|
|
|
MaxRequestBodySize : 16 * 1024,
|
|
|
|
|
|
|
|
ReadTimeout : 30 * time.Second,
|
|
|
|
WriteTimeout : 30 * time.Second,
|
|
|
|
IdleTimeout : 360 * time.Second,
|
|
|
|
|
|
|
|
TCPKeepalive : true,
|
|
|
|
TCPKeepalivePeriod : 60 * time.Second,
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
ReduceMemoryUsage : _httpReduceMemory,
|
2019-08-13 18:08:16 +00:00
|
|
|
|
2021-12-16 09:55:04 +00:00
|
|
|
CloseOnShutdown : true,
|
|
|
|
DisableKeepalive : false,
|
|
|
|
|
2021-12-16 15:40:25 +00:00
|
|
|
Logger : _server,
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
2021-12-16 12:37:12 +00:00
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpTls1Server := & fasthttp.Server {}
|
|
|
|
*_httpTls1Server = *_httpPlain1Server
|
2019-08-15 06:46:15 +00:00
|
|
|
|
2021-12-16 12:37:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpPlain2Server := & http.Server {
|
2019-08-14 18:55:05 +00:00
|
|
|
|
|
|
|
Handler : _server,
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
MaxHeaderBytes : _httpPlain1Server.ReadBufferSize,
|
2019-08-14 18:55:05 +00:00
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
ReadTimeout : _httpPlain1Server.ReadTimeout,
|
|
|
|
ReadHeaderTimeout : _httpPlain1Server.ReadTimeout,
|
|
|
|
WriteTimeout : _httpPlain1Server.WriteTimeout,
|
|
|
|
IdleTimeout : _httpPlain1Server.IdleTimeout,
|
2019-08-14 18:55:05 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
|
|
|
|
_httpTls2Server := & http.Server {}
|
|
|
|
*_httpTls2Server = *_httpPlain2Server
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_tls2Config := _tls1Config.Clone ()
|
2021-12-16 13:21:09 +00:00
|
|
|
if !_http1Disabled && !_http2Disabled {
|
|
|
|
_tls2Config.NextProtos = []string { "h2", "http/1.1", "http/1.0" }
|
|
|
|
} else if !_http1Disabled {
|
|
|
|
_tls2Config.NextProtos = []string { "http/1.1", "http/1.0" }
|
|
|
|
} else if !_http2Disabled {
|
|
|
|
_tls2Config.NextProtos = []string { "h2" }
|
2021-12-17 15:01:48 +00:00
|
|
|
} else if _bindQuic != "" {
|
|
|
|
// NOP
|
2021-12-16 13:21:09 +00:00
|
|
|
} else {
|
|
|
|
panic ("[1b618ffe]")
|
|
|
|
}
|
2019-08-15 07:41:08 +00:00
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !_quiet {
|
|
|
|
_httpPlain2Server.ErrorLog = log.New (os.Stderr, log.Prefix () + "[ee] [efe8cf82] [go-http.] | ", 0)
|
|
|
|
} else {
|
|
|
|
_httpPlain2Server.ErrorLog = log.New (ioutil.Discard, "", 0)
|
|
|
|
}
|
|
|
|
|
2021-12-16 15:40:25 +00:00
|
|
|
if !_quiet {
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpTls2Server.ErrorLog = log.New (os.Stderr, log.Prefix () + "[ee] [f734edc4] [go-http.] | ", 0)
|
2021-12-16 15:40:25 +00:00
|
|
|
} else {
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpTls2Server.ErrorLog = log.New (ioutil.Discard, "", 0)
|
2021-12-16 15:40:25 +00:00
|
|
|
}
|
2021-12-16 12:37:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2021-12-16 21:10:11 +00:00
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpQuicServer := & http3.Server {}
|
2021-12-17 15:01:48 +00:00
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpQuicServer.Server = & http.Server {
|
2021-12-16 21:10:11 +00:00
|
|
|
|
|
|
|
Handler : _server,
|
|
|
|
TLSConfig : nil,
|
|
|
|
|
|
|
|
}
|
2021-12-17 15:01:48 +00:00
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
_tls3Config := _tls1Config.Clone ()
|
|
|
|
_tls3Config.NextProtos = []string { "h3", "h3-29" }
|
|
|
|
_httpQuicServer.Server.TLSConfig = _tls3Config
|
2021-12-17 15:01:48 +00:00
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpQuicServer.QuicConfig = & quic.Config {
|
2021-12-16 21:10:11 +00:00
|
|
|
|
|
|
|
Versions : []quic.VersionNumber {
|
|
|
|
quic.Version1,
|
2021-12-16 21:36:29 +00:00
|
|
|
quic.VersionDraft29,
|
2021-12-16 21:10:11 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
HandshakeIdleTimeout : 6 * time.Second,
|
2021-12-17 23:29:57 +00:00
|
|
|
MaxIdleTimeout : _httpTls1Server.IdleTimeout,
|
2021-12-16 21:10:11 +00:00
|
|
|
|
|
|
|
MaxIncomingStreams : 1024,
|
|
|
|
MaxIncomingUniStreams : 1024,
|
|
|
|
|
|
|
|
InitialConnectionReceiveWindow : 1 * 1024 * 1024,
|
|
|
|
MaxConnectionReceiveWindow : 4 * 1024 * 1024,
|
|
|
|
|
|
|
|
InitialStreamReceiveWindow : 512 * 1024,
|
|
|
|
MaxStreamReceiveWindow : 2 * 1024 * 1024,
|
|
|
|
KeepAlive : true,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-12-17 15:01:48 +00:00
|
|
|
if !_quiet {
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpQuicServer.Server.ErrorLog = log.New (os.Stderr, log.Prefix () + "[ee] [a6af7354] [quic-h3.] | ", 0)
|
2021-12-17 15:01:48 +00:00
|
|
|
} else {
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpQuicServer.Server.ErrorLog = log.New (ioutil.Discard, "", 0)
|
2021-12-17 15:01:48 +00:00
|
|
|
}
|
2021-12-16 21:10:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
if _timeoutDisabled {
|
2019-08-14 18:55:05 +00:00
|
|
|
|
2021-12-19 15:43:13 +00:00
|
|
|
if !_quiet {
|
|
|
|
log.Printf ("[ii] [5e901455] [http-x..] disabling HTTP timeouts!\n")
|
|
|
|
}
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpPlain1Server.ReadTimeout = 0
|
|
|
|
_httpPlain1Server.WriteTimeout = 0
|
|
|
|
_httpPlain1Server.IdleTimeout = 0
|
|
|
|
|
|
|
|
_httpTls1Server.ReadTimeout = 0
|
|
|
|
_httpTls1Server.WriteTimeout = 0
|
|
|
|
_httpTls1Server.IdleTimeout = 0
|
2019-08-14 18:55:05 +00:00
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpPlain2Server.ReadTimeout = 0
|
|
|
|
_httpPlain2Server.ReadHeaderTimeout = 0
|
|
|
|
_httpPlain2Server.WriteTimeout = 0
|
|
|
|
_httpPlain2Server.IdleTimeout = 0
|
2019-08-15 06:46:15 +00:00
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpTls2Server.ReadTimeout = 0
|
|
|
|
_httpTls2Server.ReadHeaderTimeout = 0
|
|
|
|
_httpTls2Server.WriteTimeout = 0
|
|
|
|
_httpTls2Server.IdleTimeout = 0
|
2019-08-14 18:55:05 +00:00
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
2019-08-14 18:55:05 +00:00
|
|
|
|
2021-12-16 12:37:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-08-14 18:55:05 +00:00
|
|
|
if !_quiet && (_debug || _isFirst) {
|
2021-12-17 23:29:57 +00:00
|
|
|
if _bindPlain1 != "" {
|
|
|
|
log.Printf ("[ii] [f11e4e37] [bind-0a.] listening on `http://%s/` (using FastHTTP supporting HTTP/1.1, HTTP/1.0);\n", _bindPlain1)
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _bindPlain2 != "" {
|
|
|
|
log.Printf ("[ii] [9a05dbb7] [bind-0b.] listening on `http://%s/` (using Go HTTP supporting HTTP/1.1, HTTP/1.0);\n", _bindPlain2)
|
|
|
|
}
|
|
|
|
if _bindTls1 != "" {
|
2021-12-16 13:21:09 +00:00
|
|
|
if !_http1Disabled && (!_http2Disabled && _bindTls2 == "") {
|
2021-12-17 23:29:57 +00:00
|
|
|
log.Printf ("[ii] [21f050c3] [bind-1..] listening on `https://%s/` (using FastHTTP supporting TLS with HTTP/1.1, HTTP/1.0, and HTTP/2 split);\n", _bindTls1)
|
2021-12-16 13:21:09 +00:00
|
|
|
} else if !_http1Disabled {
|
2021-12-17 23:29:57 +00:00
|
|
|
log.Printf ("[ii] [8e41f2df] [bind-1..] listening on `https://%s/` (using FastHTTP supporting TLS with HTTP/1.1, HTTP/1.0);\n", _bindTls1)
|
2021-12-16 13:21:09 +00:00
|
|
|
} else {
|
|
|
|
panic ("[fc754170]")
|
|
|
|
}
|
2019-08-15 06:46:15 +00:00
|
|
|
}
|
|
|
|
if _bindTls2 != "" {
|
2021-12-16 13:21:09 +00:00
|
|
|
if !_http1Disabled && !_http2Disabled {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [e7f03c99] [bind-2..] listening on `https://%s/` (using Go HTTP supporting TLS with HTTP/2, HTTP/1.1, HTTP/1.0);\n", _bindTls2)
|
2021-12-16 13:21:09 +00:00
|
|
|
} else if !_http1Disabled {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [477583ad] [bind-2..] listening on `https://%s/` (using Go HTTP supporting TLS with HTTP/1.1, HTTP/1.0 only);\n", _bindTls2)
|
2021-12-16 13:21:09 +00:00
|
|
|
} else if !_http2Disabled {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [7d2c7ddb] [bind-2..] listening on `https://%s/` (using Go HTTP supporting TLS with HTTP/2 only);\n", _bindTls2)
|
2021-12-16 13:21:09 +00:00
|
|
|
} else {
|
|
|
|
panic ("[d784a82c]")
|
|
|
|
}
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
2021-12-16 21:10:11 +00:00
|
|
|
if _bindQuic != "" {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [b958617a] [bind-3..] listening on `https://%s/` (using QUIC supporting TLS with HTTP/3 only);", _bindQuic)
|
2021-12-16 21:10:11 +00:00
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
var _httpPlain1Listener net.Listener
|
|
|
|
if _bindPlain1 != "" {
|
|
|
|
if _listener_0, _error := reuseport.Listen ("tcp4", _bindPlain1); _error == nil {
|
|
|
|
_httpPlain1Listener = _listener_0
|
|
|
|
} else {
|
|
|
|
AbortError (_error, "[d5f51e9f] [bind-0a.] failed creating TCP listener!")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var _httpPlain2Listener net.Listener
|
|
|
|
if _bindPlain2 != "" {
|
|
|
|
if _listener_0, _error := reuseport.Listen ("tcp4", _bindPlain2); _error == nil {
|
|
|
|
_httpPlain2Listener = _listener_0
|
2019-08-14 18:55:05 +00:00
|
|
|
} else {
|
2021-12-17 23:29:57 +00:00
|
|
|
AbortError (_error, "[546075c2] [bind-0b.] failed creating TCP listener!")
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
var _httpTls1Listener net.Listener
|
|
|
|
if _bindTls1 != "" {
|
|
|
|
if _listener_0, _error := reuseport.Listen ("tcp4", _bindTls1); _error == nil {
|
|
|
|
_httpTls1Listener = _listener_0
|
2019-08-14 18:55:05 +00:00
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[e35cc693] [bind-1..] failed creating TCP listener!")
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-15 06:46:15 +00:00
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
var _httpTls2Listener net.Listener
|
2019-08-15 06:46:15 +00:00
|
|
|
if _bindTls2 != "" {
|
|
|
|
if _listener_0, _error := reuseport.Listen ("tcp4", _bindTls2); _error == nil {
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpTls2Listener = _listener_0
|
2019-08-14 18:55:05 +00:00
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[63567445] [bind-2..] failed creating TCP listener!")
|
2021-12-17 15:01:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
var _httpQuicListener net.PacketConn
|
2021-12-17 15:01:48 +00:00
|
|
|
if _bindQuic != "" {
|
|
|
|
if _listener_0, _error := net.ListenPacket ("udp4", _bindQuic); _error == nil {
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpQuicListener = _listener_0
|
2021-12-17 15:01:48 +00:00
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[3b1bfc15] [bind-3..] failed creating UDP listener!")
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-08-16 17:50:25 +00:00
|
|
|
var _splitListenerClose func () ()
|
2021-12-17 23:29:57 +00:00
|
|
|
if (_httpTls1Listener != nil) && (_httpTls2Listener == nil) && !_http2Disabled {
|
|
|
|
log.Printf ("[ii] [1098a405] [bind-1..] listening on `https://%s/` (using Go HTTP supporting only HTTP/2 split);\n", _bindTls1)
|
|
|
|
_tls1Config.NextProtos = append ([]string { "h2" }, _tls1Config.NextProtos ...)
|
2021-12-17 15:01:48 +00:00
|
|
|
if !_quiet {
|
2021-12-17 23:29:57 +00:00
|
|
|
log.Printf ("[ii] [ba970bbb] [bind-1..] advertising TLS next protocols: %s", _tls1Config.NextProtos)
|
2021-12-17 15:01:48 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
_tlsListener := tls.NewListener (_httpTls1Listener, _tls1Config)
|
|
|
|
_httpTls1Listener_0 := & splitListener {
|
2019-08-16 17:50:25 +00:00
|
|
|
listener : _tlsListener,
|
|
|
|
queue : make (chan net.Conn),
|
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpTls2Listener_0 := & splitListener {
|
2019-08-16 17:50:25 +00:00
|
|
|
listener : _tlsListener,
|
|
|
|
queue : make (chan net.Conn),
|
|
|
|
}
|
|
|
|
_splitListenerClose = func () () {
|
|
|
|
if _error := _tlsListener.Close (); _error != nil {
|
2021-12-17 21:27:55 +00:00
|
|
|
LogError (_error, "[a5bce477] [bind-1..] failed closing TLS listener!")
|
2019-08-16 17:50:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
go func () () {
|
|
|
|
for {
|
|
|
|
if _connection_0, _error := _tlsListener.Accept (); _error == nil {
|
|
|
|
go func () () {
|
|
|
|
_connection := _connection_0.(*tls.Conn)
|
|
|
|
if _error := _connection.Handshake (); _error != nil {
|
|
|
|
if !_quiet {
|
2021-12-17 23:29:57 +00:00
|
|
|
log.Printf ("[ww] [d1c3dba3] [bind-1..] failed negotiating TLS connection!\n")
|
2019-08-16 17:50:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_protocol := _connection.ConnectionState () .NegotiatedProtocol
|
|
|
|
if _protocol == "h2" {
|
|
|
|
if _debug {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[dd] [df9f3e7e] [bind-1..] dispatching HTTP/2 TLS connection!\n")
|
2019-08-16 17:50:25 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpTls2Listener_0.queue <- _connection
|
2021-12-16 13:41:26 +00:00
|
|
|
} else if (_protocol == "http/1.1") || (_protocol == "http/1.0") || (_protocol == "") {
|
2019-08-16 17:50:25 +00:00
|
|
|
if _debug {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[dd] [d534c361] [bind-1..] dispatching HTTP/1.x TLS connection!\n")
|
2019-08-16 17:50:25 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpTls1Listener_0.queue <- _connection
|
2019-08-16 17:50:25 +00:00
|
|
|
} else {
|
|
|
|
if !_quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ww] [5cc0ebde] [bind-1..] unknown TLS protocol `%s`!\n", _protocol)
|
2019-08-16 17:50:25 +00:00
|
|
|
}
|
|
|
|
_connection.Close ()
|
|
|
|
}
|
|
|
|
} ()
|
|
|
|
} else if strings.Contains (_error.Error (), "use of closed network connection") {
|
|
|
|
break
|
|
|
|
} else {
|
2021-12-17 21:27:55 +00:00
|
|
|
LogError (_error, "[04b6637f] [bind-1..] failed accepting TLS connection!")
|
2019-08-16 17:50:25 +00:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} ()
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpTls1Listener = _httpTls1Listener_0
|
|
|
|
_httpTls2Listener = _httpTls2Listener_0
|
2019-08-16 17:50:25 +00:00
|
|
|
} else {
|
2021-12-17 23:29:57 +00:00
|
|
|
if _httpTls1Listener != nil {
|
2021-12-17 15:01:15 +00:00
|
|
|
if !_quiet {
|
2021-12-17 23:29:57 +00:00
|
|
|
log.Printf ("[ii] [ceed854a] [bind-1..] advertising TLS next protocols: %s", _tls1Config.NextProtos)
|
2021-12-17 15:01:15 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpTls1Listener = tls.NewListener (_httpTls1Listener, _tls1Config)
|
2019-08-16 17:50:25 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _httpTls2Listener != nil {
|
2021-12-17 15:01:15 +00:00
|
|
|
if !_quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [8b97c977] [bind-2..] advertising TLS next protocols: %s", _tls2Config.NextProtos)
|
2021-12-17 15:01:15 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpTls2Listener = tls.NewListener (_httpTls2Listener, _tls2Config)
|
2019-08-16 17:50:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
if _httpQuicListener != nil {
|
2021-12-17 15:01:15 +00:00
|
|
|
if !_quiet {
|
2021-12-17 23:29:57 +00:00
|
|
|
log.Printf ("[ii] [22feb826] [bind-3..] advertising TLS next protocols: %s", _tls3Config.NextProtos)
|
2021-12-17 15:01:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
if _httpPlain1Listener != nil {
|
|
|
|
_server.httpPlain1Server = _httpPlain1Server
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _httpPlain2Listener != nil {
|
|
|
|
_server.httpPlain2Server = _httpPlain2Server
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _httpTls1Listener != nil {
|
|
|
|
_server.httpTls1Server = _httpTls1Server
|
2019-08-15 06:46:15 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _httpTls2Listener != nil {
|
|
|
|
_server.httpTls2Server = _httpTls2Server
|
|
|
|
}
|
|
|
|
if _httpQuicListener != nil {
|
|
|
|
_server.httpQuicServer = _httpQuicServer
|
2021-12-16 21:10:11 +00:00
|
|
|
}
|
2019-08-14 18:55:05 +00:00
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
_httpPlain1Server = nil
|
|
|
|
_httpPlain2Server = nil
|
|
|
|
_httpTls1Server = nil
|
|
|
|
_httpTls2Server = nil
|
|
|
|
_httpQuicServer = nil
|
2019-08-14 18:55:05 +00:00
|
|
|
|
|
|
|
|
2021-12-16 12:37:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-08-14 18:55:05 +00:00
|
|
|
var _waiter sync.WaitGroup
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
if _server.httpPlain1Server != nil {
|
2019-08-14 18:55:05 +00:00
|
|
|
_waiter.Add (1)
|
2019-08-13 18:08:16 +00:00
|
|
|
go func () () {
|
2019-08-14 18:55:05 +00:00
|
|
|
defer _waiter.Done ()
|
|
|
|
if !_quiet {
|
2021-12-17 21:11:35 +00:00
|
|
|
log.Printf ("[ii] [f2061f1b] [fasthttp] starting FastHTTP server...\n")
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _error := _server.httpPlain1Server.Serve (_httpPlain1Listener); _error != nil {
|
2021-12-17 21:11:35 +00:00
|
|
|
AbortError (_error, "[44f45c67] [fasthttp] failed executing server!")
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
2021-12-16 21:10:11 +00:00
|
|
|
if !_quiet {
|
2021-12-17 21:11:35 +00:00
|
|
|
log.Printf ("[ii] [aca4a14f] [fasthttp] stopped FastHTTP server;\n")
|
2021-12-16 21:10:11 +00:00
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
} ()
|
|
|
|
}
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
if _server.httpTls1Server != nil {
|
2019-08-14 18:55:05 +00:00
|
|
|
_waiter.Add (1)
|
|
|
|
go func () () {
|
|
|
|
defer _waiter.Done ()
|
|
|
|
if !_quiet {
|
2021-12-17 21:11:35 +00:00
|
|
|
log.Printf ("[ii] [83cb1f6f] [fasthttp] starting FastHTTP server (for TLS)...\n")
|
2019-08-15 06:46:15 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _error := _server.httpTls1Server.Serve (_httpTls1Listener); _error != nil {
|
2021-12-17 21:11:35 +00:00
|
|
|
AbortError (_error, "[b2d50852] [fasthttp] failed executing server!")
|
2019-08-15 06:46:15 +00:00
|
|
|
}
|
2021-12-16 21:10:11 +00:00
|
|
|
if !_quiet {
|
2021-12-17 21:11:35 +00:00
|
|
|
log.Printf ("[ii] [ee4180b7] [fasthttp] stopped FastHTTP server (for TLS);\n")
|
2021-12-16 21:10:11 +00:00
|
|
|
}
|
2019-08-15 06:46:15 +00:00
|
|
|
} ()
|
|
|
|
}
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
if _server.httpPlain2Server != nil {
|
2019-08-15 06:46:15 +00:00
|
|
|
_waiter.Add (1)
|
|
|
|
go func () () {
|
|
|
|
defer _waiter.Done ()
|
|
|
|
if !_quiet {
|
2021-12-17 23:29:57 +00:00
|
|
|
log.Printf ("[ii] [4e579931] [go-http.] starting Go HTTP server...\n")
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _error := _server.httpPlain2Server.Serve (_httpPlain2Listener); (_error != nil) && (_error != http.ErrServerClosed) {
|
|
|
|
AbortError (_error, "[99e9abba] [go-http.] failed executing server!")
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
2021-12-16 21:10:11 +00:00
|
|
|
if !_quiet {
|
2021-12-17 23:29:57 +00:00
|
|
|
log.Printf ("[ii] [af0e9811] [go-http.] stopped Go HTTP server;\n")
|
2021-12-16 21:10:11 +00:00
|
|
|
}
|
|
|
|
} ()
|
|
|
|
}
|
|
|
|
|
2021-12-17 23:29:57 +00:00
|
|
|
if _server.httpTls2Server != nil {
|
|
|
|
_waiter.Add (1)
|
|
|
|
go func () () {
|
|
|
|
defer _waiter.Done ()
|
|
|
|
if !_quiet {
|
|
|
|
log.Printf ("[ii] [46ec2e41] [go-http.] starting Go HTTP server (for TLS)...\n")
|
|
|
|
}
|
|
|
|
if _error := _server.httpTls2Server.Serve (_httpTls2Listener); (_error != nil) && (_error != http.ErrServerClosed) {
|
|
|
|
AbortError (_error, "[9f6d28f4] [go-http.] failed executing server (for TLS)!")
|
|
|
|
}
|
|
|
|
if !_quiet {
|
|
|
|
log.Printf ("[ii] [9a487770] [go-http.] stopped Go HTTP server (for TLS);\n")
|
|
|
|
}
|
|
|
|
} ()
|
|
|
|
}
|
|
|
|
|
|
|
|
if _server.httpQuicServer != nil {
|
2021-12-16 21:10:11 +00:00
|
|
|
_waiter.Add (1)
|
|
|
|
go func () () {
|
|
|
|
defer _waiter.Done ()
|
|
|
|
if !_quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [4cf834b0] [quic-h3.] starting QUIC server...\n")
|
2021-12-16 21:10:11 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _error := _server.httpQuicServer.Serve (_httpQuicListener); (_error != nil) && (_error.Error () != "server closed") {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[73e700c5] [quic-h3.] failed executing server!")
|
2021-12-16 21:10:11 +00:00
|
|
|
}
|
|
|
|
if !_quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [0a9d72e9] [quic-h3.] stopped QUIC server;\n")
|
2021-12-16 21:10:11 +00:00
|
|
|
}
|
2019-08-14 18:55:05 +00:00
|
|
|
} ()
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
2021-12-19 12:06:39 +00:00
|
|
|
if _report && _reportStatsEnabled {
|
2021-12-18 15:54:06 +00:00
|
|
|
_reportStatsQuiet = _quiet
|
|
|
|
go func () () {
|
|
|
|
reportStatsLoop ()
|
|
|
|
} ()
|
|
|
|
}
|
|
|
|
|
|
|
|
if !_quiet {
|
|
|
|
time.Sleep (100 * time.Millisecond)
|
|
|
|
log.Printf ("[--] [ ]\n")
|
|
|
|
}
|
|
|
|
|
2019-08-14 18:55:05 +00:00
|
|
|
{
|
|
|
|
_waiter.Add (1)
|
|
|
|
_signals := make (chan os.Signal, 32)
|
|
|
|
signal.Notify (_signals, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
go func () () {
|
|
|
|
defer _waiter.Done ()
|
|
|
|
<- _signals
|
2021-12-18 15:54:06 +00:00
|
|
|
_reportStatsStop = true
|
|
|
|
if !_quiet {
|
|
|
|
log.Printf ("[--] [ ]\n")
|
|
|
|
}
|
2019-08-14 18:55:05 +00:00
|
|
|
if !_quiet {
|
2021-12-17 21:11:35 +00:00
|
|
|
log.Printf ("[ii] [691cb695] [shutdown] terminating...\n")
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _server.httpPlain1Server != nil {
|
2019-08-15 06:46:15 +00:00
|
|
|
_waiter.Add (1)
|
|
|
|
go func () () {
|
|
|
|
defer _waiter.Done ()
|
|
|
|
if !_quiet {
|
2021-12-17 21:11:35 +00:00
|
|
|
log.Printf ("[ii] [8eea3f63] [fasthttp] stopping FastHTTP server...\n")
|
2019-08-15 06:46:15 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
_server.httpPlain1Server.Shutdown ()
|
2019-08-15 06:46:15 +00:00
|
|
|
} ()
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
2019-08-16 17:50:25 +00:00
|
|
|
if _splitListenerClose != nil {
|
|
|
|
_waiter.Add (1)
|
|
|
|
go func () () {
|
|
|
|
defer _waiter.Done ()
|
|
|
|
_splitListenerClose ()
|
|
|
|
} ()
|
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _server.httpTls1Server != nil {
|
2019-08-15 06:46:15 +00:00
|
|
|
_waiter.Add (1)
|
|
|
|
go func () () {
|
|
|
|
defer _waiter.Done ()
|
|
|
|
if !_quiet {
|
2021-12-17 21:11:35 +00:00
|
|
|
log.Printf ("[ii] [ff651007] [fasthttp] stopping FastHTTP server (for TLS)...\n")
|
2019-08-15 06:46:15 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
_server.httpTls1Server.Shutdown ()
|
|
|
|
} ()
|
|
|
|
}
|
|
|
|
if _server.httpPlain2Server != nil {
|
|
|
|
_waiter.Add (1)
|
|
|
|
go func () () {
|
|
|
|
defer _waiter.Done ()
|
|
|
|
if !_quiet {
|
|
|
|
log.Printf ("[ii] [befe966d] [go-http.] stopping Go HTTP server...\n")
|
|
|
|
}
|
|
|
|
_server.httpPlain2Server.Shutdown (context.TODO ())
|
2019-08-15 06:46:15 +00:00
|
|
|
} ()
|
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _server.httpTls2Server != nil {
|
2019-08-15 06:46:15 +00:00
|
|
|
_waiter.Add (1)
|
|
|
|
go func () () {
|
|
|
|
defer _waiter.Done ()
|
|
|
|
if !_quiet {
|
2021-12-17 23:29:57 +00:00
|
|
|
log.Printf ("[ii] [9ae5a25b] [go-http.] stopping Go HTTP server (for TLS)...\n")
|
2019-08-15 06:46:15 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
_server.httpTls2Server.Shutdown (context.TODO ())
|
2021-12-16 21:10:11 +00:00
|
|
|
} ()
|
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
if _server.httpQuicServer != nil {
|
2021-12-16 21:10:11 +00:00
|
|
|
_waiter.Add (1)
|
|
|
|
go func () () {
|
|
|
|
defer _waiter.Done ()
|
2019-08-15 07:30:10 +00:00
|
|
|
if !_quiet {
|
2021-12-17 21:27:55 +00:00
|
|
|
log.Printf ("[ii] [41dab8c2] [quic-h3.] stopping QUIC server...\n")
|
2019-08-15 07:30:10 +00:00
|
|
|
}
|
2021-12-17 23:29:57 +00:00
|
|
|
_server.httpQuicServer.CloseGracefully (1 * time.Second)
|
2021-12-16 21:10:11 +00:00
|
|
|
time.Sleep (1 * time.Second)
|
2021-12-17 23:29:57 +00:00
|
|
|
_server.httpQuicServer.Close ()
|
2019-08-15 06:46:15 +00:00
|
|
|
} ()
|
2019-08-14 18:55:05 +00:00
|
|
|
}
|
2019-08-15 17:26:59 +00:00
|
|
|
if true {
|
|
|
|
go func () () {
|
|
|
|
time.Sleep (6 * time.Second)
|
2021-12-17 21:11:35 +00:00
|
|
|
AbortError (nil, "[827c672c] [shutdown] forced terminated!")
|
2019-08-15 17:26:59 +00:00
|
|
|
} ()
|
|
|
|
}
|
2019-08-14 18:55:05 +00:00
|
|
|
} ()
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
|
|
|
|
2019-08-14 18:55:05 +00:00
|
|
|
_waiter.Wait ()
|
2019-08-13 18:08:16 +00:00
|
|
|
|
2019-08-14 18:55:05 +00:00
|
|
|
if !_quiet {
|
2021-12-17 21:11:35 +00:00
|
|
|
defer log.Printf ("[ii] [a49175db] [shutdown] terminated!\n")
|
2021-12-16 12:37:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if _cdbReader != nil {
|
|
|
|
_server.cdbReader = nil
|
|
|
|
if _error := _cdbReader.Close (); _error != nil {
|
2021-12-17 21:27:55 +00:00
|
|
|
AbortError (_error, "[a1031c39] [cdb.....] failed closing archive!")
|
2021-12-16 12:37:12 +00:00
|
|
|
}
|
2019-08-13 18:08:16 +00:00
|
|
|
}
|
2019-08-14 18:55:05 +00:00
|
|
|
|
2021-12-16 12:37:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-08-13 18:08:16 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-08-16 17:50:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type splitListener struct {
|
|
|
|
listener net.Listener
|
|
|
|
queue chan net.Conn
|
|
|
|
}
|
|
|
|
|
|
|
|
func (_listener *splitListener) Accept () (net.Conn, error) {
|
|
|
|
if _connection, _ok := <- _listener.queue; _ok {
|
|
|
|
return _connection, nil
|
|
|
|
} else {
|
|
|
|
return nil, io.EOF
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (_listener *splitListener) Close () (error) {
|
|
|
|
close (_listener.queue)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (_listener *splitListener) Addr () (net.Addr) {
|
|
|
|
if _listener.listener != nil {
|
|
|
|
return _listener.listener.Addr ()
|
|
|
|
} else {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-16 11:32:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2021-12-18 09:35:58 +00:00
|
|
|
var _statsRequestsTotal uint64
|
2021-12-18 20:37:05 +00:00
|
|
|
var _statsRequestsBody uint64
|
2021-12-18 09:35:58 +00:00
|
|
|
var _statsRequestsFast uint64
|
|
|
|
var _statsRequestsSlow uint64
|
2021-12-18 20:38:39 +00:00
|
|
|
var _statsResponses1xx uint64
|
|
|
|
var _statsResponses2xx uint64
|
|
|
|
var _statsResponses3xx uint64
|
|
|
|
var _statsResponses4xx uint64
|
|
|
|
var _statsResponses5xx uint64
|
2021-12-18 09:35:58 +00:00
|
|
|
|
2021-12-18 18:10:11 +00:00
|
|
|
var _statsUsageCpuTotal uint64
|
|
|
|
var _statsUsageCpuUser uint64
|
|
|
|
var _statsUsageCpuSys uint64
|
|
|
|
var _statsUsageSwitchPreempted uint64
|
|
|
|
var _statsUsageSwitchVoluntary uint64
|
|
|
|
var _statsUsageFaultsMajor uint64
|
|
|
|
var _statsUsageFaultsMinor uint64
|
|
|
|
var _statsUsageIoReads uint64
|
|
|
|
var _statsUsageIoWrites uint64
|
2021-12-18 09:35:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2021-12-18 18:10:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
func reportStatsLoop () () {
|
|
|
|
|
2021-12-18 15:54:06 +00:00
|
|
|
for {
|
2021-12-18 18:10:11 +00:00
|
|
|
|
|
|
|
reportUpdateUsage ()
|
|
|
|
reportUpdateStats ()
|
|
|
|
|
|
|
|
time.Sleep (1000 * time.Millisecond)
|
|
|
|
|
2021-12-18 15:54:06 +00:00
|
|
|
if _reportStatsStop {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-18 18:10:11 +00:00
|
|
|
func reportUpdateStats () () {
|
2021-12-18 15:54:06 +00:00
|
|
|
|
|
|
|
_timestamp := RuntimeNanoseconds ()
|
|
|
|
|
|
|
|
_reportHeartbeatCounter += 1
|
|
|
|
|
|
|
|
_shouldLog := false
|
|
|
|
if !_reportStatsQuiet {
|
|
|
|
_shouldLog = _shouldLog || ((_reportHeartbeatCounter % 30) == 0)
|
|
|
|
} else {
|
|
|
|
_shouldLog = _shouldLog || ((_reportHeartbeatCounter % 360) == 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
_reportHeartbeat.Update (_timestamp)
|
|
|
|
if _reportHeartbeat.Speed1paLast < 0.001 {
|
|
|
|
_reportHeartbeat.Changed = false
|
|
|
|
}
|
|
|
|
|
|
|
|
_invalid := false
|
|
|
|
_changed := false
|
|
|
|
|
|
|
|
_reportRequestsTotal.Update2 (_timestamp, &_changed, &_invalid)
|
2021-12-18 20:37:05 +00:00
|
|
|
_reportRequestsBody.Update2 (_timestamp, &_changed, &_invalid)
|
2021-12-18 15:54:06 +00:00
|
|
|
_reportRequestsFast.Update2 (_timestamp, &_changed, &_invalid)
|
|
|
|
_reportRequestsSlow.Update2 (_timestamp, &_changed, &_invalid)
|
2021-12-18 20:38:39 +00:00
|
|
|
_reportResponses1xx.Update2 (_timestamp, &_changed, &_invalid)
|
|
|
|
_reportResponses2xx.Update2 (_timestamp, &_changed, &_invalid)
|
|
|
|
_reportResponses3xx.Update2 (_timestamp, &_changed, &_invalid)
|
|
|
|
_reportResponses4xx.Update2 (_timestamp, &_changed, &_invalid)
|
|
|
|
_reportResponses5xx.Update2 (_timestamp, &_changed, &_invalid)
|
2021-12-18 15:54:06 +00:00
|
|
|
|
2021-12-18 18:10:11 +00:00
|
|
|
_reportUsageCpuTotal.Update2 (_timestamp, &_changed, &_invalid)
|
|
|
|
_reportUsageCpuUser.Update2 (_timestamp, &_changed, &_invalid)
|
|
|
|
_reportUsageCpuSys.Update2 (_timestamp, &_changed, &_invalid)
|
|
|
|
_reportUsageSwitchPreempted.Update2 (_timestamp, &_changed, &_invalid)
|
|
|
|
_reportUsageSwitchVoluntary.Update2 (_timestamp, &_changed, &_invalid)
|
|
|
|
_reportUsageFaultsMajor.Update2 (_timestamp, &_changed, &_invalid)
|
|
|
|
_reportUsageFaultsMinor.Update2 (_timestamp, &_changed, &_invalid)
|
|
|
|
_reportUsageIoReads.Update2 (_timestamp, &_changed, &_invalid)
|
|
|
|
_reportUsageIoWrites.Update2 (_timestamp, &_changed, &_invalid)
|
|
|
|
|
2021-12-18 15:54:06 +00:00
|
|
|
if _invalid || (!_shouldLog && !_changed) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if _shouldLog && !_reportStatsQuiet {
|
|
|
|
log.Printf ("[--] [ ]\n")
|
|
|
|
}
|
2021-12-18 18:10:11 +00:00
|
|
|
|
2021-12-18 15:54:06 +00:00
|
|
|
if (_shouldLog || _reportHeartbeat.Changed) && _reportHeartbeat.Touched {
|
2021-12-18 18:10:11 +00:00
|
|
|
log.Printf ("[ii] [addc4553] [stats...] uptime %7.2f h | tps %7.2f %6.1f%%\n",
|
2021-12-18 15:54:06 +00:00
|
|
|
_reportHeartbeat.ValueLast / 3600, _reportHeartbeat.Speed1Last, _reportHeartbeat.Speed1prLast)
|
|
|
|
}
|
2021-12-18 18:10:11 +00:00
|
|
|
|
2021-12-18 15:54:06 +00:00
|
|
|
if (_shouldLog || _reportRequestsTotal.Changed) && _reportRequestsTotal.Touched {
|
2021-12-18 18:10:11 +00:00
|
|
|
log.Printf ("[ii] [870f4146] [stats...] requests %7.2f M | kps %7.2f %6.1f%% (%+.1f%%)\n",
|
2021-12-18 15:54:06 +00:00
|
|
|
_reportRequestsTotal.ValueLast, _reportRequestsTotal.Speed1Last, _reportRequestsTotal.Speed1prLast, _reportRequestsTotal.Speed1prWindow)
|
|
|
|
}
|
2021-12-18 20:38:39 +00:00
|
|
|
if (_shouldLog || _reportResponses1xx.Changed) && _reportResponses1xx.Touched {
|
2021-12-18 18:10:11 +00:00
|
|
|
log.Printf ("[ii] [d12ebda3] [stats...] resp-1xx %7.2f M | kps %7.2f %6.1f%% (%+.1f%%)\n",
|
2021-12-18 20:38:39 +00:00
|
|
|
_reportResponses1xx.ValueLast, _reportResponses1xx.Speed1Last, _reportResponses1xx.Speed1prLast, _reportResponses1xx.Speed1prWindow)
|
2021-12-18 15:54:06 +00:00
|
|
|
}
|
2021-12-18 20:38:39 +00:00
|
|
|
if (_shouldLog || _reportResponses2xx.Changed) && _reportResponses2xx.Touched {
|
2021-12-18 18:10:11 +00:00
|
|
|
log.Printf ("[ii] [2464e4c2] [stats...] resp-2xx %7.2f M | kps %7.2f %6.1f%% (%+.1f%%)\n",
|
2021-12-18 20:38:39 +00:00
|
|
|
_reportResponses2xx.ValueLast, _reportResponses2xx.Speed1Last, _reportResponses2xx.Speed1prLast, _reportResponses2xx.Speed1prWindow)
|
2021-12-18 15:54:06 +00:00
|
|
|
}
|
2021-12-18 20:38:39 +00:00
|
|
|
if (_shouldLog || _reportResponses3xx.Changed) && _reportResponses3xx.Touched {
|
2021-12-18 18:10:11 +00:00
|
|
|
log.Printf ("[ii] [59bea970] [stats...] resp-3xx %7.2f M | kps %7.2f %6.1f%% (%+.1f%%)\n",
|
2021-12-18 20:38:39 +00:00
|
|
|
_reportResponses3xx.ValueLast, _reportResponses3xx.Speed1Last, _reportResponses3xx.Speed1prLast, _reportResponses3xx.Speed1prWindow)
|
2021-12-18 15:54:06 +00:00
|
|
|
}
|
2021-12-18 20:38:39 +00:00
|
|
|
if (_shouldLog || _reportResponses4xx.Changed) && _reportResponses4xx.Touched {
|
2021-12-18 18:10:11 +00:00
|
|
|
log.Printf ("[ii] [babb043c] [stats...] resp-4xx %7.2f M | kps %7.2f %6.1f%% (%+.1f%%)\n",
|
2021-12-18 20:38:39 +00:00
|
|
|
_reportResponses4xx.ValueLast, _reportResponses4xx.Speed1Last, _reportResponses4xx.Speed1prLast, _reportResponses4xx.Speed1prWindow)
|
2021-12-18 15:54:06 +00:00
|
|
|
}
|
2021-12-18 20:38:39 +00:00
|
|
|
if (_shouldLog || _reportResponses5xx.Changed) && _reportResponses5xx.Touched {
|
2021-12-18 18:10:11 +00:00
|
|
|
log.Printf ("[ii] [047ba05b] [stats...] resp-5xx %7.2f M | kps %7.2f %6.1f%% (%+.1f%%)\n",
|
2021-12-18 20:38:39 +00:00
|
|
|
_reportResponses5xx.ValueLast, _reportResponses5xx.Speed1Last, _reportResponses5xx.Speed1prLast, _reportResponses5xx.Speed1prWindow)
|
2021-12-18 15:54:06 +00:00
|
|
|
}
|
2021-12-18 20:37:05 +00:00
|
|
|
if (_shouldLog || _reportRequestsBody.Changed) && _reportRequestsBody.Touched {
|
|
|
|
log.Printf ("[ii] [d2d45f12] [stats...] resp-sz %7.2f GB | MBps %7.2f %6.1f%% (%+.1f%%)\n",
|
|
|
|
_reportRequestsBody.ValueLast, _reportRequestsBody.Speed1Last, _reportRequestsBody.Speed1prLast, _reportRequestsBody.Speed1prWindow)
|
|
|
|
}
|
2021-12-18 18:10:11 +00:00
|
|
|
|
|
|
|
if (_shouldLog || _reportUsageCpuTotal.Changed) && _reportUsageCpuTotal.Touched {
|
|
|
|
log.Printf ("[ii] [e27def0f] [stats...] cpu-all %7.2f h | load %7.2f %6.1f%% (%+.1f%%)\n",
|
|
|
|
_reportUsageCpuTotal.ValueLast / 3600, _reportUsageCpuTotal.Speed1Last, _reportUsageCpuTotal.Speed1prLast, _reportUsageCpuTotal.Speed1prWindow)
|
|
|
|
}
|
|
|
|
if (_shouldLog || _reportUsageCpuSys.Changed) && _reportUsageCpuSys.Touched {
|
|
|
|
log.Printf ("[ii] [4a13138d] [stats...] cpu-sys %7.2f h | load %7.2f %6.1f%% (%+.1f%%)\n",
|
|
|
|
_reportUsageCpuSys.ValueLast / 3600, _reportUsageCpuSys.Speed1Last, _reportUsageCpuSys.Speed1prLast, _reportUsageCpuSys.Speed1prWindow)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_shouldLog || _reportUsageSwitchPreempted.Changed) && _reportUsageSwitchPreempted.Touched {
|
|
|
|
log.Printf ("[ii] [9e3fe2a8] [stats...] csw-prem %7.2f M | kps %7.2f %6.1f%% (%+.1f%%)\n",
|
|
|
|
_reportUsageSwitchPreempted.ValueLast, _reportUsageSwitchPreempted.Speed1Last, _reportUsageSwitchPreempted.Speed1prLast, _reportUsageSwitchPreempted.Speed1prWindow)
|
|
|
|
}
|
|
|
|
if (_shouldLog || _reportUsageSwitchVoluntary.Changed) && _reportUsageSwitchVoluntary.Touched {
|
|
|
|
log.Printf ("[ii] [e8059c56] [stats...] csw-norm %7.2f M | kps %7.2f %6.1f%% (%+.1f%%)\n",
|
|
|
|
_reportUsageSwitchVoluntary.ValueLast, _reportUsageSwitchVoluntary.Speed1Last, _reportUsageSwitchVoluntary.Speed1prLast, _reportUsageSwitchVoluntary.Speed1prWindow)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_shouldLog || _reportUsageFaultsMajor.Changed) && _reportUsageFaultsMajor.Touched {
|
|
|
|
log.Printf ("[ii] [08adfe80] [stats...] mem-maj %7.2f GB | MBps %7.2f %6.1f%% (%+.1f%%)\n",
|
|
|
|
_reportUsageFaultsMajor.ValueLast, _reportUsageFaultsMajor.Speed1Last / 1024, _reportUsageFaultsMajor.Speed1prLast, _reportUsageFaultsMajor.Speed1prWindow)
|
|
|
|
}
|
|
|
|
if (_shouldLog || _reportUsageFaultsMinor.Changed) && _reportUsageFaultsMinor.Touched {
|
|
|
|
log.Printf ("[ii] [6681ca7b] [stats...] mem-min %7.2f GB | MBps %7.2f %6.1f%% (%+.1f%%)\n",
|
|
|
|
_reportUsageFaultsMinor.ValueLast, _reportUsageFaultsMinor.Speed1Last / 1024, _reportUsageFaultsMinor.Speed1prLast, _reportUsageFaultsMinor.Speed1prWindow)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_shouldLog || _reportUsageIoReads.Changed) && _reportUsageIoReads.Touched {
|
|
|
|
log.Printf ("[ii] [db937bbe] [stats...] io-read %7.2f GB | MBps %7.2f %6.1f%% (%+.1f%%)\n",
|
|
|
|
_reportUsageIoReads.ValueLast, _reportUsageIoReads.Speed1Last / 1024, _reportUsageIoReads.Speed1prLast, _reportUsageIoReads.Speed1prWindow)
|
|
|
|
}
|
|
|
|
if (_shouldLog || _reportUsageIoWrites.Changed) && _reportUsageIoWrites.Touched {
|
|
|
|
log.Printf ("[ii] [ea16e474] [stats...] io-write %7.2f GB | MBps %7.2f %6.1f%% (%+.1f%%)\n",
|
|
|
|
_reportUsageIoWrites.ValueLast, _reportUsageIoWrites.Speed1Last / 1024, _reportUsageIoWrites.Speed1prLast, _reportUsageIoWrites.Speed1prWindow)
|
|
|
|
}
|
|
|
|
|
2021-12-18 15:54:06 +00:00
|
|
|
if _shouldLog && !_reportStatsQuiet {
|
|
|
|
log.Printf ("[--] [ ]\n")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-18 18:10:11 +00:00
|
|
|
func reportUpdateUsage () () {
|
|
|
|
|
|
|
|
var _usage syscall.Rusage
|
|
|
|
|
|
|
|
if _error := syscall.Getrusage (syscall.RUSAGE_SELF, &_usage); _error != nil {
|
|
|
|
LogError (_error, "[c1d79147] [stats...] failed getting usage!")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
_pageSize := uint64 (syscall.Getpagesize ())
|
|
|
|
_ioSize := uint64 (512)
|
|
|
|
|
|
|
|
_statsUsageCpuUser = (uint64 (_usage.Utime.Sec) * 1000 * 1000) + uint64 (_usage.Utime.Usec)
|
|
|
|
_statsUsageCpuSys = (uint64 (_usage.Stime.Sec) * 1000 * 1000) + uint64 (_usage.Stime.Usec)
|
|
|
|
_statsUsageCpuTotal = _statsUsageCpuUser + _statsUsageCpuSys
|
|
|
|
_statsUsageSwitchVoluntary = uint64 (_usage.Nvcsw)
|
|
|
|
_statsUsageSwitchPreempted = uint64 (_usage.Nivcsw)
|
|
|
|
_statsUsageFaultsMajor = uint64 (_usage.Majflt) * _pageSize
|
|
|
|
_statsUsageFaultsMinor = uint64 (_usage.Minflt) * _pageSize
|
|
|
|
_statsUsageIoReads = uint64 (_usage.Inblock) * _ioSize
|
|
|
|
_statsUsageIoWrites = uint64 (_usage.Oublock) * _ioSize
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-18 15:54:06 +00:00
|
|
|
var _reportStatsEnabled = true
|
|
|
|
var _reportStatsQuiet = false
|
|
|
|
var _reportStatsStop = false
|
|
|
|
|
|
|
|
var _reportHeartbeatCounter uint64
|
|
|
|
var _reportHeartbeat = & StatMetric {
|
|
|
|
MetricSource : &_reportHeartbeatCounter,
|
|
|
|
}
|
|
|
|
|
|
|
|
var _reportRequestsTotal = & StatMetric {
|
|
|
|
MetricSource : &_statsRequestsTotal,
|
|
|
|
ValueScale : 1000 * 1000,
|
|
|
|
SpeedScale : 1000,
|
|
|
|
SpeedThreshold : 0.1,
|
|
|
|
}
|
2021-12-18 18:10:11 +00:00
|
|
|
|
2021-12-18 20:37:05 +00:00
|
|
|
var _reportRequestsBody = & StatMetric {
|
|
|
|
MetricSource : &_statsRequestsBody,
|
|
|
|
ValueScale : 1024 * 1024 * 1024, // GiB
|
|
|
|
SpeedScale : 1024, // KiB
|
|
|
|
SpeedThreshold : 1024,
|
|
|
|
}
|
|
|
|
|
2021-12-18 15:54:06 +00:00
|
|
|
var _reportRequestsFast = & StatMetric {
|
|
|
|
MetricSource : &_statsRequestsFast,
|
|
|
|
ValueScale : 1000 * 1000,
|
|
|
|
SpeedScale : 1000,
|
|
|
|
SpeedThreshold : 1.0,
|
|
|
|
}
|
2021-12-18 18:10:11 +00:00
|
|
|
|
2021-12-18 15:54:06 +00:00
|
|
|
var _reportRequestsSlow = & StatMetric {
|
|
|
|
MetricSource : &_statsRequestsSlow,
|
|
|
|
ValueScale : 1000 * 1000,
|
|
|
|
SpeedScale : 1000,
|
|
|
|
SpeedThreshold : 1.0,
|
|
|
|
}
|
2021-12-18 18:10:11 +00:00
|
|
|
|
2021-12-18 20:38:39 +00:00
|
|
|
var _reportResponses1xx = & StatMetric {
|
|
|
|
MetricSource : &_statsResponses1xx,
|
2021-12-18 15:54:06 +00:00
|
|
|
ValueScale : 1000 * 1000,
|
|
|
|
SpeedScale : 1000,
|
|
|
|
SpeedThreshold : 0.01,
|
|
|
|
}
|
2021-12-18 18:10:11 +00:00
|
|
|
|
2021-12-18 20:38:39 +00:00
|
|
|
var _reportResponses2xx = & StatMetric {
|
|
|
|
MetricSource : &_statsResponses2xx,
|
2021-12-18 15:54:06 +00:00
|
|
|
ValueScale : 1000 * 1000,
|
|
|
|
SpeedScale : 1000,
|
2021-12-18 18:10:11 +00:00
|
|
|
SpeedThreshold : 8.0,
|
2021-12-18 15:54:06 +00:00
|
|
|
}
|
2021-12-18 18:10:11 +00:00
|
|
|
|
2021-12-18 20:38:39 +00:00
|
|
|
var _reportResponses3xx = & StatMetric {
|
|
|
|
MetricSource : &_statsResponses3xx,
|
2021-12-18 15:54:06 +00:00
|
|
|
ValueScale : 1000 * 1000,
|
|
|
|
SpeedScale : 1000,
|
|
|
|
SpeedThreshold : 0.01,
|
|
|
|
}
|
2021-12-18 18:10:11 +00:00
|
|
|
|
2021-12-18 20:38:39 +00:00
|
|
|
var _reportResponses4xx = & StatMetric {
|
|
|
|
MetricSource : &_statsResponses4xx,
|
2021-12-18 15:54:06 +00:00
|
|
|
ValueScale : 1000 * 1000,
|
|
|
|
SpeedScale : 1000,
|
|
|
|
SpeedThreshold : 0.01,
|
|
|
|
}
|
2021-12-18 18:10:11 +00:00
|
|
|
|
2021-12-18 20:38:39 +00:00
|
|
|
var _reportResponses5xx = & StatMetric {
|
|
|
|
MetricSource : &_statsResponses5xx,
|
2021-12-18 15:54:06 +00:00
|
|
|
ValueScale : 1000 * 1000,
|
|
|
|
SpeedScale : 1000,
|
|
|
|
SpeedThreshold : 0.01,
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-18 18:10:11 +00:00
|
|
|
var _reportUsageCpuTotal = & StatMetric {
|
|
|
|
MetricSource : &_statsUsageCpuTotal,
|
|
|
|
ValueScale : 1000 * 1000, // microseconds -> seconds
|
|
|
|
SpeedScale : 1000 * 1000, // microseconds -> seconds
|
|
|
|
SpeedThreshold : 0.50, // -> percent
|
|
|
|
}
|
|
|
|
|
|
|
|
var _reportUsageCpuUser = & StatMetric {
|
|
|
|
MetricSource : &_statsUsageCpuUser,
|
|
|
|
ValueScale : 1000 * 1000, // microseconds -> seconds
|
|
|
|
SpeedScale : 1000 * 1000, // microseconds -> seconds
|
|
|
|
SpeedThreshold : 0.10, // -> percent
|
|
|
|
}
|
|
|
|
|
|
|
|
var _reportUsageCpuSys = & StatMetric {
|
|
|
|
MetricSource : &_statsUsageCpuSys,
|
|
|
|
ValueScale : 1000 * 1000, // microseconds -> seconds
|
|
|
|
SpeedScale : 1000 * 1000, // microseconds -> seconds
|
|
|
|
SpeedThreshold : 0.25, // -> percent
|
|
|
|
}
|
|
|
|
|
|
|
|
var _reportUsageSwitchPreempted = & StatMetric {
|
|
|
|
MetricSource : &_statsUsageSwitchPreempted,
|
|
|
|
ValueScale : 1000 * 1000,
|
|
|
|
SpeedScale : 1000,
|
|
|
|
SpeedThreshold : 0.1,
|
|
|
|
}
|
|
|
|
|
|
|
|
var _reportUsageSwitchVoluntary = & StatMetric {
|
|
|
|
MetricSource : &_statsUsageSwitchVoluntary,
|
|
|
|
ValueScale : 1000 * 1000,
|
|
|
|
SpeedScale : 1000,
|
|
|
|
SpeedThreshold : 10,
|
|
|
|
}
|
|
|
|
|
|
|
|
var _reportUsageFaultsMajor = & StatMetric {
|
|
|
|
MetricSource : &_statsUsageFaultsMajor,
|
|
|
|
ValueScale : 1024 * 1024 * 1024, // GiB
|
|
|
|
SpeedScale : 1024, // KiB
|
|
|
|
SpeedThreshold : 1024,
|
|
|
|
}
|
|
|
|
|
|
|
|
var _reportUsageFaultsMinor = & StatMetric {
|
|
|
|
MetricSource : &_statsUsageFaultsMinor,
|
|
|
|
ValueScale : 1024 * 1024 * 1024, // GiB
|
|
|
|
SpeedScale : 1024, // KiB
|
|
|
|
SpeedThreshold : 1024,
|
|
|
|
}
|
|
|
|
|
|
|
|
var _reportUsageIoReads = & StatMetric {
|
|
|
|
MetricSource : &_statsUsageIoReads,
|
|
|
|
ValueScale : 1024 * 1024 * 1024, // GiB
|
|
|
|
SpeedScale : 1024, // KiB
|
|
|
|
SpeedThreshold : 1024,
|
|
|
|
}
|
|
|
|
|
|
|
|
var _reportUsageIoWrites = & StatMetric {
|
|
|
|
MetricSource : &_statsUsageIoWrites,
|
|
|
|
ValueScale : 1024 * 1024 * 1024, // GiB
|
|
|
|
SpeedScale : 1024, // KiB
|
|
|
|
SpeedThreshold : 16,
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-18 15:54:06 +00:00
|
|
|
|
|
|
|
|
2021-12-16 11:32:05 +00:00
|
|
|
//go:embed usage.txt
|
|
|
|
var usageText string
|
|
|
|
|