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 }