This is an automated email from the ASF dual-hosted git repository.
maciej pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iggy.git
The following commit(s) were added to refs/heads/master by this push:
new f6c415084 feat(go): implement TCP/TLS connection in Go SDK (#2834)
f6c415084 is described below
commit f6c415084878ba3bc492abac471e0f761dfc660b
Author: saie-ch <[email protected]>
AuthorDate: Thu Mar 5 14:37:35 2026 +0530
feat(go): implement TCP/TLS connection in Go SDK (#2834)
Closes #2824
---
foreign/go/client/tcp/tcp_core.go | 89 +++++++++++++++++++++++++++++++++++++--
1 file changed, 86 insertions(+), 3 deletions(-)
diff --git a/foreign/go/client/tcp/tcp_core.go
b/foreign/go/client/tcp/tcp_core.go
index 85a5da4ed..0d6073164 100644
--- a/foreign/go/client/tcp/tcp_core.go
+++ b/foreign/go/client/tcp/tcp_core.go
@@ -18,10 +18,13 @@
package tcp
import (
+ "crypto/tls"
+ "crypto/x509"
"encoding/binary"
- "errors"
"fmt"
"net"
+ "os"
+ "strings"
"sync"
"time"
@@ -141,6 +144,35 @@ func WithServerAddress(address string) Option {
}
}
+// WithTLS enables or disables TLS for the TCP client.
+func WithTLS(enabled bool) Option {
+ return func(opts *Options) {
+ opts.config.tlsEnabled = enabled
+ }
+}
+
+// WithTLSDomain sets the TLS domain for server name indication (SNI).
+// If empty, the domain will be automatically extracted from the server
address.
+func WithTLSDomain(domain string) Option {
+ return func(opts *Options) {
+ opts.config.tlsDomain = domain
+ }
+}
+
+// WithTLSCAFile sets the path to the CA certificate file for TLS verification.
+func WithTLSCAFile(path string) Option {
+ return func(opts *Options) {
+ opts.config.tlsCAFile = path
+ }
+}
+
+// WithTLSValidateCertificate enables or disables TLS certificate validation.
+func WithTLSValidateCertificate(validate bool) Option {
+ return func(opts *Options) {
+ opts.config.tlsValidateCertificate = validate
+ }
+}
+
// NewIggyTcpClient creates a new Iggy TCP client with the given options.
// warning: don't use this function directly, use iggycli.NewIggyClient with
iggycli.WithTcp instead.
func NewIggyTcpClient(options ...Option) (*IggyTcpClient, error) {
@@ -325,8 +357,20 @@ func (c *IggyTcpClient) connect() error {
return nil
}
- // TODO TLS logic
- return errors.New("TLS connection is not implemented
yet")
+ // TLS logic
+ tlsConfig, err := c.createTLSConfig()
+ if err != nil {
+ return err
+ }
+
+ tlsConn := tls.Client(connection, tlsConfig)
+ if err := tlsConn.Handshake(); err != nil {
+ connection.Close()
+ return fmt.Errorf("TLS handshake failed: %w",
err)
+ }
+
+ conn = tlsConn
+ return nil
},
retry.Attempts(uint(c.config.reconnection.maxRetries)),
retry.Delay(c.config.reconnection.interval),
@@ -342,6 +386,45 @@ func (c *IggyTcpClient) connect() error {
return nil
}
+func (c *IggyTcpClient) createTLSConfig() (*tls.Config, error) {
+ tlsConfig := &tls.Config{
+ InsecureSkipVerify: !c.config.tlsValidateCertificate,
+ }
+
+ // Set server name for SNI
+ serverName := c.config.tlsDomain
+ if serverName == "" {
+ // Extract hostname from server address (format: "host:port")
+ host := c.currentServerAddress
+ if colonIdx := strings.LastIndex(host, ":"); colonIdx != -1 {
+ host = host[:colonIdx]
+ }
+ serverName = host
+ }
+
+ if serverName == "" {
+ return nil, ierror.ErrInvalidTlsDomain
+ }
+ tlsConfig.ServerName = serverName
+
+ // Load CA certificate if provided
+ if c.config.tlsCAFile != "" {
+ caCert, err := os.ReadFile(c.config.tlsCAFile)
+ if err != nil {
+ return nil, ierror.ErrInvalidTlsCertificatePath
+ }
+
+ caCertPool := x509.NewCertPool()
+ if !caCertPool.AppendCertsFromPEM(caCert) {
+ return nil, ierror.ErrInvalidTlsCertificate
+ }
+
+ tlsConfig.RootCAs = caCertPool
+ }
+
+ return tlsConfig, nil
+}
+
func (c *IggyTcpClient) disconnect() error {
c.mtx.Lock()
defer c.mtx.Unlock()