From 0cc061dec85619cf4d911ef341df0793245ed13a Mon Sep 17 00:00:00 2001 From: Davide Garberi Date: Mon, 2 Mar 2026 09:43:27 +0100 Subject: [PATCH] :art: Fix network serving TLS on mobile devices (#17119) * Until now, the TLS would only work via the fixed port proxy, which isn't used on mobile devices. * Move the logic for the multiplexer out of the fixed port logic * Use the newly moved multiplexer logic for the regular server as well, whenever the fixed port and the server port match. --- kernel/server/proxy/fixedport.go | 36 +++------------------- kernel/server/serve.go | 15 +++++++++ kernel/util/cmux.go | 52 ++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 32 deletions(-) create mode 100644 kernel/util/cmux.go diff --git a/kernel/server/proxy/fixedport.go b/kernel/server/proxy/fixedport.go index 09d840a57..74711ac6e 100644 --- a/kernel/server/proxy/fixedport.go +++ b/kernel/server/proxy/fixedport.go @@ -18,6 +18,7 @@ package proxy import ( "crypto/tls" + "errors" "net" "net/http" "net/http/httputil" @@ -51,39 +52,10 @@ func InitFixedPortService(host string, useTLS bool, certPath, keyPath string) { return } - m := cmux.New(ln) - - // Match TLS connections (first byte 0x16 indicates TLS handshake) - tlsL := m.Match(cmux.TLS()) - // Match HTTP (anything else) - httpL := m.Match(cmux.Any()) - - cert, err := tls.LoadX509KeyPair(certPath, keyPath) - if err != nil { - logging.LogWarnf("failed to load TLS cert for fixed port service: %s", err) - ln.Close() - return - } - tlsConfig := &tls.Config{Certificates: []tls.Certificate{cert}} - - tlsListener := tls.NewListener(tlsL, tlsConfig) - - go func() { - httpServer := &http.Server{Handler: proxy} - if err := httpServer.Serve(httpL); err != nil && err != cmux.ErrListenerClosed { - logging.LogWarnf("fixed port HTTP server error: %s", err) + if serveErr := util.ServeMultiplexed(ln, proxy, certPath, keyPath, nil); serveErr != nil { + if serveErr != cmux.ErrListenerClosed && !errors.Is(serveErr, http.ErrServerClosed) { + logging.LogWarnf("fixed port cmux serve error: %s", serveErr) } - }() - - go func() { - httpsServer := &http.Server{Handler: proxy} - if err := httpsServer.Serve(tlsListener); err != nil && err != cmux.ErrListenerClosed { - logging.LogWarnf("fixed port HTTPS server error: %s", err) - } - }() - - if err := m.Serve(); err != nil && err != cmux.ErrListenerClosed { - logging.LogWarnf("fixed port cmux serve error: %s", err) } } else { logging.LogInfof("fixed port service [%s] is running", addr) diff --git a/kernel/server/serve.go b/kernel/server/serve.go index 702215dba..7e686b6dd 100644 --- a/kernel/server/serve.go +++ b/kernel/server/serve.go @@ -47,6 +47,7 @@ import ( "github.com/siyuan-note/siyuan/kernel/model" "github.com/siyuan-note/siyuan/kernel/server/proxy" "github.com/siyuan-note/siyuan/kernel/util" + "github.com/soheilhy/cmux" "golang.org/x/net/webdav" ) @@ -244,6 +245,20 @@ func Serve(fastMode bool, cookieKey string) { Handler: ginServer, } + if useTLS && (util.FixedPort == util.ServerPort || util.IsPortOpen(util.FixedPort)) { + if err = util.ServeMultiplexed(ln, ginServer, certPath, keyPath, util.HttpServer); err != nil { + if errors.Is(err, http.ErrServerClosed) || err == cmux.ErrListenerClosed { + return + } + + if !fastMode { + logging.LogErrorf("boot kernel failed: %s", err) + os.Exit(logging.ExitCodeUnavailablePort) + } + } + return + } + if err = util.HttpServer.Serve(ln); err != nil { if errors.Is(err, http.ErrServerClosed) { return diff --git a/kernel/util/cmux.go b/kernel/util/cmux.go new file mode 100644 index 000000000..abda8469d --- /dev/null +++ b/kernel/util/cmux.go @@ -0,0 +1,52 @@ +package util + +import ( + "crypto/tls" + "errors" + "net" + "net/http" + + "github.com/siyuan-note/logging" + "github.com/soheilhy/cmux" +) + +func ServeMultiplexed(ln net.Listener, handler http.Handler, certPath, keyPath string, httpServer *http.Server) error { + m := cmux.New(ln) + + tlsL := m.Match(cmux.TLS()) + httpL := m.Match(cmux.Any()) + + cert, err := tls.LoadX509KeyPair(certPath, keyPath) + if err != nil { + logging.LogErrorf("failed to load TLS cert for multiplexing: %s", err) + return err + } + + tlsConfig := &tls.Config{ + Certificates: []tls.Certificate{cert}, + } + + tlsListener := tls.NewListener(tlsL, tlsConfig) + + if httpServer == nil { + httpServer = &http.Server{Handler: handler} + } else { + httpServer.Handler = handler + } + + httpsServer := &http.Server{Handler: handler} + + go func() { + if serveErr := httpServer.Serve(httpL); serveErr != nil && serveErr != cmux.ErrListenerClosed && !errors.Is(serveErr, http.ErrServerClosed) { + logging.LogErrorf("multiplexed HTTP server error: %s", serveErr) + } + }() + + go func() { + if serveErr := httpsServer.Serve(tlsListener); serveErr != nil && serveErr != cmux.ErrListenerClosed && !errors.Is(serveErr, http.ErrServerClosed) { + logging.LogErrorf("multiplexed HTTPS server error: %s", serveErr) + } + }() + + return m.Serve() +}