| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- // register_http.go — 通过 HTTPS 向对端注册设备(发现流程的 HTTP 回发环节)。
- //
- // LocalSend 协议:本机收到对端的组播公告后,应向对端 HTTP 端点
- // POST /api/localsend/v2/register 回发本机信息,使对端完成"互相发现"。
- // 该请求携带自签客户端证书(mTLS),对端按证书指纹校验;对端证书为
- // 自签,故此处 InsecureSkipVerify(指纹校验由对端完成)。
- // 本实现不依赖 localgo 的 HTTPDiscovery(其含网关/子网扫描等重依赖),
- // 仅保留协议规定的注册回发功能。
- package discovery
- import (
- "bytes"
- "context"
- "encoding/json"
- "fmt"
- "net"
- "net/http"
- "time"
- "TengTuToolbox/localsend/model"
- )
- // RegisterWithDevice 向指定 IP:port 的 LocalSend 设备回发本机注册信息。
- // scheme 为 "http" 或 "https";返回对端响应的注册信息(InfoDto)。
- func RegisterWithDevice(ctx context.Context, ip net.IP, port int, scheme string, reg model.RegisterDto) (*model.InfoDto, error) {
- if ip == nil {
- return nil, fmt.Errorf("ip is nil")
- }
- body, err := json.Marshal(reg)
- if err != nil {
- return nil, fmt.Errorf("failed to marshal register dto: %w", err)
- }
- if scheme == "" {
- scheme = "https"
- }
- url := fmt.Sprintf("%s://%s:%d/api/localsend/v2/register", scheme, ip.String(), port)
- req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body))
- if err != nil {
- return nil, fmt.Errorf("failed to create register request: %w", err)
- }
- req.Header.Set("Content-Type", "application/json")
- client := &http.Client{
- Timeout: 3 * time.Second,
- Transport: &http.Transport{TLSClientConfig: clientTLSConfig()},
- }
- resp, err := client.Do(req)
- if err != nil {
- return nil, fmt.Errorf("register request failed: %w", err)
- }
- defer resp.Body.Close()
- if resp.StatusCode != http.StatusOK {
- return nil, fmt.Errorf("register returned status %d", resp.StatusCode)
- }
- var infoResp model.InfoDto
- if err := json.NewDecoder(resp.Body).Decode(&infoResp); err != nil {
- return nil, fmt.Errorf("failed to decode register response: %w", err)
- }
- return &infoResp, nil
- }
|