<commit_before>/**
 * Copyright (C) 2012 Turn, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.turn.ttorrent.client.announce;

import com.turn.ttorrent.bcodec.BDecoder;
import com.turn.ttorrent.bcodec.BEValue;
import com.turn.ttorrent.client.SharedTorrent;
import com.turn.ttorrent.common.AnnounceableTorrent;
import com.turn.ttorrent.common.LoggerUtils;
import com.turn.ttorrent.common.Peer;
import com.turn.ttorrent.common.TorrentInfo;
import com.turn.ttorrent.common.protocol.TrackerMessage.AnnounceRequestMessage;
import com.turn.ttorrent.common.protocol.TrackerMessage.MessageValidationException;
import com.turn.ttorrent.common.protocol.http.HTTPAnnounceRequestMessage;
import com.turn.ttorrent.common.protocol.http.HTTPAnnounceResponseMessage;
import com.turn.ttorrent.common.protocol.http.HTTPTrackerMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Announcer for HTTP trackers.
 *
 * @author mpetazzoni
 * @see <a href="http://wiki.theory.org/BitTorrentSpecification#Tracker_Request_Parameters">BitTorrent tracker request specification</a>
 */
public class HTTPTrackerClient extends TrackerClient {

	protected static final Logger logger =
		LoggerFactory.getLogger(HTTPTrackerClient.class);

	/**
	 * Create a new HTTP announcer for the given torrent.
	 *
	 * @param peers Our own peer specification.
	 */
  public HTTPTrackerClient(List<Peer> peers, URI tracker) {
    super(peers, tracker);
	}

	/**
	 * Build, send and process a tracker announce request.
	 *
	 * <p>
	 * This function first builds an announce request for the specified event
	 * with all the required parameters. Then, the request is made to the
	 * tracker and the response analyzed.
	 * </p>
	 *
	 * <p>
	 * All registered {@link AnnounceResponseListener} objects are then fired
	 * with the decoded payload.
	 * </p>
	 *
     * @param event The announce event type (can be AnnounceEvent.NONE for
     * periodic updates).
     * @param inhibitEvents Prevent event listeners from being notified.
     * @param torrentInfo
     */
	public void announce(final AnnounceRequestMessage.RequestEvent event,
                       boolean inhibitEvents, final AnnounceableTorrent torrentInfo, final List<Peer> adresses) throws AnnounceException {
    logAnnounceRequest(event, torrentInfo);

    final List<HTTPTrackerMessage> trackerResponses = new ArrayList<HTTPTrackerMessage>();
    for (final Peer address : adresses) {
      URL target = encodeAnnounceToURL(event, torrentInfo, address);
      sendAnnounce(target, "GET", new ResponseParser() {
        @Override
        public void parse(InputStream inputStream) throws IOException, MessageValidationException {
          trackerResponses.add(HTTPTrackerMessage.parse(inputStream));
        }
      });
    }
    // we process only first request:
    if (trackerResponses.size() > 0) {
      final HTTPTrackerMessage message = trackerResponses.get(0);
      this.handleTrackerAnnounceResponse(message, inhibitEvents, torrentInfo.getHexInfoHash());
    }
  }

  @Override
  protected void multiAnnounce(AnnounceRequestMessage.RequestEvent event, boolean inhibitEvent, final List<? extends AnnounceableTorrent> torrents, List<Peer> addresses) throws AnnounceException {
    List<List<HTTPTrackerMessage>> trackerResponses = new ArrayList<List<HTTPTrackerMessage>>();

    URL trackerUrl;
    try {
      trackerUrl = this.tracker.toURL();
    } catch (MalformedURLException e) {
      throw new AnnounceException("Invalid tracker URL " + this.tracker, e);
    }

    for (final Peer address : addresses) {
      StringBuilder body = new StringBuilder();
      for (final AnnounceableTorrent torrentInfo : torrents) {
        body.append(encodeAnnounceToURL(event, torrentInfo, address)).append("\n");
      }
      final List<HTTPTrackerMessage> responsesForCurrentIp = new ArrayList<HTTPTrackerMessage>();
      String bodyStr = body.toString().substring(0, body.length() - 1);
      sendAnnounce(trackerUrl, bodyStr, "POST", new ResponseParser() {
        @Override
        public void parse(InputStream inputStream) throws IOException, MessageValidationException {
          final List<BEValue> list = BDecoder.bdecode(inputStream).getList();
          for (BEValue value : list) {
            responsesForCurrentIp.add(HTTPTrackerMessage.parse(value));
          }
        }
      });
      trackerResponses.add(responsesForCurrentIp);
    }
    // we process only first request:
    if (trackerResponses.size() > 0) {
      final List<HTTPTrackerMessage> messages = trackerResponses.get(0);
      for (HTTPTrackerMessage message : messages) {

        if (!(message instanceof HTTPAnnounceResponseMessage)) {
          logger.info("Incorrect instance of message {}. Skipping...", message);<commit_msg>just simple refactoring: stringbuilder also have substring method<commit_after>/**
 * Copyright (C) 2012 Turn, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.turn.ttorrent.client.announce;

import com.turn.ttorrent.bcodec.BDecoder;
import com.turn.ttorrent.bcodec.BEValue;
import com.turn.ttorrent.client.SharedTorrent;
import com.turn.ttorrent.common.AnnounceableTorrent;
import com.turn.ttorrent.common.LoggerUtils;
import com.turn.ttorrent.common.Peer;
import com.turn.ttorrent.common.TorrentInfo;
import com.turn.ttorrent.common.protocol.TrackerMessage.AnnounceRequestMessage;
import com.turn.ttorrent.common.protocol.TrackerMessage.MessageValidationException;
import com.turn.ttorrent.common.protocol.http.HTTPAnnounceRequestMessage;
import com.turn.ttorrent.common.protocol.http.HTTPAnnounceResponseMessage;
import com.turn.ttorrent.common.protocol.http.HTTPTrackerMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Announcer for HTTP trackers.
 *
 * @author mpetazzoni
 * @see <a href="http://wiki.theory.org/BitTorrentSpecification#Tracker_Request_Parameters">BitTorrent tracker request specification</a>
 */
public class HTTPTrackerClient extends TrackerClient {

	protected static final Logger logger =
		LoggerFactory.getLogger(HTTPTrackerClient.class);

	/**
	 * Create a new HTTP announcer for the given torrent.
	 *
	 * @param peers Our own peer specification.
	 */
  public HTTPTrackerClient(List<Peer> peers, URI tracker) {
    super(peers, tracker);
	}

	/**
	 * Build, send and process a tracker announce request.
	 *
	 * <p>
	 * This function first builds an announce request for the specified event
	 * with all the required parameters. Then, the request is made to the
	 * tracker and the response analyzed.
	 * </p>
	 *
	 * <p>
	 * All registered {@link AnnounceResponseListener} objects are then fired
	 * with the decoded payload.
	 * </p>
	 *
     * @param event The announce event type (can be AnnounceEvent.NONE for
     * periodic updates).
     * @param inhibitEvents Prevent event listeners from being notified.
     * @param torrentInfo
     */
	public void announce(final AnnounceRequestMessage.RequestEvent event,
                       boolean inhibitEvents, final AnnounceableTorrent torrentInfo, final List<Peer> adresses) throws AnnounceException {
    logAnnounceRequest(event, torrentInfo);

    final List<HTTPTrackerMessage> trackerResponses = new ArrayList<HTTPTrackerMessage>();
    for (final Peer address : adresses) {
      URL target = encodeAnnounceToURL(event, torrentInfo, address);
      sendAnnounce(target, "GET", new ResponseParser() {
        @Override
        public void parse(InputStream inputStream) throws IOException, MessageValidationException {
          trackerResponses.add(HTTPTrackerMessage.parse(inputStream));
        }
      });
    }
    // we process only first request:
    if (trackerResponses.size() > 0) {
      final HTTPTrackerMessage message = trackerResponses.get(0);
      this.handleTrackerAnnounceResponse(message, inhibitEvents, torrentInfo.getHexInfoHash());
    }
  }

  @Override
  protected void multiAnnounce(AnnounceRequestMessage.RequestEvent event, boolean inhibitEvent, final List<? extends AnnounceableTorrent> torrents, List<Peer> addresses) throws AnnounceException {
    List<List<HTTPTrackerMessage>> trackerResponses = new ArrayList<List<HTTPTrackerMessage>>();

    URL trackerUrl;
    try {
      trackerUrl = this.tracker.toURL();
    } catch (MalformedURLException e) {
      throw new AnnounceException("Invalid tracker URL " + this.tracker, e);
    }

    for (final Peer address : addresses) {
      StringBuilder body = new StringBuilder();
      for (final AnnounceableTorrent torrentInfo : torrents) {
        body.append(encodeAnnounceToURL(event, torrentInfo, address)).append("\n");
      }
      final List<HTTPTrackerMessage> responsesForCurrentIp = new ArrayList<HTTPTrackerMessage>();
      String bodyStr = body.substring(0, body.length() - 1);
      sendAnnounce(trackerUrl, bodyStr, "POST", new ResponseParser() {
        @Override
        public void parse(InputStream inputStream) throws IOException, MessageValidationException {
          final List<BEValue> list = BDecoder.bdecode(inputStream).getList();
          for (BEValue value : list) {
            responsesForCurrentIp.add(HTTPTrackerMessage.parse(value));
          }
        }
      });
      trackerResponses.add(responsesForCurrentIp);
    }
    // we process only first request:
    if (trackerResponses.size() > 0) {
      final List<HTTPTrackerMessage> messages = trackerResponses.get(0);
      for (HTTPTrackerMessage message : messages) {

        if (!(message instanceof HTTPAnnounceResponseMessage)) {
          logger.info("Incorrect instance of message {}. Skipping...", message);
{'fraction_non_alphanumeric': 0.09380417921343188, 'fraction_numerical': 0.0029199744502235603, 'mean_word_length': 4.01143118427069, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5218643', 'n_tokens_mistral': 3053, 'n_tokens_neox': 2922, 'n_words': 838}