source

BitTorrent: 다운로드가 시작되지 않음

factcode 2022. 9. 13. 22:03
반응형

BitTorrent: 다운로드가 시작되지 않음

라라벨에 비트렌트 트래커를 설치하려고 합니다.하지만 다운로드가 시작되지 않아 꼼짝할 수 없습니다.시드하고 있는 것처럼 보이는 피어가 1개 있어 접속할 수 있다고 100% 확신하고 있습니다.그러나 다른 기계에서 두 번째 클라이언트를 실행하면 다운로드가 시작되지 않습니다.「피어에의 접속」(uTorrent)에 고정되어 있습니다.

Tracker에서 고객님의 안내방송을 받으면 아래의 답변을 보내드립니다.

d8:intervali1000e12:min intervali300e5:peers18:�ؤ�i�ؑ�XÚJU�6e

다운로드 클라이언트에는 다음과 같은 데이터가 있습니다.

여기에 이미지 설명 입력 여기에 이미지 설명 입력

제 방송 코드는 다음과 같습니다.

<?php

namespace App\Http\Controllers\Announce;

use App\Helpers\BencodeHelper;
use App\Models\Peer;
use App\Models\PeerTorrent;
use App\Models\Torrent;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Log;

class AnnounceController extends Controller
{
    const __INTERVAL = 1000;
    const __TIMEOUT = 120;
    const __INTERVAL_MIN = 60;
    const __MAX_PPR = 20;

    public function announce(Request $request)
    {
        Log::info($request->fullUrl());
        $status = 200;
        $content = "";
        $passkey = Input::get('passkey');
        $peer_id = Input::get('peer_id');
        $port = Input::get('port');
        $info_hash = Input::get('info_hash');
        $downloaded = Input::get('uploaded') ? intval(Input::get('uploaded')) : 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;

        $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']));
            }
        }

        $port = $_SERVER['REMOTE_PORT'];
        /*if(!$port || !ctype_digit($port) || intval($port) < 1 || intval($port) > 65535)
        {
            $content = BencodeHelper::track("Invalid client port.");
            $status = 401;
            return (new Response(AnnounceController::track($content), $status))
                ->header('Content-Type', $value);
        }

        if ($port == 999 && substr($peer_id, 0, 10) == '-TO0001-XX') {
            die("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");
        }*/


        if (!$passkey) {
            $content = BencodeHelper::track("Missing passkey.");
            $status = 401;
            return (new Response(AnnounceController::track($content), $status))
                ->header('Content-Type', $value);
        }


        $torrent = Torrent::getByInfoHash(sha1($info_hash));
        if (!$torrent || $torrent == null) {
            $content = "Torrent not registered with this tracker.";
            $status = 404;
            return (new Response(AnnounceController::track($content), $status))
                ->header('Content-Type', $value);
        }

        $user = User::has('passkeys', '=', $passkey)->get();

        if ($user == null) {
            $content = BencodeHelper::track("Invalid passkey.");
            $status = 401;
            return (new Response(AnnounceController::track($content), $status))
                ->header('Content-Type', $value);
        }

        $peer = Peer::getByHashAndPasskey(bin2hex($peer_id), $passkey);

        if ($peer == null) {
            $peer = Peer::create([
                'hash' => bin2hex($peer_id),
                'user_agent' => $_SERVER['HTTP_USER_AGENT'],
                'ip_address' => $ipAddress,
                'passkey' => $passkey,
                'port' => $port
            ]);
        }

        if (!$info_hash || strlen($info_hash) != 20) {
            $content = BencodeHelper::track("Invalid info_hash.");
            $status = 401;
            return (new Response(AnnounceController::track($content), $status))
                ->header('Content-Type', $value);
        }


        $peer_torrent = PeerTorrent::getByPeerAndTorrent($peer, $torrent);

        if ($peer_torrent == null) {
            $peer_torrent = PeerTorrent::create([
                'peer_id' => $peer->id,
                'torrent_id' => $torrent->id,
                'uploaded' => $uploaded,
                'downloaded' => $downloaded,
                'left' => $left,
                'stopped' => false
            ]);

        } else {
            $peer_torrent->uploaded = $uploaded;
            $peer_torrent->downloaded = $downloaded;
            $peer_torrent->left = $left;
            $peer_torrent->save();
        }

        $seeders = $torrent->getSeedersCount();
        $leechers = $torrent->getLeechersCount();
        $resp = "";
        if ($compact != 1) {
            $resp = "d" . $this->benc_str("interval") . "i" . AnnounceController::__INTERVAL . "e" . $this->benc_str("peers") . "l";
        } else {
            $resp = "d" . $this->benc_str("interval") . "i" . AnnounceController::__INTERVAL . "e" . $this->benc_str("min interval") . "i" . 300 . "e5:" . "peers";
        }

        $peer = array();

        $peer_num = 0;
        foreach ($torrent->getPeersArray() as $row) {
            if ($compact != 1) {
                if ($row["peer_id"] === $peer->hash) {
                    continue;
                }

                $resp .= "d" . $this->benc_str("ip") . $this->benc_str($row['ip']);

                if ($no_peer_id == 0) {
                    $resp .= $this->benc_str("peer id") . $this->benc_str($row["peer_id"]);
                }

                $resp .= $this->benc_str("port") . "i" . $row["port"] . "e" . "e";

            } else {
                $peer_ip = explode('.', $row["ip"]);
                $peer_ip = pack("C*", $peer_ip[0], $peer_ip[1], $peer_ip[2], $peer_ip[3]);
                $peer_port = pack("n*", (int)$row["port"]);
                $time = intval((time() % 7680) / 60);

                if ($left == 0) {
                    $time += 128;
                }

                $time = pack("C", $time);
                $peer[] = $time . $peer_ip . $peer_port;
                $peer_num++;
            }
        }

        if ($compact != 1) {
            $resp .= "ee";
        } else {
            $o = "";
            for ($i = 0; $i < $peer_num; $i++) {
                $o .= substr($peer[$i], 1, 6);
            }
            $resp .= strlen($o) . ':' . $o . 'e';
        }

        $this->benc_resp_raw($resp);
    }

    public function benc_resp($d)
    {
        return $this->benc_resp_raw($this->benc(array('type' => 'dictionary', 'value' => $d)));
    }

    public function benc_resp_raw($x)
    {
        header("Content-Type: text/plain");
        header("Pragma: no-cache");

        if ($_SERVER['HTTP_ACCEPT_ENCODING'] == 'gzip') {
            header("Content-Encoding: gzip");
            echo gzencode($x, 9, FORCE_GZIP);
        } else {
            echo $x;
        }
    }

    function benc($obj)
    {
        if (!is_array($obj) || !isset($obj["type"]) || !isset($obj["value"]))
            return;
        $c = $obj["value"];
        switch ($obj["type"]) {
            case "string":
                return $this->benc_str($c);
            case "integer":
                return $this->benc_int($c);
            case "list":
                return $this->benc_list($c);
            case "dictionary":
                return $this->benc_dict($c);
            default:
                return;
        }
    }

    public function benc_str($s)
    {
        return strlen($s) . ":$s";
    }

    public function benc_int($i)
    {
        return "i" . $i . "e";
    }

    public function benc_list($a)
    {
        $s = "l";
        foreach ($a as $e) {
            $s .= $this->benc($e);
        }
        $s .= "e";
        return $s;
    }

    public function benc_dict($d)
    {
        $s = "d";
        $keys = array_keys($d);
        sort($keys);
        foreach ($keys as $k) {
            $v = $d[$k];
            $s .= $this->benc_str($k);
            $s .= $this->benc($v);
        }
        $s .= "e";
        return $s;
    }


    public function hex2bin($hex)
    {
        $r = '';
        for ($i = 0; $i < strlen($hex); $i += 2) {
            $r .= chr(hexdec($hex{$i} . $hex{($i + 1)}));
        }
        return $r;
    }
}

내가 여기서 뭘 놓쳤는지 잘 모르겠어.

아마 당신이 계속 세팅해서 그런 것 같아요.

->header('Content-Type', $value);

전혀 설정되지 않고$value그럼 "Announce-Response"의 형식이 잘못된 건가요?

   $port = $_SERVER['REMOTE_PORT'];

문제는 접속하고 있는 피어가 송신하는 포토를 아나운스 스트링에 등록하는 것이 아니라, 트래커가 피어가 접속하고 있는 리모트 포토를 등록하는 것이라고 생각합니다.
그것은 거의 확실히 사용하기에는 잘못된 포트이다.

언급URL : https://stackoverflow.com/questions/34474060/bittorrent-download-not-starting

반응형