// 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 }