Friday, December 13, 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 information to the consumer connects, then wait for one more connection.

The problem that I’m seeing is that each time the server sends massive payloads, it’ll try this efficiently but it surely then can’t ship information to the subsequent consumer that connects (the ship errors out with the TCP error EBADF). If coping with smaller payloads (<30k), the server can ship information efficiently to every consumer that connects. Then as quickly as a big one is distributed, the subsequent transmission fails.

If I disable the GOGC with debug.SetGCPercent(-1), the problem goes away and I can ship as many massive payloads as required. From the debugging I’ve achieved to date, 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 truly run it GitHub – lealem47/go-wolfssl-https-server

Thanks!

bundle fundamental

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"

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

// Settle for waits for and returns the subsequent 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("Consumer 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 deal with.
func (cl *wolfSSLListener) Addr() web.Addr {
	return cl.listener.Addr()
}

sort 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 information
func randomDataHandler(w http.ResponseWriter, r *http.Request) {
	// Get the "dimension" question parameter from the request
	sizeParam := r.URL.Question().Get("dimension")
	dimension := 500000 // default dimension

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

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

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

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

func fundamental() {
	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.Pay attention("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