[server] Add initial HTTP/2 and TLS support by using net.http

This commit is contained in:
Ciprian Dorin Craciun 2019-08-14 21:55:05 +03:00
parent ad089651b1
commit a1e456d290
2 changed files with 263 additions and 33 deletions

View file

@ -3,7 +3,9 @@
package server package server
import "bufio"
import "bytes" import "bytes"
import "crypto/tls"
import "flag" import "flag"
import "fmt" import "fmt"
import "io" import "io"
@ -34,6 +36,7 @@ import . "github.com/volution/kawipiko/lib/server"
type server struct { type server struct {
httpServer *fasthttp.Server httpServer *fasthttp.Server
httpsServer *http.Server
cdbReader *cdb.CDB cdbReader *cdb.CDB
cachedFileFingerprints map[string][]byte cachedFileFingerprints map[string][]byte
cachedDataMeta map[string][]byte cachedDataMeta map[string][]byte
@ -41,6 +44,7 @@ type server struct {
securityHeadersEnabled bool securityHeadersEnabled bool
securityHeadersTls bool securityHeadersTls bool
debug bool debug bool
quiet bool
dummy bool dummy bool
} }
@ -49,6 +53,11 @@ type server struct {
func (_server *server) Serve (_context *fasthttp.RequestCtx) () { func (_server *server) Serve (_context *fasthttp.RequestCtx) () {
if _server.dummy {
_server.ServeDummy (_context)
return
}
// _request := (*fasthttp.Request) (NoEscape (unsafe.Pointer (&_context.Request))) // _request := (*fasthttp.Request) (NoEscape (unsafe.Pointer (&_context.Request)))
_requestHeaders := (*fasthttp.RequestHeader) (NoEscape (unsafe.Pointer (&_context.Request.Header))) _requestHeaders := (*fasthttp.RequestHeader) (NoEscape (unsafe.Pointer (&_context.Request.Header)))
_response := (*fasthttp.Response) (NoEscape (unsafe.Pointer (&_context.Response))) _response := (*fasthttp.Response) (NoEscape (unsafe.Pointer (&_context.Response)))
@ -391,6 +400,50 @@ func ServeDummyRaw (_context *fasthttp.RequestCtx) () {
func (_server *server) ServeHTTP (_response http.ResponseWriter, _request *http.Request) () {
_context := fasthttp.RequestCtx {}
_context.Request.Reset ()
_context.Response.Reset ()
_context.Request.Header.SetMethod (_request.Method)
_context.Request.Header.SetRequestURI (_request.URL.Path)
_server.Serve (&_context)
{
_buffer := bytes.NewBuffer (make ([]byte, 0, 4096))
_writer := bufio.NewWriter (_buffer)
_context.Response.Header.Write (_writer)
_writer.Flush ()
_context.Response.Header.Read (bufio.NewReader (_buffer))
}
_responseBody := _context.Response.Body ()
_responseHeaders := _response.Header ()
_context.Response.Header.VisitAll (
func (_key_0 []byte, _value_0 []byte) () {
switch string (_key_0) {
case "Connection" :
// NOP
default :
_key := string (_key_0)
_value := string (_value_0)
_responseHeaders[_key] = append (_responseHeaders[_key], _value)
}
})
if len (_responseBody) > 0 {
_responseHeaders["Content-Length"] = []string { fmt.Sprintf ("%d", len (_responseBody)) }
}
_response.WriteHeader (_context.Response.Header.StatusCode ())
_response.Write (_responseBody)
}
func Main () () { func Main () () {
Main_0 (main_0) Main_0 (main_0)
} }
@ -400,6 +453,7 @@ func main_0 () (error) {
var _bind string var _bind string
var _bindTls string
var _archivePath string var _archivePath string
var _archiveInmem bool var _archiveInmem bool
var _archiveMmap bool var _archiveMmap bool
@ -414,6 +468,7 @@ func main_0 () (error) {
var _threads uint var _threads uint
var _slave uint var _slave uint
var _debug bool var _debug bool
var _quiet bool
var _dummy bool var _dummy bool
var _isFirst bool var _isFirst bool
var _isMaster bool var _isMaster bool
@ -441,6 +496,7 @@ func main_0 () (error) {
kawipiko-server kawipiko-server
--bind <ip>:<port> --bind <ip>:<port>
--bind-tls <ip>:<port>
--processes <count> (of slave processes) --processes <count> (of slave processes)
--threads <count> (of threads per process) --threads <count> (of threads per process)
@ -472,6 +528,7 @@ func main_0 () (error) {
} }
_bind_0 := _flags.String ("bind", "", "") _bind_0 := _flags.String ("bind", "", "")
_bindTls_0 := _flags.String ("bind-tls", "", "")
_archivePath_0 := _flags.String ("archive", "", "") _archivePath_0 := _flags.String ("archive", "", "")
_archiveInmem_0 := _flags.Bool ("archive-inmem", false, "") _archiveInmem_0 := _flags.Bool ("archive-inmem", false, "")
_archiveMmap_0 := _flags.Bool ("archive-mmap", false, "") _archiveMmap_0 := _flags.Bool ("archive-mmap", false, "")
@ -489,11 +546,13 @@ func main_0 () (error) {
_profileCpu_0 := _flags.String ("profile-cpu", "", "") _profileCpu_0 := _flags.String ("profile-cpu", "", "")
_profileMem_0 := _flags.String ("profile-mem", "", "") _profileMem_0 := _flags.String ("profile-mem", "", "")
_debug_0 := _flags.Bool ("debug", false, "") _debug_0 := _flags.Bool ("debug", false, "")
_quiet_0 := _flags.Bool ("quiet", false, "")
_dummy_0 := _flags.Bool ("dummy", false, "") _dummy_0 := _flags.Bool ("dummy", false, "")
FlagsParse (_flags, 0, 0) FlagsParse (_flags, 0, 0)
_bind = *_bind_0 _bind = *_bind_0
_bindTls = *_bindTls_0
_archivePath = *_archivePath_0 _archivePath = *_archivePath_0
_archiveInmem = *_archiveInmem_0 _archiveInmem = *_archiveInmem_0
_archiveMmap = *_archiveMmap_0 _archiveMmap = *_archiveMmap_0
@ -509,6 +568,7 @@ func main_0 () (error) {
_threads = *_threads_0 _threads = *_threads_0
_slave = *_slave_0 _slave = *_slave_0
_debug = *_debug_0 _debug = *_debug_0
_quiet = *_quiet_0 && !_debug
_dummy = *_dummy_0 _dummy = *_dummy_0
_profileCpu = *_profileCpu_0 _profileCpu = *_profileCpu_0
@ -521,7 +581,7 @@ func main_0 () (error) {
_isFirst = true _isFirst = true
} }
if _bind == "" { if (_bind == "") && (_bindTls == "") {
AbortError (nil, "[6edd9512] expected bind address argument!") AbortError (nil, "[6edd9512] expected bind address argument!")
} }
@ -577,7 +637,7 @@ func main_0 () (error) {
debug.SetGCPercent (50) debug.SetGCPercent (50)
debug.SetMaxThreads (int (128 * (_threads / 64 + 1))) debug.SetMaxThreads (int (128 * (_threads / 64 + 1)))
debug.SetMaxStack (16 * 1024) // debug.SetMaxStack (16 * 1024)
_httpServerReduceMemory := false _httpServerReduceMemory := false
@ -599,9 +659,12 @@ func main_0 () (error) {
_processName := os.Args[0] _processName := os.Args[0]
_processArguments := make ([]string, 0, len (os.Args)) _processArguments := make ([]string, 0, len (os.Args))
_processArguments = append (_processArguments, if _bind != "" {
"--bind", _bind, _processArguments = append (_processArguments, "--bind", _bind)
) }
if _bindTls != "" {
_processArguments = append (_processArguments, "--bind-tls", _bindTls)
}
if _archivePath != "" { if _archivePath != "" {
_processArguments = append (_processArguments, "--archive", _archivePath) _processArguments = append (_processArguments, "--archive", _archivePath)
} }
@ -635,6 +698,9 @@ func main_0 () (error) {
if _debug { if _debug {
_processArguments = append (_processArguments, "--debug") _processArguments = append (_processArguments, "--debug")
} }
if _quiet {
_processArguments = append (_processArguments, "--quiet")
}
if _dummy { if _dummy {
_processArguments = append (_processArguments, "--dummy") _processArguments = append (_processArguments, "--dummy")
} }
@ -655,7 +721,7 @@ func main_0 () (error) {
if _processPid, _error := os.StartProcess (_processName, _processArguments, _processAttributes); _error == nil { if _processPid, _error := os.StartProcess (_processName, _processArguments, _processAttributes); _error == nil {
_processesJoin.Add (1) _processesJoin.Add (1)
_processesPid[_processIndex] = _processPid _processesPid[_processIndex] = _processPid
if _debug { if !_quiet {
log.Printf ("[ii] [63cb22f8] sub-process `%d` started (with `%d` threads);\n", _processPid.Pid, _threads) log.Printf ("[ii] [63cb22f8] sub-process `%d` started (with `%d` threads);\n", _processPid.Pid, _threads)
} }
go func (_index int, _processPid *os.Process) () { go func (_index int, _processPid *os.Process) () {
@ -700,7 +766,7 @@ func main_0 () (error) {
_processesJoin.Wait () _processesJoin.Wait ()
if _debug { if !_quiet {
log.Printf ("[ii] [b949bafc] sub-processes terminated;\n") log.Printf ("[ii] [b949bafc] sub-processes terminated;\n")
} }
@ -716,7 +782,7 @@ func main_0 () (error) {
var _cdbReader *cdb.CDB var _cdbReader *cdb.CDB
if _archivePath != "" { if _archivePath != "" {
if _debug || _isFirst { if !_quiet && (_debug || _isFirst) {
log.Printf ("[ii] [3b788396] opening archive file `%s`...\n", _archivePath) log.Printf ("[ii] [3b788396] opening archive file `%s`...\n", _archivePath)
} }
@ -745,7 +811,7 @@ func main_0 () (error) {
} }
if _archivePreload { if _archivePreload {
if _debug { if !_quiet {
log.Printf ("[ii] [13f4ebf7] preloading archive file...\n") log.Printf ("[ii] [13f4ebf7] preloading archive file...\n")
} }
_buffer := [16 * 1024]byte {} _buffer := [16 * 1024]byte {}
@ -818,7 +884,7 @@ func main_0 () (error) {
} else { } else {
if _debug || _isFirst { if !_quiet && (_debug || _isFirst) {
log.Printf ("[ww] [dd697a66] using `read`-based archive (with significant performance impact)!\n") log.Printf ("[ww] [dd697a66] using `read`-based archive (with significant performance impact)!\n")
} }
@ -856,7 +922,7 @@ func main_0 () (error) {
} }
if _indexPaths || _indexDataMeta || _indexDataContent { if _indexPaths || _indexDataMeta || _indexDataContent {
if _debug { if !_quiet {
log.Printf ("[ii] [fa5338fd] indexing archive...\n") log.Printf ("[ii] [fa5338fd] indexing archive...\n")
} }
if _filesIndex, _error := _cdbReader.GetWithCdbHash ([]byte (NamespaceFilesIndex)); _error == nil { if _filesIndex, _error := _cdbReader.GetWithCdbHash ([]byte (NamespaceFilesIndex)); _error == nil {
@ -956,6 +1022,7 @@ func main_0 () (error) {
securityHeadersTls : _securityHeadersTls, securityHeadersTls : _securityHeadersTls,
securityHeadersEnabled : _securityHeadersEnabled, securityHeadersEnabled : _securityHeadersEnabled,
debug : _debug, debug : _debug,
quiet : _quiet,
dummy : _dummy, dummy : _dummy,
} }
@ -1022,51 +1089,147 @@ func main_0 () (error) {
} }
_httpsServer := & http.Server {
Handler : _server,
TLSConfig : & tls.Config {},
MaxHeaderBytes : 16 * 1024,
ReadTimeout : 30 * time.Second,
ReadHeaderTimeout : 30 * time.Second,
WriteTimeout : 30 * time.Second,
IdleTimeout : 360 * time.Second,
}
if _timeoutDisabled { if _timeoutDisabled {
_httpServer.ReadTimeout = 0 _httpServer.ReadTimeout = 0
_httpServer.WriteTimeout = 0 _httpServer.WriteTimeout = 0
_httpServer.IdleTimeout = 0 _httpServer.IdleTimeout = 0
_httpsServer.ReadTimeout = 0
_httpsServer.ReadHeaderTimeout = 0
_httpsServer.WriteTimeout = 0
_httpsServer.IdleTimeout = 1 * time.Second
} }
if _dummy {
_httpServer.Handler = _server.ServeDummy if !_quiet && (_debug || _isFirst) {
if _bind != "" {
log.Printf ("[ii] [f11e4e37] listening on `http://%s/`;\n", _bind)
}
if _bindTls != "" {
log.Printf ("[ii] [21f050c3] listening on `https://%s/`;\n", _bindTls)
}
} }
_server.httpServer = _httpServer
var _httpListener net.Listener
if _bind != "" {
if _listener_0, _error := reuseport.Listen ("tcp4", _bind); _error == nil {
_httpListener = _listener_0
} else {
AbortError (_error, "[d5f51e9f] failed starting listener!")
}
}
var _httpsListener net.Listener
if _bindTls != "" {
if _listener_0, _error := reuseport.Listen ("tcp4", _bindTls); _error == nil {
_httpsListener = _listener_0
} else {
AbortError (_error, "[e35cc693] failed starting listener!")
}
}
if _bindTls != "" {
if _certificate, _error := tls.X509KeyPair ([]byte (DefaultTlsCertificatePublic), []byte (DefaultTlsCertificatePrivate)); _error == nil {
_httpsServer.TLSConfig.Certificates = append (_httpsServer.TLSConfig.Certificates, _certificate)
} else {
AbortError (_error, "[98ba6d23] failed parsing TLS certificate!")
}
}
{ if _httpListener != nil {
_signals := make (chan os.Signal, 32) _server.httpServer = _httpServer
signal.Notify (_signals, syscall.SIGINT, syscall.SIGTERM) }
if _httpsListener != nil {
_server.httpsServer = _httpsServer
}
_httpServer = nil
_httpsServer = nil
var _waiter sync.WaitGroup
if _server.httpServer != nil {
_waiter.Add (1)
go func () () { go func () () {
<- _signals defer _waiter.Done ()
if _debug { if !_quiet {
log.Printf ("[ii] [691cb695] shutingdown...\n") log.Printf ("[ii] [f2061f1b] starting HTTP server...\n")
}
if _error := _server.httpServer.Serve (_httpListener); _error != nil {
AbortError (_error, "[44f45c67] failed executing server!")
}
if !_quiet {
log.Printf ("[ii] [aca4a14f] stopped HTTP server;\n")
} }
_server.httpServer.Shutdown ()
} () } ()
} }
if _server.httpsServer != nil {
if _debug || _isFirst { _waiter.Add (1)
log.Printf ("[ii] [f11e4e37] listening on `http://%s/`;\n", _bind) go func () () {
defer _waiter.Done ()
if !_quiet {
log.Printf ("[ii] [46ec2e41] starting HTTPS server...\n")
}
if _error := _server.httpsServer.ServeTLS (_httpsListener, "", ""); (_error != nil) && (_error != http.ErrServerClosed) {
AbortError (_error, "[9f6d28f4] failed executing server!")
}
if !_quiet {
log.Printf ("[ii] [9a487770] stopped HTTPS server;\n")
}
} ()
} }
var _httpListener net.Listener {
if _httpListener_0, _error := reuseport.Listen ("tcp4", _bind); _error == nil { _waiter.Add (1)
_httpListener = _httpListener_0 _signals := make (chan os.Signal, 32)
} else { signal.Notify (_signals, syscall.SIGINT, syscall.SIGTERM)
AbortError (_error, "[d5f51e9f] failed starting listener!") go func () () {
defer _waiter.Done ()
<- _signals
if !_quiet {
log.Printf ("[ii] [691cb695] shutingdown (1)...\n")
}
if _server.httpServer != nil {
if !_quiet {
log.Printf ("[ii] [8eea3f63] stopping HTTP server...\n")
}
_server.httpServer.Shutdown ()
}
if _server.httpsServer != nil {
if !_quiet {
log.Printf ("[ii] [9ae5a25b] stopping HTTPS server...\n")
}
_server.httpsServer.Close ()
}
} ()
} }
if _error := _httpServer.Serve (_httpListener); _error != nil { _waiter.Wait ()
AbortError (_error, "[44f45c67] failed executing server!")
}
if _debug { if !_quiet {
defer log.Printf ("[ii] [a49175db] done!\n") defer log.Printf ("[ii] [a49175db] done!\n")
} }
return nil return nil
} }

67
sources/lib/server/tls.go Normal file
View file

@ -0,0 +1,67 @@
package server
var DefaultTlsCertificatePublic = []byte (`
-----BEGIN CERTIFICATE-----
MIIDIzCCAgugAwIBAgIUVyUIITgu0+by4ASAy3b9vOM+B2wwDQYJKoZIhvcNAQEL
BQAwHzEdMBsGA1UEAxMUa2F3aXBpa28udm9sdXRpb24ucm8wIBcNMTkwODE0MTUw
OTEzWhgPMjA1OTA4MTQxNTA5MTNaMB8xHTAbBgNVBAMTFGthd2lwaWtvLnZvbHV0
aW9uLnJvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvo6I70Xe87KO
aj764hlWEcAWWaEnBmzMgJtOiAgFfG6B3vMuSE84Ro7a0uqVwkHqhYOrE66jFBo8
moPBOBABovVpDtNGjWGE+xFqf609MEuWloDNu4d6wgBjdjcXfZZ6KYcsfsctcoRe
eYljgujx+lvRgORKS4nWnOOyY3O9wJRMxa3ITkRfVUwlQgampKKcIk3iXdRqdAOt
ws6TO3VTwVZ1poDDSyYcKTW6aQoQmsOCDEgQh+pyYQJSVIEqiFP32cjq43opHonf
OpykAiL2e7MiRYJur5E5xH2ZmT9SersPcACMoCu1DiHPJaGvxfl693gf4pgX6rDb
PWTNJqWpqwIDAQABo1UwUzAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUF
BwMBMA8GA1UdDwEB/wQFAwMHoAAwHQYDVR0OBBYEFPDjABVCI490LdvHPeotzNq3
xa9KMA0GCSqGSIb3DQEBCwUAA4IBAQA0cYKpYneOgBRGL/5q86g17qGOrQOWjdDr
1k7i817pBjIfRj9bm1n2iaSrC4GCt4Ok+hl/DyjPNDDUXZxEmfmxlugi6dKLPQp9
p30hlTB7E3ArHKkWXYGo19URewAUYOMEIR1lB5/RS21rnpUKHawrwi9pZHTwYQ5Q
QcnpA9/FvCbPo8gb9kPAuDyj39tdzzgNK/Xvj8ym9RhUbTtBgbWujRCIWU0L6bfl
i7DLfJoPSK+s6S5YGr88VAz0y9zAGD/2wGq9R1hUSDw0OfMgEm9GoSz6FpXKKBtl
M01bP11akztK8sWChdels4OXOsPQ1SdF2XE4od82cm6lA8IgE1hY
-----END CERTIFICATE-----
`)
var DefaultTlsCertificatePrivate = []byte (`
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC+jojvRd7zso5q
PvriGVYRwBZZoScGbMyAm06ICAV8boHe8y5ITzhGjtrS6pXCQeqFg6sTrqMUGjya
g8E4EAGi9WkO00aNYYT7EWp/rT0wS5aWgM27h3rCAGN2Nxd9lnophyx+xy1yhF55
iWOC6PH6W9GA5EpLidac47Jjc73AlEzFrchORF9VTCVCBqakopwiTeJd1Gp0A63C
zpM7dVPBVnWmgMNLJhwpNbppChCaw4IMSBCH6nJhAlJUgSqIU/fZyOrjeikeid86
nKQCIvZ7syJFgm6vkTnEfZmZP1J6uw9wAIygK7UOIc8loa/F+Xr3eB/imBfqsNs9
ZM0mpamrAgMBAAECggEAORjSVQeVj2XAIHuwhtDapkTtLXwJCnbNK/fdJwtoQWmH
RnuNMaNzFEk3rh0WNHe1wr26JBKe0KYv5Ih3+8loBCEOkp+hszk2NFh6lbkd7Xuo
qn37pyYoFTsykjhdtIbDIfBb17zslDSvbjFJfO85mi+q7bj5vfqWMLpVOFF02N/S
SmASAzAYTAOE+wheMuTWkm8r3PXh8WhJViWLp/9l6gyLT0mOazxaVayOWyJ/pg1w
qPZiNOavTbNyP7jzUysA4LX9CdBQx3k48IQm0c59Zu49Rl7H6ZT9Vp2CSkvbZRZS
qVLKYtE4o5SIyAPI5QBCRyNVkHQnZAzPIv/vwbky4QKBgQDmcxY9YVIVpjZQCcVg
R++ClrjKKzuR4dmUvmF3H6F4uT6S+7zPsaaIbgBUo2B/Z5QZ+vv6FeKcGZhGSVzU
gtiQeNvEPE25oHbJm3ui71Wvw2mEpTp52bYL6k68b45ydq/CCpohSLym/WjlVVSz
ce2IJZaviGn68jY175bRRDAb2wKBgQDTrykGt8gfACmSBZcULkaXCDqT0nfnWccx
OHuimbIDgSU0Q/KJA9P0pSbtL/2rUXEnZpUJ0oDDEi0MpBkSX3Tb3U959aY97hXK
arHI0iziUcW1ZZ2XGO5KtRviQ0D5CKZWR1Ttjm1oCJkmxAag070CF/UdcTGEizrK
OeI7o1l6cQKBgBo21z3ON0ctLBp4shIcvLsPKCAfQNx8Y4LPEUk6uOSBtgOETVsW
60mzsafvGcgEYU1/RnCRUsDNDIxaRgwKglYU2XL+JR1Lipeubyb+sLGYugUTwo4f
3NyIH8LBseOFasLY7+V/X65jPy5vQX5UJGALXpPDIcMhEFecVHyjlBFnAoGABtWs
+W6No5KZxQExM5Ga7d1yJruw62NWrxwnwcQ8nyhYTyuydQIOoeODMj1Ob22dvavu
O/bz+Vho4/OYa6NxXnfyzPlFeNJrGbIAM3+1u0jwnT6+q9Y+O2NFlzScsG27ESYU
c+cZWTaN21aQ8Dhl7d9gJqc09haYu1bLGynXBcECgYEAsxgIbbO3CtxPfqgtJrAo
eRPPLX7UOdXmarOBYFL+jsG5SWSyECqKDgkjyeQFVqHzK+W4k654TobZoMUhDIUL
GeNAoNAIjPciush/0yYI8w3EybHIkB6JSi4LyhWBQazGaAr3Ai0NHbKt3ZzcOM1D
azCipM9H6CJO+MjoG+S53Xo=
-----END PRIVATE KEY-----
`)