/** * The announce action * @return $this * @internal param Request $request */ public function announce(Request $request) { Log::info($request->fullUrl()); // GET params sent by the client $passkey = Input::get('passkey'); $peer_id = base64_encode(Input::get('peer_id')); $info_hash = Input::get('info_hash'); $downloaded = Input::get('downloaded') ? intval(Input::get('downloaded')) : 0; $uploaded = Input::get('uploaded') ? intval(Input::get('uploaded')) : 0; $left = Input::get('left') ? intval(Input::get('left')) : 0; $compact = Input::get('compact') ? intval(Input::get('compact')) : 0; $no_peer_id = Input::get('no_peer_id') ? intval(Input::get('no_peer_id')) : 0; $event = strip_tags(Input::get('event')); // Client IP address $ipAddress = ''; // Check for X-Forwarded-For headers and use those if found if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && '' !== trim($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ipAddress = trim($_SERVER['HTTP_X_FORWARDED_FOR']); } else { if (isset($_SERVER['REMOTE_ADDR']) && '' !== trim($_SERVER['REMOTE_ADDR'])) { $ipAddress = trim($_SERVER['REMOTE_ADDR']); } } // Check client ports $port = $_SERVER['REMOTE_PORT']; if (!$port || !ctype_digit($port) || intval($port) < 1 || intval($port) > 65535) { return BencodeHelper::bencodedResponseRaw("Invalid client port", 103); } if ($port == 999 && substr($peer_id, 0, 10) == '-TO0001-XX') { return BencodeHelper::bencodedResponseRaw("d8:completei0e10:incompletei0e8:intervali600e12:min intervali60e5:peersld2:ip12:72.14.194.184:port3:999ed2:ip11:72.14.194.14:port3:999ed2:ip12:72.14.194.654:port3:999eee", 103); } // Check passkey param if (!$passkey) { return BencodeHelper::bencodedResponseRaw("Missing passkey", 900); } // Find passkey-related user $user = User::has('passkeys', '=', $passkey)->get(); if ($user == null) { return BencodeHelper::bencodedResponseRaw("Invalid passkey", 900); } // Check info_hash param if (!$info_hash) { return BencodeHelper::bencodedResponseRaw("Missing info hash", 101); } $info_hash = strtoupper(bin2hex($info_hash)); // Check torrent hash $torrent = Torrent::getByInfoHash($info_hash); if (!$torrent || $torrent == null) { return BencodeHelper::bencodedResponseRaw("Torrent not registered with this tracker.", 900); } // Check if peer already exists $peer = Peer::getByIPAndPasskey($ipAddress, $passkey); // Create a new one if it does not if ($peer == null) { $attributes = ['hash' => $peer_id, 'user_agent' => $_SERVER['HTTP_USER_AGENT'], 'ip_address' => $ipAddress, 'passkey' => $passkey, 'port' => $port]; $peer = Peer::create($attributes); } // Check info_hash (must be 20 chars long) if (!$info_hash) { return BencodeHelper::bencodedResponseRaw("Invalid info hash.", 150); } // Check if peer is already assigned to torrent $peer_torrent = PeerTorrent::getByPeerAndTorrent($peer, $torrent); // Assign it, if not if ($peer_torrent == null) { $attributes = ['peer_id' => $peer->id, 'torrent_id' => $torrent->id, 'uploaded' => $uploaded, 'downloaded' => $downloaded, 'left' => $left]; // Event handling if ($event === BitTorrent::EVENT_STARTED || $event == BitTorrent::EVENT_COMPLETED) { $attributes['stopped'] = false; } else { $attributes['stopped'] = true; } PeerTorrent::create($attributes); } else { // Or update the existing one $peer_torrent->uploaded = $uploaded; $peer_torrent->downloaded = $downloaded; $peer_torrent->left = $left; $peer_torrent->save(); } // Perform announce on the torrent $torrent->announce(); // Build response $resp = BencodeHelper::buildAnnounceResponse($torrent, $peer_torrent, $compact, $no_peer_id); return BencodeHelper::bencodedResponseRaw($resp); }