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.