Saturday, December 14, 2024
HomeGolangGOGC dropping pointers allotted in C? - Code Overview

GOGC dropping pointers allotted in C? – Code Overview


Hello,

I’m making an attempt to get an https server working by overwriting the settle for/learn/write strategies within the http module. I’m utilizing go-wolfssl for TLS.

The server will settle for a TLS 1.2 connection, then ship some random knowledge to the consumer connects, then wait for an additional connection.

The difficulty that I’m seeing is that at any time when the server sends giant payloads, it’ll do this efficiently but it surely then can’t ship knowledge to the following consumer that connects (the ship errors out with the TCP error EBADF). If coping with smaller payloads (<30k), the server can ship knowledge efficiently to every consumer that connects. Then as quickly as a big one is shipped, the following transmission fails.

If I disable the GOGC with debug.SetGCPercent(-1), the problem goes away and I can ship as many giant payloads as required. From the debugging I’ve finished thus far, this appears like a difficulty with the GO rubbish collector dropping C pointers. go-wolfssl depends on the wolfSSL C library so it makes use of CGO. Does anybody have another concepts or enter?

Code is beneath. See this repo to really run it GitHub – lealem47/go-wolfssl-https-server

Thanks!

package deal most important

import (
	"bytes"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	log "github.com/sirupsen/logrus"
	wolfSSL "github.com/wolfssl/go-wolfssl"
	"web"
	"web/http"
	"os"
	"strconv"
	"sync"
	"time"
)

const defaultPort = "8443"

kind wolfSSLListener struct {
	listener web.Listener
	ctx      *wolfSSL.WOLFSSL_CTX
}

// Settle for waits for and returns the following connection to the listener.
func (cl *wolfSSLListener) Settle for() (web.Conn, error) {
	conn, err := cl.listener.Settle for()
	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.(*web.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("Shopper Efficiently Linked!")
	}

	return &wolfSSLConn{
		conn: conn,
		ssl:  ssl,
	}, nil
}

// Shut closes the listener, making it cease accepting new connections.
func (cl *wolfSSLListener) Shut() error {
	fmt.Println("Closing listener...")
	return cl.listener.Shut()
}

// Addr returns the listener's community handle.
func (cl *wolfSSLListener) Addr() web.Addr {
	return cl.listener.Addr()
}

kind wolfSSLConn struct {
	conn   web.Conn
	ssl    *wolfSSL.WOLFSSL
	buffer bytes.Buffer
	mu     sync.Mutex
	closed bool
}

func (w *wolfSSLConn) Learn(b []byte) (int, error) {
	log.Infof("Calling learn: %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("learn error: %d", errCode)
	}

	log.Infof("Learn 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) Shut() error {
	log.Infof("Closing connection")

	wolfSSL.WolfSSL_shutdown(w.ssl)
	wolfSSL.WolfSSL_free(w.ssl)
	return w.conn.Shut()
}

func (w *wolfSSLConn) LocalAddr() web.Addr {
	return w.conn.LocalAddr()
}

func (w *wolfSSLConn) RemoteAddr() web.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 producing and base64 encoding 5KB of random knowledge
func randomDataHandler(w http.ResponseWriter, r *http.Request) {
	// Get the "measurement" question parameter from the request
	sizeParam := r.URL.Question().Get("measurement")
	measurement := 500000 // default measurement

	// If the "measurement" parameter is offered, convert it to an integer
	if sizeParam != "" {
		parsedSize, err := strconv.Atoi(sizeParam)
		if err != nil || parsedSize <= 0 {
			http.Error(w, "Invalid measurement parameter", http.StatusBadRequest)
			return
		}
		measurement = parsedSize
	}

	// Generate random knowledge of the desired measurement
	knowledge := make([]byte, measurement)
	_, err := rand.Learn(knowledge)
	if err != nil {
		http.Error(w, "Couldn't generate random knowledge", http.StatusInternalServerError)
		return
	}

	// Base64 encode the random knowledge
	encodedData := base64.StdEncoding.EncodeToString(knowledge)

	// Set content material kind and write the base64 encoded knowledge
	w.Header().Set("Content material-Kind", "utility/base64")
	w.Write([]byte(encodedData))
}

func most important() {
	port := defaultPort

	// Set logging degree
	log.SetLevel(log.InfoLevel)

	log.SetFormatter(&log.TextFormatter{
		DisableColors: false,
		FullTimestamp: true,
	})

	// Arrange the HTTP server and routes
	http.HandleFunc("https://discussion board.golangbridge.org/", 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 := web.Hear("tcp", ":"+port)
	if err != nil {
		fmt.Println("Error beginning listener:", err)
		return
	}
	defer baseListener.Shut()

	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 beginning HTTP server:", err)
	}
}

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments