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()

Reply via email to