Skip to content

Commit 4f15050

Browse files
committed
2025-08-19 23:01:26
1 parent bcc213b commit 4f15050

File tree

2 files changed

+173
-0
lines changed

2 files changed

+173
-0
lines changed

protocol/etch/cmd/main.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/binary"
7+
"flag"
8+
"log"
9+
"net"
10+
"net/url"
11+
"time"
12+
13+
"github.com/mohanson/daze/lib/doa"
14+
"github.com/mohanson/daze/protocol/etch"
15+
)
16+
17+
func main() {
18+
flag.Parse()
19+
switch flag.Arg(0) {
20+
case "server":
21+
server := etch.Server{}
22+
server.Run()
23+
select {}
24+
case "client":
25+
// client := etch.NewClient()
26+
// log.Println(client.DnsQuery())
27+
r := ResolverDoh("http://127.0.0.1:8080")
28+
log.Println(r.LookupHost(context.Background(), "baidu.com"))
29+
}
30+
}
31+
32+
// Cdoh structure can be used for DoH protocol processing.
33+
type Cdoh struct {
34+
Server string
35+
Buffer *bytes.Buffer
36+
}
37+
38+
func (c Cdoh) Read(b []byte) (n int, err error) { return c.Buffer.Read(b) }
39+
func (c Cdoh) Close() error { return nil }
40+
func (c Cdoh) LocalAddr() net.Addr { return nil }
41+
func (c Cdoh) RemoteAddr() net.Addr { return nil }
42+
func (c Cdoh) SetDeadline(t time.Time) error { return nil }
43+
func (c Cdoh) SetReadDeadline(t time.Time) error { return nil }
44+
func (c Cdoh) SetWriteDeadline(t time.Time) error { return nil }
45+
func (c Cdoh) Write(b []byte) (n int, err error) {
46+
size := int(binary.BigEndian.Uint16(b[:2]))
47+
doa.Doa(size == len(b)-2)
48+
49+
client := etch.NewClient("127.0.0.1:8080")
50+
body := client.DnsQuery(b[2:])
51+
52+
// resp, err := http.Post(c.Server, "application/dns-message", bytes.NewReader(b[2:]))
53+
// if err != nil {
54+
// log.Println("cdoh:", err)
55+
// return len(b), nil
56+
// }
57+
// body, err := io.ReadAll(resp.Body)
58+
// if err != nil {
59+
// log.Println("cdoh:", err)
60+
// return len(b), nil
61+
// }
62+
data := make([]byte, 2+len(body))
63+
binary.BigEndian.PutUint16(data[:2], uint16(len(body)))
64+
copy(data[2:], body)
65+
c.Buffer.Write(data)
66+
return len(b), nil
67+
}
68+
69+
// ResolverDoh returns a DoH resolver. For further information, see https://datatracker.ietf.org/doc/html/rfc8484.
70+
func ResolverDoh(addr string) *net.Resolver {
71+
urls := doa.Try(url.Parse(addr))
72+
host := doa.Try(net.LookupHost(urls.Hostname()))[0]
73+
port := urls.Port()
74+
urls.Host = host
75+
if port != "" {
76+
urls.Host = host + ":" + port
77+
}
78+
return &net.Resolver{
79+
PreferGo: true,
80+
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
81+
conn := &Cdoh{
82+
Server: urls.String(),
83+
Buffer: bytes.NewBuffer([]byte{}),
84+
}
85+
return conn, nil
86+
},
87+
}
88+
}

protocol/etch/engine.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package etch
2+
3+
import (
4+
"bytes"
5+
"io"
6+
"net/http"
7+
"net/rpc"
8+
9+
"github.com/mohanson/daze/lib/doa"
10+
)
11+
12+
type Etch struct{}
13+
14+
func (m *Etch) DnsQuery(arg []byte, ret *[]byte) error {
15+
r, err := http.Post("https://1.1.1.1/dns-query", "application/dns-message", bytes.NewReader(arg))
16+
if err != nil {
17+
return err
18+
}
19+
b, err := io.ReadAll(r.Body)
20+
if err != nil {
21+
return err
22+
}
23+
*ret = b
24+
return nil
25+
}
26+
27+
type Server struct{}
28+
29+
func (s *Server) Run() error {
30+
doa.Nil(rpc.Register(&Etch{}))
31+
rpc.HandleHTTP()
32+
doa.Nil(http.ListenAndServe("127.0.0.1:8080", nil))
33+
34+
// l, err := net.Listen("tcp", "127.0.0.1:8080")
35+
// if err != nil {
36+
// log.Fatal("listen error:", err)
37+
// }
38+
39+
// // 设置 JSON-RPC 处理
40+
// http.HandleFunc("/rpc", func(w http.ResponseWriter, r *http.Request) {
41+
// // 设置响应头
42+
// w.Header().Set("Content-Type", "application/json")
43+
44+
// // 创建 JSON-RPC 编解码器
45+
// conn, _, err := w.(http.Hijacker).Hijack()
46+
// if err != nil {
47+
// log.Println("Hijacking failed:", err)
48+
// return
49+
// }
50+
// defer conn.Close()
51+
52+
// // 处理 JSON-RPC 请求
53+
// codec := jsonrpc.NewServerCodec(conn)
54+
// err = rpc.ServeRequest(codec)
55+
// if err != nil {
56+
// log.Println("ServeRequest error:", err)
57+
// return
58+
// }
59+
// })
60+
61+
// // 启动 HTTP 服务器
62+
// fmt.Println("JSON-RPC server starting on :8080...")
63+
// err = http.ListenAndServe(":8080", nil)
64+
// if err != nil {
65+
// log.Fatal("ListenAndServe error:", err)
66+
// }
67+
68+
return nil
69+
}
70+
71+
type Client struct {
72+
cli *rpc.Client
73+
}
74+
75+
func (c *Client) DnsQuery(arg []byte) []byte {
76+
r := []byte{}
77+
doa.Nil(c.cli.Call("Etch.DnsQuery", arg, &r))
78+
return r
79+
}
80+
81+
func NewClient(server string) *Client {
82+
c := doa.Try(rpc.DialHTTP("tcp", server))
83+
client := &Client{cli: c}
84+
return client
85+
}

0 commit comments

Comments
 (0)