github.com/chainreactors/fingers@v1.2.1/common/sender_tinygo.go (about)

     1  //go:build tinygo
     2  // +build tinygo
     3  
     4  package common
     5  
     6  import (
     7  	"crypto/tls"
     8  	"fmt"
     9  	"net"
    10  	"net/http"
    11  	"strconv"
    12  	"strings"
    13  	"time"
    14  )
    15  
    16  // ServiceSender abstracts service-level fingerprint requests.
    17  type ServiceSender interface {
    18  	Send(host string, portStr string, data []byte, network string) ([]byte, error)
    19  }
    20  
    21  // DefaultServiceSender sends TCP/UDP/TLS probes with a timeout.
    22  type DefaultServiceSender struct {
    23  	timeout time.Duration
    24  }
    25  
    26  func NewServiceSender(timeout time.Duration) ServiceSender {
    27  	if timeout <= 0 {
    28  		timeout = 5 * time.Second
    29  	}
    30  	return &DefaultServiceSender{timeout: timeout}
    31  }
    32  
    33  func (d *DefaultServiceSender) Send(host string, portStr string, data []byte, network string) ([]byte, error) {
    34  	port, actualNetwork := d.parsePortString(portStr, network)
    35  	target := fmt.Sprintf("%s:%d", host, port)
    36  
    37  	switch strings.ToLower(actualNetwork) {
    38  	case "tls", "ssl":
    39  		return d.sendTLS(target, data)
    40  	case "udp":
    41  		return d.sendUDP(target, data)
    42  	case "tcp", "":
    43  		return d.sendTCP(target, data)
    44  	default:
    45  		return d.sendTCP(target, data)
    46  	}
    47  }
    48  
    49  func (d *DefaultServiceSender) sendTCP(target string, data []byte) ([]byte, error) {
    50  	conn, err := net.DialTimeout("tcp", target, d.timeout)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  	defer conn.Close()
    55  
    56  	if len(data) > 0 {
    57  		conn.SetWriteDeadline(time.Now().Add(d.timeout))
    58  		_, err = conn.Write(data)
    59  		if err != nil {
    60  			return nil, err
    61  		}
    62  	}
    63  
    64  	conn.SetReadDeadline(time.Now().Add(d.timeout))
    65  	buffer := make([]byte, 10240)
    66  	n, err := conn.Read(buffer)
    67  	if n > 0 {
    68  		return buffer[:n], nil
    69  	}
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  	return buffer[:n], nil
    74  }
    75  
    76  func (d *DefaultServiceSender) sendTLS(target string, data []byte) ([]byte, error) {
    77  	conn, err := tls.DialWithDialer(&net.Dialer{Timeout: d.timeout}, "tcp", target, &tls.Config{
    78  		InsecureSkipVerify: true,
    79  	})
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  	defer conn.Close()
    84  
    85  	if len(data) > 0 {
    86  		conn.SetWriteDeadline(time.Now().Add(d.timeout))
    87  		_, err = conn.Write(data)
    88  		if err != nil {
    89  			return nil, err
    90  		}
    91  	}
    92  
    93  	conn.SetReadDeadline(time.Now().Add(d.timeout))
    94  	buffer := make([]byte, 10240)
    95  	n, err := conn.Read(buffer)
    96  	if n > 0 {
    97  		return buffer[:n], nil
    98  	}
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  	return buffer[:n], nil
   103  }
   104  
   105  func (d *DefaultServiceSender) sendUDP(target string, data []byte) ([]byte, error) {
   106  	conn, err := net.DialTimeout("udp", target, d.timeout)
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  	defer conn.Close()
   111  
   112  	if len(data) > 0 {
   113  		conn.SetWriteDeadline(time.Now().Add(d.timeout))
   114  		_, err = conn.Write(data)
   115  		if err != nil {
   116  			return nil, err
   117  		}
   118  	}
   119  
   120  	readTimeout := d.timeout
   121  	if readTimeout > 200*time.Millisecond {
   122  		readTimeout = 200 * time.Millisecond
   123  	}
   124  	conn.SetReadDeadline(time.Now().Add(readTimeout))
   125  
   126  	buffer := make([]byte, 10240)
   127  	n, err := conn.Read(buffer)
   128  	if n > 0 {
   129  		return buffer[:n], nil
   130  	}
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  	return buffer[:n], nil
   135  }
   136  
   137  func (d *DefaultServiceSender) parsePortString(portStr string, defaultNetwork string) (port int, network string) {
   138  	portStr = strings.TrimSpace(portStr)
   139  	network = defaultNetwork
   140  
   141  	if strings.HasPrefix(strings.ToUpper(portStr), "U:") {
   142  		portStr = portStr[2:]
   143  		network = "udp"
   144  	}
   145  
   146  	portNum, err := strconv.Atoi(portStr)
   147  	if err != nil {
   148  		return 80, network
   149  	}
   150  
   151  	return portNum, network
   152  }
   153  
   154  type ServiceCallback func(*ServiceResult)
   155  
   156  type DefaultHTTPSender struct {
   157  	client *http.Client
   158  }
   159  
   160  func NewHTTPSender(timeout time.Duration) http.RoundTripper {
   161  	if timeout <= 0 {
   162  		timeout = 10 * time.Second
   163  	}
   164  
   165  	return &DefaultHTTPSender{
   166  		client: &http.Client{
   167  			Transport: http.DefaultTransport,
   168  			Timeout:   timeout,
   169  		},
   170  	}
   171  }
   172  
   173  func (d *DefaultHTTPSender) RoundTrip(req *http.Request) (*http.Response, error) {
   174  	return d.client.Transport.RoundTrip(req)
   175  }