github.com/iDigitalFlame/xmt@v0.5.4/com/tcp.go (about)

     1  // Copyright (C) 2020 - 2023 iDigitalFlame
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU General Public License as published by
     5  // the Free Software Foundation, either version 3 of the License, or
     6  // any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU General Public License
    14  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    15  //
    16  
    17  package com
    18  
    19  import (
    20  	"context"
    21  	"crypto/tls"
    22  	"net"
    23  	"time"
    24  )
    25  
    26  type tcpClient struct {
    27  	c tcpConnector
    28  }
    29  type tcpListener struct {
    30  	_ [0]func()
    31  	net.Listener
    32  	timeout time.Duration
    33  }
    34  type tcpConnector struct {
    35  	tls *tls.Config
    36  	net.Dialer
    37  }
    38  
    39  // NewTCP creates a new simple TCP based connector with the supplied timeout.
    40  func NewTCP(t time.Duration) Connector {
    41  	if t < 0 {
    42  		t = DefaultTimeout
    43  	}
    44  	return &tcpConnector{Dialer: net.Dialer{Timeout: t, KeepAlive: t}}
    45  }
    46  func (t *tcpListener) Accept() (net.Conn, error) {
    47  	if d, ok := t.Listener.(deadliner); ok {
    48  		d.SetDeadline(time.Now().Add(t.timeout))
    49  	}
    50  	c, err := t.Listener.Accept()
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  	return c, nil
    55  }
    56  
    57  // NewTLS creates a new simple TLS wrapped TCP based connector with the supplied
    58  // timeout.
    59  func NewTLS(t time.Duration, c *tls.Config) Connector {
    60  	if t < 0 {
    61  		t = DefaultTimeout
    62  	}
    63  	return &tcpConnector{tls: c, Dialer: net.Dialer{Timeout: t, KeepAlive: t}}
    64  }
    65  func (t tcpClient) Connect(x context.Context, s string) (net.Conn, error) {
    66  	return t.c.Connect(x, s)
    67  }
    68  func (t *tcpConnector) Connect(x context.Context, s string) (net.Conn, error) {
    69  	c, err := newStreamConn(x, NameTCP, s, t)
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  	return c, nil
    74  }
    75  func (t *tcpConnector) Listen(x context.Context, s string) (net.Listener, error) {
    76  	c, err := newStreamListener(x, NameTCP, s, t)
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	return &tcpListener{timeout: t.Timeout, Listener: c}, nil
    81  }
    82  func newStreamListener(x context.Context, n, s string, t *tcpConnector) (net.Listener, error) {
    83  	if t.tls != nil && (len(t.tls.Certificates) == 0 || t.tls.GetCertificate == nil) {
    84  		return nil, ErrInvalidTLSConfig
    85  	}
    86  	l, err := ListenConfig.Listen(x, n, s)
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  	if t.tls == nil {
    91  		return l, nil
    92  	}
    93  	return tls.NewListener(l, t.tls), nil
    94  }