register_http.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // register_http.go — 通过 HTTPS 向对端注册设备(发现流程的 HTTP 回发环节)。
  2. //
  3. // LocalSend 协议:本机收到对端的组播公告后,应向对端 HTTP 端点
  4. // POST /api/localsend/v2/register 回发本机信息,使对端完成"互相发现"。
  5. // 该请求携带自签客户端证书(mTLS),对端按证书指纹校验;对端证书为
  6. // 自签,故此处 InsecureSkipVerify(指纹校验由对端完成)。
  7. // 本实现不依赖 localgo 的 HTTPDiscovery(其含网关/子网扫描等重依赖),
  8. // 仅保留协议规定的注册回发功能。
  9. package discovery
  10. import (
  11. "bytes"
  12. "context"
  13. "encoding/json"
  14. "fmt"
  15. "net"
  16. "net/http"
  17. "time"
  18. "TengTuToolbox/localsend/model"
  19. )
  20. // RegisterWithDevice 向指定 IP:port 的 LocalSend 设备回发本机注册信息。
  21. // scheme 为 "http" 或 "https";返回对端响应的注册信息(InfoDto)。
  22. func RegisterWithDevice(ctx context.Context, ip net.IP, port int, scheme string, reg model.RegisterDto) (*model.InfoDto, error) {
  23. if ip == nil {
  24. return nil, fmt.Errorf("ip is nil")
  25. }
  26. body, err := json.Marshal(reg)
  27. if err != nil {
  28. return nil, fmt.Errorf("failed to marshal register dto: %w", err)
  29. }
  30. if scheme == "" {
  31. scheme = "https"
  32. }
  33. url := fmt.Sprintf("%s://%s:%d/api/localsend/v2/register", scheme, ip.String(), port)
  34. req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body))
  35. if err != nil {
  36. return nil, fmt.Errorf("failed to create register request: %w", err)
  37. }
  38. req.Header.Set("Content-Type", "application/json")
  39. client := &http.Client{
  40. Timeout: 3 * time.Second,
  41. Transport: &http.Transport{TLSClientConfig: clientTLSConfig()},
  42. }
  43. resp, err := client.Do(req)
  44. if err != nil {
  45. return nil, fmt.Errorf("register request failed: %w", err)
  46. }
  47. defer resp.Body.Close()
  48. if resp.StatusCode != http.StatusOK {
  49. return nil, fmt.Errorf("register returned status %d", resp.StatusCode)
  50. }
  51. var infoResp model.InfoDto
  52. if err := json.NewDecoder(resp.Body).Decode(&infoResp); err != nil {
  53. return nil, fmt.Errorf("failed to decode register response: %w", err)
  54. }
  55. return &infoResp, nil
  56. }