feat: add DoT
This commit is contained in:
		
							parent
							
								
									9cf8968a82
								
							
						
					
					
						commit
						43281f26fe
					
				
							
								
								
									
										16
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								Makefile
									
									
									
									
									
								
							@ -1,3 +1,6 @@
 | 
				
			|||||||
 | 
					# Tested under Apple M1.
 | 
				
			||||||
 | 
					# Edit it if you use different platform.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PROJECT_NAME := comandy
 | 
					PROJECT_NAME := comandy
 | 
				
			||||||
BUILD_PATH := build
 | 
					BUILD_PATH := build
 | 
				
			||||||
GOOS := android
 | 
					GOOS := android
 | 
				
			||||||
@ -11,12 +14,12 @@ CGO_ENABLED := 1
 | 
				
			|||||||
GO_SRC := $(shell find . -name '*.go')
 | 
					GO_SRC := $(shell find . -name '*.go')
 | 
				
			||||||
NDK_TOOLCHAIN := ~/Library/Android/sdk/ndk/$(NDK_VERSION)/toolchains/llvm/prebuilt/$(BUILD_MACHINE)-$(BUILD_ARCH)
 | 
					NDK_TOOLCHAIN := ~/Library/Android/sdk/ndk/$(NDK_VERSION)/toolchains/llvm/prebuilt/$(BUILD_MACHINE)-$(BUILD_ARCH)
 | 
				
			||||||
CC := $(NDK_TOOLCHAIN)/bin/aarch64-linux-$(TARGET_SDK)-clang
 | 
					CC := $(NDK_TOOLCHAIN)/bin/aarch64-linux-$(TARGET_SDK)-clang
 | 
				
			||||||
TEST_OUTPUT = '$(shell cd $(BUILD_PATH) && ./test)'
 | 
					TEST_OUTPUT = '$(shell cd $(BUILD_PATH) && ./test | head -c 12)'
 | 
				
			||||||
TEST_EXPECTED = '{"code":500,"data":"aW52YWxpZCB1cmwgJyc="}'
 | 
					TEST_EXPECTED = '{"code":200,'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
all: shared
 | 
					all: shared
 | 
				
			||||||
 | 
					
 | 
				
			||||||
shared: $(GO_SRC) dir
 | 
					shared: $(GO_SRC) dir tidy
 | 
				
			||||||
	GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=$(CGO_ENABLED) NDK_TOOLCHAIN=$(NDK_TOOLCHAIN) CC=$(CC) go build -buildmode=c-shared -o $(BUILD_PATH)/lib$(PROJECT_NAME).so $(GO_SRC)
 | 
						GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=$(CGO_ENABLED) NDK_TOOLCHAIN=$(NDK_TOOLCHAIN) CC=$(CC) go build -buildmode=c-shared -o $(BUILD_PATH)/lib$(PROJECT_NAME).so $(GO_SRC)
 | 
				
			||||||
test: dir
 | 
					test: dir
 | 
				
			||||||
	@GOOS=$(BUILD_MACHINE) CC=cc NDK_TOOLCHAIN="" $(MAKE) -e shared
 | 
						@GOOS=$(BUILD_MACHINE) CC=cc NDK_TOOLCHAIN="" $(MAKE) -e shared
 | 
				
			||||||
@ -27,7 +30,12 @@ runtest: test
 | 
				
			|||||||
	else \
 | 
						else \
 | 
				
			||||||
		echo "test failed, expected:" $(TEST_EXPECTED) "but got:" $(TEST_OUTPUT); \
 | 
							echo "test failed, expected:" $(TEST_EXPECTED) "but got:" $(TEST_OUTPUT); \
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
 | 
					tidy:
 | 
				
			||||||
 | 
						go mod tidy
 | 
				
			||||||
dir:
 | 
					dir:
 | 
				
			||||||
	@if [ ! -d "$(BUILD_PATH)" ]; then mkdir $(BUILD_PATH); fi
 | 
						@if [ ! -d "$(BUILD_PATH)" ]; then mkdir $(BUILD_PATH); fi
 | 
				
			||||||
clean:
 | 
					clean:
 | 
				
			||||||
	@if [ -d "$(BUILD_PATH)" ]; then rm -rf $(BUILD_PATH)/lib$(PROJECT_NAME).*; fi
 | 
						@if [ -d "$(BUILD_PATH)" ]; then \
 | 
				
			||||||
 | 
							rm -rf $(BUILD_PATH)/lib$(PROJECT_NAME).*; \
 | 
				
			||||||
 | 
							rm -rf $(BUILD_PATH)/test; \
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,11 @@
 | 
				
			|||||||
#include "libcomandy.h"
 | 
					#include "libcomandy.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main() {
 | 
					int main() {
 | 
				
			||||||
    char* msg = request("{}");
 | 
					    puts(request("{\"method\":\"GET\","
 | 
				
			||||||
    puts(msg);
 | 
					        "\"url\":\"https://i.pximg.net/img-master/img/2012/04/04/21/24/46/26339586_p0_master1200.jpg\","
 | 
				
			||||||
 | 
					        "\"headers\":{"
 | 
				
			||||||
 | 
					            "\"Referer\":\"https://www.pixiv.net/\","
 | 
				
			||||||
 | 
					            "\"User-Agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0\""
 | 
				
			||||||
 | 
					        "}"
 | 
				
			||||||
 | 
					    "}"));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										138
									
								
								dns.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								dns.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,138 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"crypto/tls"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/fumiama/terasu"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type dnsstat struct {
 | 
				
			||||||
 | 
						A string
 | 
				
			||||||
 | 
						E bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type dnsservers struct {
 | 
				
			||||||
 | 
						sync.RWMutex
 | 
				
			||||||
 | 
						m map[string][]*dnsstat
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// hasrecord no lock, use under lock
 | 
				
			||||||
 | 
					func hasrecord(lst []*dnsstat, a string) bool {
 | 
				
			||||||
 | 
						for _, addr := range lst {
 | 
				
			||||||
 | 
							if addr.A == a {
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (ds *dnsservers) add(m map[string][]string) {
 | 
				
			||||||
 | 
						ds.Lock()
 | 
				
			||||||
 | 
						defer ds.Unlock()
 | 
				
			||||||
 | 
						addList := map[string][]*dnsstat{}
 | 
				
			||||||
 | 
						for host, addrs := range m {
 | 
				
			||||||
 | 
							for _, addr := range addrs {
 | 
				
			||||||
 | 
								if !hasrecord(ds.m[host], addr) && !hasrecord(addList[host], addr) {
 | 
				
			||||||
 | 
									addList[host] = append(addList[host], &dnsstat{addr, true})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for host, addrs := range addList {
 | 
				
			||||||
 | 
							ds.m[host] = append(ds.m[host], addrs...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (ds *dnsservers) dial(ctx context.Context) (tlsConn *tls.Conn, err error) {
 | 
				
			||||||
 | 
						ds.RLock()
 | 
				
			||||||
 | 
						defer ds.RUnlock()
 | 
				
			||||||
 | 
						var conn net.Conn
 | 
				
			||||||
 | 
						for host, addrs := range ds.m {
 | 
				
			||||||
 | 
							for _, addr := range addrs {
 | 
				
			||||||
 | 
								if !addr.E {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								conn, err = net.Dial("tcp", addr.A)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								tlsConn = terasu.Use(tls.Client(conn, &tls.Config{ServerName: host}))
 | 
				
			||||||
 | 
								err = tlsConn.HandshakeContext(ctx)
 | 
				
			||||||
 | 
								if err == nil {
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								addr.E = false // no need to acquire write lock
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var dotv6servers = dnsservers{
 | 
				
			||||||
 | 
						m: map[string][]*dnsstat{
 | 
				
			||||||
 | 
							"dns.alidns.com": {
 | 
				
			||||||
 | 
								{"[2400:3200::1]:853", true},
 | 
				
			||||||
 | 
								{"[2400:3200:baba::1]:853", true},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"dot.sb": {
 | 
				
			||||||
 | 
								{"[2a09::]:853", true},
 | 
				
			||||||
 | 
								{"[2a11::]:853", true},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"dns.google": {
 | 
				
			||||||
 | 
								{"[2001:4860:4860::8888]:853", true},
 | 
				
			||||||
 | 
								{"[2001:4860:4860::8844]:853", true},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"cloudflare-dns.com": {
 | 
				
			||||||
 | 
								{"[2606:4700:4700::1111]:853", true},
 | 
				
			||||||
 | 
								{"[2606:4700:4700::1001]:853", true},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"dns.umbrella.com": {
 | 
				
			||||||
 | 
								{"[2620:0:ccc::2]:853", true},
 | 
				
			||||||
 | 
								{"[2620:0:ccd::2]:853", true},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"dns10.quad9.net": {
 | 
				
			||||||
 | 
								{"[2620:fe::10]:853", true},
 | 
				
			||||||
 | 
								{"[2620:fe::fe:10]:853", true},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var dotv4servers = dnsservers{
 | 
				
			||||||
 | 
						m: map[string][]*dnsstat{
 | 
				
			||||||
 | 
							"dns.alidns.com": {
 | 
				
			||||||
 | 
								{"223.5.5.5:853", true},
 | 
				
			||||||
 | 
								{"223.6.6.6:853", true},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"dot.sb": {
 | 
				
			||||||
 | 
								{"185.222.222.222:853", true},
 | 
				
			||||||
 | 
								{"45.11.45.11:853", true},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"dns.google": {
 | 
				
			||||||
 | 
								{"8.8.8.8:853", true},
 | 
				
			||||||
 | 
								{"8.8.4.4:853", true},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"cloudflare-dns.com": {
 | 
				
			||||||
 | 
								{"1.1.1.1:853", true},
 | 
				
			||||||
 | 
								{"1.0.0.1:853", true},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"dns.umbrella.com": {
 | 
				
			||||||
 | 
								{"208.67.222.222:853", true},
 | 
				
			||||||
 | 
								{"208.67.220.220:853", true},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"dns10.quad9.net": {
 | 
				
			||||||
 | 
								{"9.9.9.10:853", true},
 | 
				
			||||||
 | 
								{"149.112.112.10:853", true},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var resolver = &net.Resolver{
 | 
				
			||||||
 | 
						PreferGo: true,
 | 
				
			||||||
 | 
						Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
 | 
				
			||||||
 | 
							if canUseIPv6.Get() {
 | 
				
			||||||
 | 
								return dotv6servers.dial(ctx)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return dotv4servers.dial(ctx)
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										51
									
								
								dns_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								dns_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"crypto/tls"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/fumiama/terasu"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestResolver(t *testing.T) {
 | 
				
			||||||
 | 
						t.Log("canUseIPv6:", canUseIPv6.Get())
 | 
				
			||||||
 | 
						addrs, err := resolver.LookupHost(context.TODO(), "dns.google")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t.Log(addrs)
 | 
				
			||||||
 | 
						t.Fail()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestDNS(t *testing.T) {
 | 
				
			||||||
 | 
						if canUseIPv6.Get() {
 | 
				
			||||||
 | 
							dotv6servers.test(t)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						dotv4servers.test(t)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (ds *dnsservers) test(t *testing.T) {
 | 
				
			||||||
 | 
						ds.RLock()
 | 
				
			||||||
 | 
						defer ds.RUnlock()
 | 
				
			||||||
 | 
						for host, addrs := range ds.m {
 | 
				
			||||||
 | 
							for _, addr := range addrs {
 | 
				
			||||||
 | 
								if !addr.E {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								conn, err := net.Dial("tcp", addr.A)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								tlsConn := terasu.Use(tls.Client(conn, &tls.Config{ServerName: host}))
 | 
				
			||||||
 | 
								err = tlsConn.Handshake()
 | 
				
			||||||
 | 
								_ = tlsConn.Close()
 | 
				
			||||||
 | 
								if err == nil {
 | 
				
			||||||
 | 
									t.Log("succ:", host, addr.A)
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								t.Fatal("fail:", host, addr.A)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										5
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								go.mod
									
									
									
									
									
								
							@ -2,4 +2,7 @@ module comandy
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
go 1.22.1
 | 
					go 1.22.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require github.com/fumiama/terasu v0.0.0-20240414143030-44fae3a81905
 | 
					require (
 | 
				
			||||||
 | 
						github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e
 | 
				
			||||||
 | 
						github.com/fumiama/terasu v0.0.0-20240414143030-44fae3a81905
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							@ -1,2 +1,4 @@
 | 
				
			|||||||
 | 
					github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e h1:wR3MXQ3VbUlPKOOUwLOYgh/QaJThBTYtsl673O3lqSA=
 | 
				
			||||||
 | 
					github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w=
 | 
				
			||||||
github.com/fumiama/terasu v0.0.0-20240414143030-44fae3a81905 h1:PHf84+ujLpFGJbfytrwZT6/D7KojmjFm5Itv6te6WUA=
 | 
					github.com/fumiama/terasu v0.0.0-20240414143030-44fae3a81905 h1:PHf84+ujLpFGJbfytrwZT6/D7KojmjFm5Itv6te6WUA=
 | 
				
			||||||
github.com/fumiama/terasu v0.0.0-20240414143030-44fae3a81905/go.mod h1:BFl0X1+rGJf8bLHl/kO+v05ryHrj/R4kyCrK89NvegA=
 | 
					github.com/fumiama/terasu v0.0.0-20240414143030-44fae3a81905/go.mod h1:BFl0X1+rGJf8bLHl/kO+v05ryHrj/R4kyCrK89NvegA=
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										61
									
								
								http.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								http.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"crypto/tls"
 | 
				
			||||||
 | 
						"encoding/base64"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/fumiama/terasu"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var dialer = net.Dialer{
 | 
				
			||||||
 | 
						Timeout: time.Minute,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var cli = http.Client{
 | 
				
			||||||
 | 
						Transport: &http.Transport{
 | 
				
			||||||
 | 
							DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
 | 
				
			||||||
 | 
								conn, err := dialer.DialContext(ctx, "tcp", addr)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								host, _, err := net.SplitHostPort(addr)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return terasu.Use(tls.Client(conn, &tls.Config{
 | 
				
			||||||
 | 
									ServerName:         host,
 | 
				
			||||||
 | 
									InsecureSkipVerify: true,
 | 
				
			||||||
 | 
								})), nil
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type capsule struct {
 | 
				
			||||||
 | 
						C int            `json:"code,omitempty"`
 | 
				
			||||||
 | 
						M string         `json:"method,omitempty"`
 | 
				
			||||||
 | 
						U string         `json:"url,omitempty"`
 | 
				
			||||||
 | 
						H map[string]any `json:"headers,omitempty"`
 | 
				
			||||||
 | 
						D string         `json:"data,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *capsule) printerr(err error) string {
 | 
				
			||||||
 | 
						buf := strings.Builder{}
 | 
				
			||||||
 | 
						r.C = http.StatusInternalServerError
 | 
				
			||||||
 | 
						r.D = base64.StdEncoding.EncodeToString(stringToBytes(err.Error()))
 | 
				
			||||||
 | 
						_ = json.NewEncoder(&buf).Encode(r)
 | 
				
			||||||
 | 
						return buf.String()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *capsule) printstrerr(err string) string {
 | 
				
			||||||
 | 
						buf := strings.Builder{}
 | 
				
			||||||
 | 
						r.C = http.StatusInternalServerError
 | 
				
			||||||
 | 
						r.D = base64.StdEncoding.EncodeToString(stringToBytes(err))
 | 
				
			||||||
 | 
						_ = json.NewEncoder(&buf).Encode(r)
 | 
				
			||||||
 | 
						return buf.String()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										16
									
								
								ipv6.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								ipv6.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/RomiChan/syncx"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var canUseIPv6 = syncx.Lazy[bool]{Init: func() bool {
 | 
				
			||||||
 | 
						resp, err := http.Get("http://v6.ipv6-test.com/json/widgetdata.php?callback=?")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_ = resp.Body.Close()
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}}
 | 
				
			||||||
							
								
								
									
										87
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										87
									
								
								main.go
									
									
									
									
									
								
							@ -3,69 +3,46 @@ package main
 | 
				
			|||||||
import "C"
 | 
					import "C"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
	"crypto/tls"
 | 
					 | 
				
			||||||
	"encoding/base64"
 | 
						"encoding/base64"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"net"
 | 
					 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/fumiama/terasu"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {}
 | 
					func main() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var dialer = net.Dialer{
 | 
					// para: json of map[host string][]addr:port string
 | 
				
			||||||
	Timeout: time.Minute,
 | 
					//
 | 
				
			||||||
}
 | 
					//export add_dns
 | 
				
			||||||
 | 
					func add_dns(para *C.char, is_ipv6 C.int) *C.char {
 | 
				
			||||||
var cli = http.Client{
 | 
						m := map[string][]string{}
 | 
				
			||||||
	Transport: &http.Transport{
 | 
						err := json.Unmarshal(stringToBytes(C.GoString(para)), &m)
 | 
				
			||||||
		DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
 | 
						if err != nil {
 | 
				
			||||||
			conn, err := dialer.DialContext(ctx, "tcp", addr)
 | 
							return C.CString(err.Error())
 | 
				
			||||||
			if err != nil {
 | 
						}
 | 
				
			||||||
				return nil, err
 | 
						if is_ipv6 != 0 {
 | 
				
			||||||
			}
 | 
							if !canUseIPv6.Get() {
 | 
				
			||||||
			host, _, err := net.SplitHostPort(addr)
 | 
								return C.CString("cannot use ipv6")
 | 
				
			||||||
			if err != nil {
 | 
							}
 | 
				
			||||||
				return nil, err
 | 
							dotv6servers.add(m)
 | 
				
			||||||
			}
 | 
							return nil
 | 
				
			||||||
			return terasu.Use(tls.Client(conn, &tls.Config{
 | 
						}
 | 
				
			||||||
				ServerName:         host,
 | 
						dotv4servers.add(m)
 | 
				
			||||||
				InsecureSkipVerify: true,
 | 
						return nil
 | 
				
			||||||
			})), nil
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type capsule struct {
 | 
					 | 
				
			||||||
	C int            `json:"code,omitempty"`
 | 
					 | 
				
			||||||
	M string         `json:"method,omitempty"`
 | 
					 | 
				
			||||||
	U string         `json:"url,omitempty"`
 | 
					 | 
				
			||||||
	H map[string]any `json:"headers,omitempty"`
 | 
					 | 
				
			||||||
	D string         `json:"data,omitempty"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *capsule) printerr(err error) string {
 | 
					 | 
				
			||||||
	buf := strings.Builder{}
 | 
					 | 
				
			||||||
	r.C = http.StatusInternalServerError
 | 
					 | 
				
			||||||
	r.D = base64.StdEncoding.EncodeToString(stringToBytes(err.Error()))
 | 
					 | 
				
			||||||
	_ = json.NewEncoder(&buf).Encode(r)
 | 
					 | 
				
			||||||
	return buf.String()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *capsule) printstrerr(err string) string {
 | 
					 | 
				
			||||||
	buf := strings.Builder{}
 | 
					 | 
				
			||||||
	r.C = http.StatusInternalServerError
 | 
					 | 
				
			||||||
	r.D = base64.StdEncoding.EncodeToString(stringToBytes(err))
 | 
					 | 
				
			||||||
	_ = json.NewEncoder(&buf).Encode(r)
 | 
					 | 
				
			||||||
	return buf.String()
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// para:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//	request("{\"method\":\"GET\","
 | 
				
			||||||
 | 
					//		"\"url\":\"https://i.pximg.net/img-master/img/2012/04/04/21/24/46/26339586_p0_master1200.jpg\","
 | 
				
			||||||
 | 
					//		"\"headers\":{"
 | 
				
			||||||
 | 
					//			"\"Referer\":\"https://www.pixiv.net/\","
 | 
				
			||||||
 | 
					//			"\"User-Agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0\""
 | 
				
			||||||
 | 
					//		"}"
 | 
				
			||||||
 | 
					//	"}");
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
//export request
 | 
					//export request
 | 
				
			||||||
func request(para *C.char) *C.char {
 | 
					func request(para *C.char) *C.char {
 | 
				
			||||||
	r := capsule{}
 | 
						r := capsule{}
 | 
				
			||||||
@ -73,13 +50,17 @@ func request(para *C.char) *C.char {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return C.CString(r.printerr(err))
 | 
							return C.CString(r.printerr(err))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if r.U == "" || !strings.HasPrefix(r.U, "http") {
 | 
						if r.U == "" || !strings.HasPrefix(r.U, "https://") {
 | 
				
			||||||
		return C.CString(r.printstrerr("invalid url '" + r.U + "'"))
 | 
							return C.CString(r.printstrerr("invalid url '" + r.U + "'"))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if r.M != "GET" && r.M != "POST" && r.M != "DELETE" {
 | 
						if r.M != "GET" && r.M != "POST" && r.M != "DELETE" {
 | 
				
			||||||
		return C.CString(r.printstrerr("invalid method '" + r.U + "'"))
 | 
							return C.CString(r.printstrerr("invalid method '" + r.U + "'"))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	req, err := http.NewRequest(r.M, r.U, strings.NewReader(r.D))
 | 
						var body io.Reader
 | 
				
			||||||
 | 
						if len(r.D) > 0 {
 | 
				
			||||||
 | 
							body = strings.NewReader(r.D)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						req, err := http.NewRequest(r.M, r.U, body)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return C.CString(r.printerr(err))
 | 
							return C.CString(r.printerr(err))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user