content: package com.acgist.snail.net.torrent.lsd;
  
  import java.net.InetSocketAddress;
  
  import com.acgist.snail.config.PeerConfig;
  import com.acgist.snail.config.SymbolConfig;
  import com.acgist.snail.config.SystemConfig;
  import com.acgist.snail.context.wrapper.HeaderWrapper;
  import com.acgist.snail.logger.Logger;
  import com.acgist.snail.logger.LoggerFactory;
  import com.acgist.snail.net.NetException;
  import com.acgist.snail.net.UdpClient;
  import com.acgist.snail.utils.ArrayUtils;
  import com.acgist.snail.utils.NetUtils;
  import com.acgist.snail.utils.StringUtils;
  
  /**
   * 本地发现客户端
   * 
   * @author acgist
   */
  public final class LocalServiceDiscoveryClient extends UdpClient<LocalServiceDiscoveryMessageHandler> {
  
      private static final Logger LOGGER = LoggerFactory.getLogger(LocalServiceDiscoveryClient.class);
      
      /**
       * BT-SEARCH协议：{@value}
       */
      private static final String PROTOCOL = "BT-SEARCH * HTTP/1.1";
      
      /**
       * @param socketAddress 地址
       */
      private LocalServiceDiscoveryClient(InetSocketAddress socketAddress) {
          super("LSD Client", new LocalServiceDiscoveryMessageHandler(socketAddress));
      }
  
      /**
       * 新建本地发现客户端
       */
      public static final LocalServiceDiscoveryClient newInstance() {
          return new LocalServiceDiscoveryClient(NetUtils.buildSocketAddress(LocalServiceDiscoveryServer.lsdHost(), LocalServiceDiscoveryServer.LSD_PORT));
      }
  
      @Override
      public boolean open() {
          return this.open(LocalServiceDiscoveryServer.getInstance().getChannel());
      }
      
      /**
       * 发送本地发现消息
       * 
       * @param infoHashs InfoHash数组
       */
      public void localSearch(String ... infoHashs) {
          if(ArrayUtils.isEmpty(infoHashs)) {
              return;
          }
          if(LOGGER.isDebugEnabled()) {
              LOGGER.debug("发送本地发现消息（InfoHash）：{}", SymbolConfig.Symbol.COMMA.join(infoHashs));
          }
          try {
              this.send(this.buildMessage(infoHashs));
          } catch (NetException e) {
              LOGGER.error("发送本地发现消息异常", e);
          }
      }
      
      /**
       * 新建本地发现消息
       * 
       * @param infoHashs InfoHash数组
       * 
       * @return 本地发现消息
       */
      private String buildMessage(String ... infoHashs) {
          final String peerId         = StringUtils.hex(PeerConfig.getInstance().getPeerId());
          final HeaderWrapper builder = HeaderWrapper.newBuilder(PROTOCOL);
          builder
              .setHeader(LocalServiceDiscoveryMessageHandler.HEADER_HOST, SymbolConfig.Symbol.COLON.join(LocalServiceDiscoveryServer.lsdHost(), LocalServiceDiscoveryServer.LSD_PORT))
              .setHeader(LocalServiceDiscoveryMessageHandler.HEADER_PORT, String.valueOf(SystemConfig.getTorrentPort()))
              .setHeader(LocalServiceDiscoveryMessageHandler.HEADER_COOKIE, peerId);
          for (String infoHash : infoHashs) {
              builder.setHeader(LocalServiceDiscoveryMessageHandler.HEADER_INFOHASH, infoHash);
          }
          return builder.build();
      }
      
  }
  