Apologies - didn’t look closely - it doesn’t appear the buffer in the 
connection is used at all. I suspect though if you read the wolfssl api that 
the implementation may be async - meaning the data must remain referenced until 
it is sent.

> On Dec 2, 2024, at 11:38 AM, robert engels <reng...@ix.netcom.com> wrote:
> 
> 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/1C648B56-431C-4D62-A010-023F21B5830A%40ix.netcom.com.

Reply via email to