You are using the same buffer for reading and writing - I suspect that is your 
problem...

> On Dec 2, 2024, at 11:00 AM, Lealem Amedie <lealemt...@gmail.com> wrote:
> 
> Hi,
> 
> I’m trying to get an https server working by overwriting the 
> accept/read/write methods in the http module. I’m using go-wolfssl for TLS.
> 
> The server will accept a TLS 1.2 connection, then send some random data to 
> the client connects, then wait for another connection.
> 
> The issue that I’m seeing is that whenever the server sends large payloads, 
> it’ll do that successfully but it then can’t send data to the next client 
> that connects (the send errors out with the TCP error EBADF). If dealing with 
> smaller payloads (<30k), the server can send data successfully to each client 
> that connects. Then as soon as a large one is sent, the next transmission 
> fails.
> 
> If I disable the GOGC with debug.SetGCPercent(-1), the issue goes away and I 
> can send as many large payloads as required. From the debugging I’ve done so 
> far, this looks like an issue with the GO garbage collector dropping C 
> pointers. go-wolfssl relies on the wolfSSL C library so it uses CGO. Does 
> anyone have any other ideas or input?
> 
> Code is below. See this repo to actually run it GitHub - 
> lealem47/go-wolfssl-https-server  
> <https://github.com/lealem47/go-wolfssl-https-server/>
> Thank you!
> 
> 
> 
> ```
> 
> package main
> 
> import (
>       "bytes"
>       "crypto/rand"
>       "encoding/base64"
>       "fmt"
>       log "github.com/sirupsen/logrus"
>       wolfSSL "github.com/wolfssl/go-wolfssl"
>       "net"
>       "net/http"
>       "os"
>       "strconv"
>       "sync"
>       "time"
> )
> 
> const defaultPort = "8443"
> 
> type wolfSSLListener struct {
>       listener net.Listener
>       ctx      *wolfSSL.WOLFSSL_CTX
> }
> 
> // Accept waits for and returns the next connection to the listener.
> func (cl *wolfSSLListener) Accept() (net.Conn, error) {
>       conn, err := cl.listener.Accept()
>       if err != nil {
>               return nil, err
>       }
>       fmt.Println("Accepted new connection from:", conn.RemoteAddr())
> 
>       ssl := wolfSSL.WolfSSL_new(cl.ctx)
>       if ssl == nil {
>               fmt.Println("WolfSSL_new Failed")
>               os.Exit(1)
>       }
> 
>       file, err := conn.(*net.TCPConn).File()
>       if err != nil {
>               panic(err)
>       }
>       fd := file.Fd()
>       wolfSSL.WolfSSL_set_fd(ssl, int(fd))
> 
>       ret := wolfSSL.WolfSSL_accept(ssl)
>       if ret != wolfSSL.WOLFSSL_SUCCESS {
>               fmt.Println("WolfSSL_accept error ", ret)
>       } else {
>               fmt.Println("Client Successfully Connected!")
>       }
> 
>       return &wolfSSLConn{
>               conn: conn,
>               ssl:  ssl,
>       }, nil
> }
> 
> // Close closes the listener, making it stop accepting new connections.
> func (cl *wolfSSLListener) Close() error {
>       fmt.Println("Closing listener...")
>       return cl.listener.Close()
> }
> 
> // Addr returns the listener's network address.
> func (cl *wolfSSLListener) Addr() net.Addr {
>       return cl.listener.Addr()
> }
> 
> type wolfSSLConn struct {
>       conn   net.Conn
>       ssl    *wolfSSL.WOLFSSL
>       buffer bytes.Buffer
>       mu     sync.Mutex
>       closed bool
> }
> 
> func (w *wolfSSLConn) Read(b []byte) (int, error) {
>       log.Infof("Calling read: %d", len(b))
> 
>       ret := wolfSSL.WolfSSL_read(w.ssl, b, uintptr(len(b)))
>       if ret < 0 {
>               errCode := wolfSSL.WolfSSL_get_error(w.ssl, int(ret))
>               return 0, fmt.Errorf("read error: %d", errCode)
>       }
> 
>       log.Infof("Read bytes: %s", string(b[:ret]))
>       return int(ret), nil
> }
> 
> func (w *wolfSSLConn) Write(b []byte) (int, error) {
>       log.Infof("Calling write: %d", len(b))
> 
>       sz := uintptr(len(b))
> 
>       ret := wolfSSL.WolfSSL_write(w.ssl, b, sz)
>       if ret < 0 {
>               errCode := wolfSSL.WolfSSL_get_error(w.ssl, int(ret))
>               return 0, fmt.Errorf("write error: %d", errCode)
>       }
> 
>       return int(ret), nil
> }
> 
> func (w *wolfSSLConn) Close() error {
>       log.Infof("Closing connection")
> 
>       wolfSSL.WolfSSL_shutdown(w.ssl)
>       wolfSSL.WolfSSL_free(w.ssl)
>       return w.conn.Close()
> }
> 
> func (w *wolfSSLConn) LocalAddr() net.Addr {
>       return w.conn.LocalAddr()
> }
> 
> func (w *wolfSSLConn) RemoteAddr() net.Addr {
>       return w.conn.RemoteAddr()
> }
> 
> func (w *wolfSSLConn) SetDeadline(t time.Time) error {
>       return w.conn.SetDeadline(t)
> }
> 
> func (w *wolfSSLConn) SetReadDeadline(t time.Time) error {
>       return w.conn.SetReadDeadline(t)
> }
> 
> func (w *wolfSSLConn) SetWriteDeadline(t time.Time) error {
>       return w.conn.SetWriteDeadline(t)
> }
> 
> // Handler for generating and base64 encoding 5KB of random data
> func randomDataHandler(w http.ResponseWriter, r *http.Request) {
>       // Get the "size" query parameter from the request
>       sizeParam := r.URL.Query().Get("size")
>       size := 500000 // default size
> 
>       // If the "size" parameter is provided, convert it to an integer
>       if sizeParam != "" {
>               parsedSize, err := strconv.Atoi(sizeParam)
>               if err != nil || parsedSize <= 0 {
>                       http.Error(w, "Invalid size parameter", 
> http.StatusBadRequest)
>                       return
>               }
>               size = parsedSize
>       }
> 
>       // Generate random data of the specified size
>       data := make([]byte, size)
>       _, err := rand.Read(data)
>       if err != nil {
>               http.Error(w, "Could not generate random data", 
> http.StatusInternalServerError)
>               return
>       }
> 
>       // Base64 encode the random data
>       encodedData := base64.StdEncoding.EncodeToString(data)
> 
>       // Set content type and write the base64 encoded data
>       w.Header().Set("Content-Type", "application/base64")
>       w.Write([]byte(encodedData))
> }
> 
> func main() {
>       port := defaultPort
> 
>       // Set logging level
>       log.SetLevel(log.InfoLevel)
> 
>       log.SetFormatter(&log.TextFormatter{
>               DisableColors: false,
>               FullTimestamp: true,
>       })
> 
>       // Set up the HTTP server and routes
>       http.HandleFunc("/", randomDataHandler)
> 
>       CERT_FILE := "./certs/server-cert.pem"
>       KEY_FILE := "./certs/server-key.pem"
> 
>       /* Initialize wolfSSL */
>       wolfSSL.WolfSSL_Init()
> 
>       /* Create WOLFSSL_CTX with tlsv12 */
>       ctx := wolfSSL.WolfSSL_CTX_new(wolfSSL.WolfTLSv1_2_server_method())
>       if ctx == nil {
>               fmt.Println(" WolfSSL_CTX_new Failed")
>               os.Exit(1)
>       }
> 
>       /* Load server certificates into WOLFSSL_CTX */
>       ret := wolfSSL.WolfSSL_CTX_use_certificate_file(ctx, CERT_FILE, 
> wolfSSL.SSL_FILETYPE_PEM)
>       if ret != wolfSSL.WOLFSSL_SUCCESS {
>               fmt.Println("Error: WolfSSL_CTX_use_certificate Failed")
>               os.Exit(1)
>       }
> 
>       /* Load server key into WOLFSSL_CTX */
>       ret = wolfSSL.WolfSSL_CTX_use_PrivateKey_file(ctx, KEY_FILE, 
> wolfSSL.SSL_FILETYPE_PEM)
>       if ret != wolfSSL.WOLFSSL_SUCCESS {
>               fmt.Println("Error: WolfSSL_CTX_use_PrivateKey Failed")
>               os.Exit(1)
>       }
> 
>       baseListener, err := net.Listen("tcp", ":"+port)
>       if err != nil {
>               fmt.Println("Error starting listener:", err)
>               return
>       }
>       defer baseListener.Close()
> 
>       wolfSSLListener := &wolfSSLListener{
>               listener: baseListener,
>               ctx:      ctx,
>       }
> 
>       log.Printf("Server listening on https://localhost:%s";, port)
>       err = http.Serve(wolfSSLListener, nil)
>       if err != nil {
>               fmt.Println("Error starting HTTP server:", err)
>       }
> }
> 
> ```
> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to golang-nuts+unsubscr...@googlegroups.com 
> <mailto:golang-nuts+unsubscr...@googlegroups.com>.
> To view this discussion visit 
> https://groups.google.com/d/msgid/golang-nuts/a662824b-3555-4143-bfd8-b3431b7dc942n%40googlegroups.com
>  
> <https://groups.google.com/d/msgid/golang-nuts/a662824b-3555-4143-bfd8-b3431b7dc942n%40googlegroups.com?utm_medium=email&utm_source=footer>.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/golang-nuts/2E25F2BC-8954-4F77-BD4A-A9536CF4A89D%40ix.netcom.com.

Reply via email to