Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- bazar@ao756:~/apt-p2p$ apt-p2p.py
- Traceback (most recent call last):
- File "/usr/local/bin/apt-p2p.py", line 15, in <module>
- from twisted.application import service, internet, app, strports
- ImportError: No module named twisted.application
- bazar@ao756:~/apt-p2p$ pip install twisted
- Collecting twisted
- Downloading https://files.pythonhosted.org/packages/06/28/2a433e147de68c8416aa0179c45e67b67161f5c0f24aaaf1723f6229f574/Twisted-19.10.0-cp37-cp37m-manylinux1_x86_64.whl (3.1MB)
- 100% |████████████████████████████████| 3.1MB 53kB/s
- Collecting hyperlink>=17.1.1 (from twisted)
- Downloading https://files.pythonhosted.org/packages/7f/91/e916ca10a2de1cb7101a9b24da546fb90ee14629e23160086cf3361c4fb8/hyperlink-19.0.0-py2.py3-none-any.whl
- Collecting Automat>=0.3.0 (from twisted)
- Downloading https://files.pythonhosted.org/packages/e5/11/756922e977bb296a79ccf38e8d45cafee446733157d59bcd751d3aee57f5/Automat-0.8.0-py2.py3-none-any.whl
- Collecting incremental>=16.10.1 (from twisted)
- Downloading https://files.pythonhosted.org/packages/f5/1d/c98a587dc06e107115cf4a58b49de20b19222c83d75335a192052af4c4b7/incremental-17.5.0-py2.py3-none-any.whl
- Collecting attrs>=17.4.0 (from twisted)
- Downloading https://files.pythonhosted.org/packages/a2/db/4313ab3be961f7a763066401fb77f7748373b6094076ae2bda2806988af6/attrs-19.3.0-py2.py3-none-any.whl
- Collecting constantly>=15.1 (from twisted)
- Downloading https://files.pythonhosted.org/packages/b9/65/48c1909d0c0aeae6c10213340ce682db01b48ea900a7d9fce7a7910ff318/constantly-15.1.0-py2.py3-none-any.whl
- Collecting PyHamcrest>=1.9.0 (from twisted)
- Downloading https://files.pythonhosted.org/packages/ac/6c/a641af18e416e6501c10b03742387176626a1d48196100160df796f36632/PyHamcrest-2.0.0-py3-none-any.whl (51kB)
- 100% |████████████████████████████████| 61kB 822kB/s
- Collecting zope.interface>=4.4.2 (from twisted)
- Downloading https://files.pythonhosted.org/packages/fc/1f/eeda511f9d857b63e248bbb2084f04e6c6a1863901954ba0872965c0895c/zope.interface-4.7.1-cp37-cp37m-manylinux1_x86_64.whl (169kB)
- 100% |████████████████████████████████| 174kB 25kB/s
- Requirement already satisfied: idna>=2.5 in /usr/lib/python3/dist-packages (from hyperlink>=17.1.1->twisted) (2.6)
- Requirement already satisfied: six in /usr/lib/python3/dist-packages (from Automat>=0.3.0->twisted) (1.13.0)
- Requirement already satisfied: setuptools in /usr/lib/python3/dist-packages (from zope.interface>=4.4.2->twisted) (44.0.0)
- Installing collected packages: hyperlink, attrs, Automat, incremental, constantly, PyHamcrest, zope.interface, twisted
- Successfully installed Automat-0.8.0 PyHamcrest-2.0.0 attrs-19.3.0 constantly-15.1.0 hyperlink-19.0.0 incremental-17.5.0 twisted-19.10.0 zope.interface-4.7.1
- bazar@ao756:~/apt-p2p$ apt-p2p.py
- Traceback (most recent call last):
- File "/usr/local/bin/apt-p2p.py", line 15, in <module>
- from twisted.application import service, internet, app, strports
- ImportError: No module named twisted.application
- bazar@ao756:~/apt-p2p$ pip install twisted.application
- Collecting twisted.application
- Could not install packages due to an EnvironmentError: 404 Client Error: Not Found for url: https://pypi.org/simple/twisted-application/
- bazar@ao756:~/apt-p2p$ sudo apt install python-twisted
- [sudo] пароль для bazar:
- Чтение списков пакетов… Готово
- Построение дерева зависимостей
- Чтение информации о состоянии… Готово
- Будут установлены следующие дополнительные пакеты:
- python-asn1crypto python-attr python-automat python-cffi-backend python-constantly
- python-cryptography python-enum34 python-hamcrest python-hyperlink python-idna
- python-incremental python-ipaddress python-openssl python-pyasn1 python-pyasn1-modules
- python-service-identity python-twisted-bin python-twisted-core python-zope.interface
- Предлагаемые пакеты:
- python-attr-doc python-cryptography-doc python-cryptography-vectors python-enum34-doc
- python-openssl-doc python-openssl-dbg python-twisted-bin-dbg python-pampy python-qt3
- python-serial python-wxgtk3.0
- Следующие НОВЫЕ пакеты будут установлены:
- python-asn1crypto python-attr python-automat python-cffi-backend python-constantly
- python-cryptography python-enum34 python-hamcrest python-hyperlink python-idna
- python-incremental python-ipaddress python-openssl python-pyasn1 python-pyasn1-modules
- python-service-identity python-twisted python-twisted-bin python-twisted-core
- python-zope.interface
- Обновлено 0 пакетов, установлено 20 новых пакетов, для удаления отмечено 0 пакетов, и 3 пакетов не обновлено.
- Необходимо скачать 2 487 kB/2 841 kB архивов.
- После данной операции объём занятого дискового пространства возрастёт на 18,6 MB.
- Хотите продолжить? [Д/н]
- Пол:1 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-asn1crypto all 0.24.0-1build1 [72,8 kB]
- Пол:2 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-attr all 18.2.0-1build1 [29,7 kB]
- Пол:3 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-automat all 0.8.0-0ubuntu2 [27,1 kB]
- Пол:4 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-constantly all 15.1.0-1build1 [8 168 B]
- Пол:5 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-ipaddress all 1.0.17-1build1 [18,4 kB]
- Пол:6 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-hamcrest all 1.9.0-2 [24,7 kB]
- Пол:7 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-idna all 2.6-2build1 [32,7 kB]
- Пол:8 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-hyperlink all 19.0.0-1 [33,5 kB]
- Пол:9 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-incremental all 16.10.1-3.1 [14,8 kB]
- Пол:10 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-openssl all 19.0.0-1build1 [43,1 kB]
- Пол:11 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-pyasn1 all 0.4.2-3build1 [46,6 kB]
- Пол:12 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-pyasn1-modules all 0.2.1-0.2build1 [32,8 kB]
- Пол:13 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-service-identity all 18.1.0-5build1 [10,6 kB]
- Пол:14 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-twisted-bin amd64 18.9.0-6 [15,2 kB]
- Пол:15 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-zope.interface amd64 4.6.0-4 [84,8 kB]
- Пол:16 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-twisted-core all 18.9.0-6 [1 989 kB]
- Пол:17 http://ru.archive.ubuntu.com/ubuntu focal/universe amd64 python-twisted all 18.9.0-6 [3 728 B]
- Получено 2 487 kB за 16с (159 kB/s)
- Выбор ранее не выбранного пакета python-asn1crypto.
- (Чтение базы данных … на данный момент установлено 472853 файла и каталога.)
- Подготовка к распаковке …/00-python-asn1crypto_0.24.0-1build1_all.deb …
- Распаковывается python-asn1crypto (0.24.0-1build1) …
- Выбор ранее не выбранного пакета python-attr.
- Подготовка к распаковке …/01-python-attr_18.2.0-1build1_all.deb …
- Распаковывается python-attr (18.2.0-1build1) …
- Выбор ранее не выбранного пакета python-automat.
- Подготовка к распаковке …/02-python-automat_0.8.0-0ubuntu2_all.deb …
- Распаковывается python-automat (0.8.0-0ubuntu2) …
- Выбор ранее не выбранного пакета python-cffi-backend.
- Подготовка к распаковке …/03-python-cffi-backend_1.13.2-1_amd64.deb …
- Распаковывается python-cffi-backend (1.13.2-1) …
- Выбор ранее не выбранного пакета python-constantly.
- Подготовка к распаковке …/04-python-constantly_15.1.0-1build1_all.deb …
- Распаковывается python-constantly (15.1.0-1build1) …
- Выбор ранее не выбранного пакета python-enum34.
- Подготовка к распаковке …/05-python-enum34_1.1.6-2ubuntu1_all.deb …
- Распаковывается python-enum34 (1.1.6-2ubuntu1) …
- Выбор ранее не выбранного пакета python-ipaddress.
- Подготовка к распаковке …/06-python-ipaddress_1.0.17-1build1_all.deb …
- Распаковывается python-ipaddress (1.0.17-1build1) …
- Выбор ранее не выбранного пакета python-cryptography.
- Подготовка к распаковке …/07-python-cryptography_2.6.1-4ubuntu1_amd64.deb …
- Распаковывается python-cryptography (2.6.1-4ubuntu1) …
- Выбор ранее не выбранного пакета python-hamcrest.
- Подготовка к распаковке …/08-python-hamcrest_1.9.0-2_all.deb …
- Распаковывается python-hamcrest (1.9.0-2) …
- Выбор ранее не выбранного пакета python-idna.
- Подготовка к распаковке …/09-python-idna_2.6-2build1_all.deb …
- Распаковывается python-idna (2.6-2build1) …
- Выбор ранее не выбранного пакета python-hyperlink.
- Подготовка к распаковке …/10-python-hyperlink_19.0.0-1_all.deb …
- Распаковывается python-hyperlink (19.0.0-1) …
- Выбор ранее не выбранного пакета python-incremental.
- Подготовка к распаковке …/11-python-incremental_16.10.1-3.1_all.deb …
- Распаковывается python-incremental (16.10.1-3.1) …
- Выбор ранее не выбранного пакета python-openssl.
- Подготовка к распаковке …/12-python-openssl_19.0.0-1build1_all.deb …
- Распаковывается python-openssl (19.0.0-1build1) …
- Выбор ранее не выбранного пакета python-pyasn1.
- Подготовка к распаковке …/13-python-pyasn1_0.4.2-3build1_all.deb …
- Распаковывается python-pyasn1 (0.4.2-3build1) …
- Выбор ранее не выбранного пакета python-pyasn1-modules.
- Подготовка к распаковке …/14-python-pyasn1-modules_0.2.1-0.2build1_all.deb …
- Распаковывается python-pyasn1-modules (0.2.1-0.2build1) …
- Выбор ранее не выбранного пакета python-service-identity.
- Подготовка к распаковке …/15-python-service-identity_18.1.0-5build1_all.deb …
- Распаковывается python-service-identity (18.1.0-5build1) …
- Выбор ранее не выбранного пакета python-twisted-bin:amd64.
- Подготовка к распаковке …/16-python-twisted-bin_18.9.0-6_amd64.deb …
- Распаковывается python-twisted-bin:amd64 (18.9.0-6) …
- Выбор ранее не выбранного пакета python-zope.interface.
- Подготовка к распаковке …/17-python-zope.interface_4.6.0-4_amd64.deb …
- Распаковывается python-zope.interface (4.6.0-4) …
- Выбор ранее не выбранного пакета python-twisted-core.
- Подготовка к распаковке …/18-python-twisted-core_18.9.0-6_all.deb …
- Распаковывается python-twisted-core (18.9.0-6) …
- Выбор ранее не выбранного пакета python-twisted.
- Подготовка к распаковке …/19-python-twisted_18.9.0-6_all.deb …
- Распаковывается python-twisted (18.9.0-6) …
- Настраивается пакет python-enum34 (1.1.6-2ubuntu1) …
- Настраивается пакет python-asn1crypto (0.24.0-1build1) …
- Настраивается пакет python-attr (18.2.0-1build1) …
- Настраивается пакет python-zope.interface (4.6.0-4) …
- Настраивается пакет python-pyasn1 (0.4.2-3build1) …
- Настраивается пакет python-idna (2.6-2build1) …
- Настраивается пакет python-pyasn1-modules (0.2.1-0.2build1) …
- Настраивается пакет python-twisted-bin:amd64 (18.9.0-6) …
- Настраивается пакет python-hamcrest (1.9.0-2) …
- Настраивается пакет python-incremental (16.10.1-3.1) …
- Настраивается пакет python-constantly (15.1.0-1build1) …
- Настраивается пакет python-hyperlink (19.0.0-1) …
- Настраивается пакет python-ipaddress (1.0.17-1build1) …
- Настраивается пакет python-cffi-backend (1.13.2-1) …
- Настраивается пакет python-automat (0.8.0-0ubuntu2) …
- Настраивается пакет python-cryptography (2.6.1-4ubuntu1) …
- Настраивается пакет python-openssl (19.0.0-1build1) …
- Настраивается пакет python-service-identity (18.1.0-5build1) …
- Настраивается пакет python-twisted-core (18.9.0-6) …
- Настраивается пакет python-twisted (18.9.0-6) …
- Обрабатываются триггеры для man-db (2.9.0-2) …
- bazar@ao756:~/apt-p2p$ pip install twisted.application
- Collecting twisted.application
- Could not install packages due to an EnvironmentError: 404 Client Error: Not Found for url: https://pypi.org/simple/twisted-application/
- bazar@ao756:~/apt-p2p$ apt-p2p.py
- 2020-01-31 15:04:08+0300 [-] Log opened.
- 2020-01-31 15:04:08+0300 [-] Loading config files: '/etc/apt-p2p/apt-p2p.conf', '/home/bazar/.apt-p2p/apt-p2p.conf', ''
- 2020-01-31 15:04:08+0300 [-] Successfully loaded config files: ''
- 2020-01-31 15:04:08+0300 [-] Starting application with uid/gid None/None
- 2020-01-31 15:04:08+0300 [-] Traceback (most recent call last):
- 2020-01-31 15:04:08+0300 [-] File "/usr/local/bin/apt-p2p.py", line 68, in <module>
- 2020-01-31 15:04:08+0300 [-] DHT = __import__(config.get('DEFAULT', 'DHT')+'.DHT', globals(), locals(), ['DHT'])
- 2020-01-31 15:04:08+0300 [-] File "/usr/local/lib/python2.7/dist-packages/apt_p2p_Khashmir/DHT.py", line 17, in <module>
- 2020-01-31 15:04:08+0300 [-] from khashmir import Khashmir
- 2020-01-31 15:04:08+0300 [-] File "/usr/local/lib/python2.7/dist-packages/apt_p2p_Khashmir/khashmir.py", line 23, in <module>
- 2020-01-31 15:04:08+0300 [-] from db import DB
- 2020-01-31 15:04:08+0300 [-] File "/usr/local/lib/python2.7/dist-packages/apt_p2p_Khashmir/db.py", line 5, in <module>
- 2020-01-31 15:04:08+0300 [-] from pysqlite2 import dbapi2 as sqlite
- 2020-01-31 15:04:08+0300 [-] ImportError: No module named pysqlite2
- bazar@ao756:~/apt-p2p$ pip install pysqlite2
- Collecting pysqlite2
- Could not install packages due to an EnvironmentError: 404 Client Error: Not Found for url: https://pypi.org/simple/pysqlite2/
- bazar@ao756:~/apt-p2p$ sudo apt install libsqlite3-dev
- Чтение списков пакетов… Готово
- Построение дерева зависимостей
- Чтение информации о состоянии… Готово
- Предлагаемые пакеты:
- sqlite3-doc
- Следующие НОВЫЕ пакеты будут установлены:
- libsqlite3-dev
- Обновлено 0 пакетов, установлено 1 новых пакетов, для удаления отмечено 0 пакетов, и 3 пакетов не обновлено.
- Необходимо скачать 684 kB архивов.
- После данной операции объём занятого дискового пространства возрастёт на 2 332 kB.
- Пол:1 http://ru.archive.ubuntu.com/ubuntu focal/main amd64 libsqlite3-dev amd64 3.30.1-1ubuntu1 [684 kB]
- Получено 684 kB за 3с (222 kB/s)
- Выбор ранее не выбранного пакета libsqlite3-dev:amd64.
- (Чтение базы данных … на данный момент установлено 474374 файла и каталога.)
- Подготовка к распаковке …/libsqlite3-dev_3.30.1-1ubuntu1_amd64.deb …
- Распаковывается libsqlite3-dev:amd64 (3.30.1-1ubuntu1) …
- Настраивается пакет libsqlite3-dev:amd64 (3.30.1-1ubuntu1) …
- bazar@ao756:~/apt-p2p$ apt-p2p.py
- 2020-01-31 15:07:01+0300 [-] Log opened.
- 2020-01-31 15:07:01+0300 [-] Loading config files: '/etc/apt-p2p/apt-p2p.conf', '/home/bazar/.apt-p2p/apt-p2p.conf', ''
- 2020-01-31 15:07:01+0300 [-] Successfully loaded config files: ''
- 2020-01-31 15:07:01+0300 [-] Starting application with uid/gid None/None
- 2020-01-31 15:07:01+0300 [-] Traceback (most recent call last):
- 2020-01-31 15:07:01+0300 [-] File "/usr/local/bin/apt-p2p.py", line 68, in <module>
- 2020-01-31 15:07:01+0300 [-] DHT = __import__(config.get('DEFAULT', 'DHT')+'.DHT', globals(), locals(), ['DHT'])
- 2020-01-31 15:07:01+0300 [-] File "/usr/local/lib/python2.7/dist-packages/apt_p2p_Khashmir/DHT.py", line 17, in <module>
- 2020-01-31 15:07:01+0300 [-] from khashmir import Khashmir
- 2020-01-31 15:07:01+0300 [-] File "/usr/local/lib/python2.7/dist-packages/apt_p2p_Khashmir/khashmir.py", line 23, in <module>
- 2020-01-31 15:07:01+0300 [-] from db import DB
- 2020-01-31 15:07:01+0300 [-] File "/usr/local/lib/python2.7/dist-packages/apt_p2p_Khashmir/db.py", line 5, in <module>
- 2020-01-31 15:07:01+0300 [-] from pysqlite2 import dbapi2 as sqlite
- 2020-01-31 15:07:01+0300 [-] ImportError: No module named pysqlite2
- bazar@ao756:~/apt-p2p$ python -c 'import _sqlite3'
- bazar@ao756:~/apt-p2p$ apt-p2p.py
- 2020-01-31 15:07:14+0300 [-] Log opened.
- 2020-01-31 15:07:14+0300 [-] Loading config files: '/etc/apt-p2p/apt-p2p.conf', '/home/bazar/.apt-p2p/apt-p2p.conf', ''
- 2020-01-31 15:07:14+0300 [-] Successfully loaded config files: ''
- 2020-01-31 15:07:14+0300 [-] Starting application with uid/gid None/None
- 2020-01-31 15:07:14+0300 [-] Traceback (most recent call last):
- 2020-01-31 15:07:14+0300 [-] File "/usr/local/bin/apt-p2p.py", line 68, in <module>
- 2020-01-31 15:07:14+0300 [-] DHT = __import__(config.get('DEFAULT', 'DHT')+'.DHT', globals(), locals(), ['DHT'])
- 2020-01-31 15:07:14+0300 [-] File "/usr/local/lib/python2.7/dist-packages/apt_p2p_Khashmir/DHT.py", line 17, in <module>
- 2020-01-31 15:07:14+0300 [-] from khashmir import Khashmir
- 2020-01-31 15:07:14+0300 [-] File "/usr/local/lib/python2.7/dist-packages/apt_p2p_Khashmir/khashmir.py", line 23, in <module>
- 2020-01-31 15:07:14+0300 [-] from db import DB
- 2020-01-31 15:07:14+0300 [-] File "/usr/local/lib/python2.7/dist-packages/apt_p2p_Khashmir/db.py", line 5, in <module>
- 2020-01-31 15:07:14+0300 [-] from pysqlite2 import dbapi2 as sqlite
- 2020-01-31 15:07:14+0300 [-] ImportError: No module named pysqlite2
- bazar@ao756:~/apt-p2p$ ls
- apt_p2p apt_p2p_Khashmir bootstrap1 debian downloader1 LICENSE.md setup.py TODO.md
- apt-p2p.conf apt-p2p.py build docs downloader2 README.md test.py
- bazar@ao756:~/apt-p2p$ cd apt_p2p_Khashmir/
- bazar@ao756:~/apt-p2p/apt_p2p_Khashmir$ ls
- actions.py db.py __init__.py khash.py krpc.py node.py util.py
- bencode.py DHT.py khashmir.py knode.py ktable.py stats.py
- bazar@ao756:~/apt-p2p/apt_p2p_Khashmir$ cat k
- khashmir.py khash.py knode.py krpc.py ktable.py
- bazar@ao756:~/apt-p2p/apt_p2p_Khashmir$ cat k
- khashmir.py khash.py knode.py krpc.py ktable.py
- bazar@ao756:~/apt-p2p/apt_p2p_Khashmir$ cat khashmir.py
- """The main Khashmir program.
- @var isLocal: a compiled regular expression suitable for testing if an
- IP address is from a known local or private range
- """
- import warnings
- warnings.simplefilter("ignore", DeprecationWarning)
- from datetime import datetime, timedelta
- from random import randrange, shuffle
- from sha import sha
- from copy import copy
- import os, re
- from twisted.internet.defer import Deferred
- from twisted.internet.base import DelayedCall
- from twisted.internet import protocol, reactor
- from twisted.python import log
- from twisted.trial import unittest
- from db import DB
- from ktable import KTable
- from knode import KNodeBase, KNodeRead, KNodeWrite, NULL_ID
- from khash import newID, newIDInRange
- from actions import FindNode, FindValue, GetValue, StoreValue
- from stats import StatsLogger
- import krpc
- isLocal = re.compile('^(192\.168\.[0-9]{1,3}\.[0-9]{1,3})|'+
- '(10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})|'+
- '(172\.0?1[6-9]\.[0-9]{1,3}\.[0-9]{1,3})|'+
- '(172\.0?2[0-9]\.[0-9]{1,3}\.[0-9]{1,3})|'+
- '(172\.0?3[0-1]\.[0-9]{1,3}\.[0-9]{1,3})|'+
- '(127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})$')
- class KhashmirBase(protocol.Factory):
- """The base Khashmir class, with base functionality and find node, no key-value mappings.
- @type _Node: L{node.Node}
- @ivar _Node: the knode implementation to use for this class of DHT
- @type config: C{dictionary}
- @ivar config: the configuration parameters for the DHT
- @type pinging: C{dictionary}
- @ivar pinging: the node's that are currently being pinged, keys are the
- node id's, values are the Deferred or DelayedCall objects
- @type port: C{int}
- @ivar port: the port to listen on
- @type store: L{db.DB}
- @ivar store: the database to store nodes and key/value pairs in
- @type node: L{node.Node}
- @ivar node: this node
- @type table: L{ktable.KTable}
- @ivar table: the routing table
- @type token_secrets: C{list} of C{string}
- @ivar token_secrets: the current secrets to use to create tokens
- @type stats: L{stats.StatsLogger}
- @ivar stats: the statistics gatherer
- @type udp: L{krpc.hostbroker}
- @ivar udp: the factory for the KRPC protocol
- @type listenport: L{twisted.internet.interfaces.IListeningPort}
- @ivar listenport: the UDP listening port
- @type next_checkpoint: L{twisted.internet.interfaces.IDelayedCall}
- @ivar next_checkpoint: the delayed call for the next checkpoint
- """
- _Node = KNodeBase
- def __init__(self, config, cache_dir='/tmp'):
- """Initialize the Khashmir class and call the L{setup} method.
- @type config: C{dictionary}
- @param config: the configuration parameters for the DHT
- @type cache_dir: C{string}
- @param cache_dir: the directory to store all files in
- (optional, defaults to the /tmp directory)
- """
- self.config = None
- self.pinging = {}
- self.setup(config, cache_dir)
- def setup(self, config, cache_dir):
- """Setup all the Khashmir sub-modules.
- @type config: C{dictionary}
- @param config: the configuration parameters for the DHT
- @type cache_dir: C{string}
- @param cache_dir: the directory to store all files in
- """
- self.config = config
- self.port = config['PORT']
- self.store = DB(os.path.join(cache_dir, 'khashmir.' + str(self.port) + '.db'))
- self.node = self._loadSelfNode('', self.port)
- self.table = KTable(self.node, config)
- self.token_secrets = [newID()]
- self.stats = StatsLogger(self.table, self.store)
- # Start listening
- self.udp = krpc.hostbroker(self, self.stats, config)
- self.udp.protocol = krpc.KRPC
- self.listenport = reactor.listenUDP(self.port, self.udp)
- # Load the routing table and begin checkpointing
- self._loadRoutingTable()
- self.refreshTable(force = True)
- self.next_checkpoint = reactor.callLater(60, self.checkpoint)
- def Node(self, id, host = None, port = None):
- """Create a new node.
- @see: L{node.Node.__init__}
- """
- n = self._Node(id, host, port)
- n.table = self.table
- n.conn = self.udp.connectionForAddr((n.host, n.port))
- return n
- def __del__(self):
- """Stop listening for packets."""
- self.listenport.stopListening()
- def _loadSelfNode(self, host, port):
- """Create this node, loading any previously saved one."""
- id = self.store.getSelfNode()
- if not id or not id.endswith(self.config['VERSION']):
- id = newID(self.config['VERSION'])
- return self._Node(id, host, port)
- def checkpoint(self):
- """Perform some periodic maintenance operations."""
- # Create a new token secret
- self.token_secrets.insert(0, newID())
- if len(self.token_secrets) > 3:
- self.token_secrets.pop()
- # Save some parameters for reloading
- self.store.saveSelfNode(self.node.id)
- self.store.dumpRoutingTable(self.table.buckets)
- # DHT maintenance
- self.store.expireValues(self.config['KEY_EXPIRE'])
- self.refreshTable()
- self.next_checkpoint = reactor.callLater(randrange(int(self.config['CHECKPOINT_INTERVAL'] * .9),
- int(self.config['CHECKPOINT_INTERVAL'] * 1.1)),
- self.checkpoint)
- def _loadRoutingTable(self):
- """Load the previous routing table nodes from the database.
- It's usually a good idea to call refreshTable(force = True) after
- loading the table.
- """
- nodes = self.store.getRoutingTable()
- for rec in nodes:
- n = self.Node(rec[0], rec[1], int(rec[2]))
- self.table.insertNode(n, contacted = False)
- #{ Local interface
- def addContact(self, host, port, callback=None, errback=None):
- """Ping this node and add the contact info to the table on pong.
- @type host: C{string}
- @param host: the IP address of the node to contact
- @type port: C{int}
- @param port:the port of the node to contact
- @type callback: C{method}
- @param callback: the method to call with the results, it must take 1
- parameter, the contact info returned by the node
- (optional, defaults to doing nothing with the results)
- @type errback: C{method}
- @param errback: the method to call if an error occurs
- (optional, defaults to calling the callback with the error)
- """
- n = self.Node(NULL_ID, host, port)
- self.sendJoin(n, callback=callback, errback=errback)
- def findNode(self, id, callback):
- """Find the contact info for the K closest nodes in the global table.
- @type id: C{string}
- @param id: the target ID to find the K closest nodes of
- @type callback: C{method}
- @param callback: the method to call with the results, it must take 1
- parameter, the list of K closest nodes
- """
- # Mark the bucket as having been accessed
- self.table.touch(id)
- # Start with our node
- nodes = [copy(self.node)]
- # Start the finding nodes action
- state = FindNode(self, id, callback, self.config, self.stats)
- reactor.callLater(0, state.goWithNodes, nodes)
- def insertNode(self, node, contacted = True):
- """Try to insert a node in our local table, pinging oldest contact if necessary.
- If all you have is a host/port, then use L{addContact}, which calls this
- method after receiving the PONG from the remote node. The reason for
- the separation is we can't insert a node into the table without its
- node ID. That means of course the node passed into this method needs
- to be a properly formed Node object with a valid ID.
- @type node: L{node.Node}
- @param node: the new node to try and insert
- @type contacted: C{boolean}
- @param contacted: whether the new node is known to be good, i.e.
- responded to a request (optional, defaults to True)
- """
- # Don't add any local nodes to the routing table
- if not self.config['LOCAL_OK'] and isLocal.match(node.host):
- log.msg('Not adding local node to table: %s/%s' % (node.host, node.port))
- return
- old = self.table.insertNode(node, contacted=contacted)
- if (isinstance(old, self._Node) and old.id != self.node.id and
- (datetime.now() - old.lastSeen) >
- timedelta(seconds=self.config['MIN_PING_INTERVAL'])):
- # Bucket is full, check to see if old node is still available
- df = self.sendPing(old)
- df.addErrback(self._staleNodeHandler, old, node, contacted)
- elif not old and not contacted:
- # There's room, we just need to contact the node first
- df = self.sendPing(node)
- # Also schedule a future ping to make sure the node works
- def rePing(newnode, self = self):
- if newnode.id not in self.pinging:
- self.pinging[newnode.id] = reactor.callLater(self.config['MIN_PING_INTERVAL'],
- self.sendPing, newnode)
- return newnode
- df.addCallback(rePing)
- def _staleNodeHandler(self, err, old, node, contacted):
- """The pinged node never responded, so replace it."""
- self.table.invalidateNode(old)
- self.insertNode(node, contacted)
- return err
- def nodeFailed(self, node):
- """Mark a node as having failed a request and schedule a future check.
- @type node: L{node.Node}
- @param node: the new node to try and insert
- """
- exists = self.table.nodeFailed(node)
- # If in the table, schedule a ping, if one isn't already sent/scheduled
- if exists and node.id not in self.pinging:
- self.pinging[node.id] = reactor.callLater(self.config['MIN_PING_INTERVAL'],
- self.sendPing, node)
- def sendPing(self, node):
- """Ping the node to see if it's still alive.
- @type node: L{node.Node}
- @param node: the node to send the join to
- """
- # Check for a ping already underway
- if (isinstance(self.pinging.get(node.id, None), DelayedCall) and
- self.pinging[node.id].active()):
- self.pinging[node.id].cancel()
- elif isinstance(self.pinging.get(node.id, None), Deferred):
- return self.pinging[node.id]
- self.stats.startedAction('ping')
- df = node.ping(self.node.id)
- self.pinging[node.id] = df
- df.addCallbacks(self._pingHandler, self._pingError,
- callbackArgs = (node, datetime.now()),
- errbackArgs = (node, datetime.now()))
- return df
- def _pingHandler(self, dict, node, start):
- """Node responded properly, update it and return the node object."""
- self.stats.completedAction('ping', start)
- del self.pinging[node.id]
- # Create the node using the returned contact info
- n = self.Node(dict['id'], dict['_krpc_sender'][0], dict['_krpc_sender'][1])
- reactor.callLater(0, self.insertNode, n)
- return n
- def _pingError(self, err, node, start):
- """Error occurred, fail node."""
- log.msg("action ping failed on %s/%s: %s" % (node.host, node.port, err.getErrorMessage()))
- self.stats.completedAction('ping', start)
- # Consume unhandled errors
- self.pinging[node.id].addErrback(lambda ping_err: None)
- del self.pinging[node.id]
- self.nodeFailed(node)
- return err
- def sendJoin(self, node, callback=None, errback=None):
- """Join the DHT by pinging a bootstrap node.
- @type node: L{node.Node}
- @param node: the node to send the join to
- @type callback: C{method}
- @param callback: the method to call with the results, it must take 1
- parameter, the contact info returned by the node
- (optional, defaults to doing nothing with the results)
- @type errback: C{method}
- @param errback: the method to call if an error occurs
- (optional, defaults to calling the callback with the error)
- """
- if errback is None:
- errback = callback
- self.stats.startedAction('join')
- df = node.join(self.node.id)
- df.addCallbacks(self._joinHandler, self._joinError,
- callbackArgs = (node, datetime.now()),
- errbackArgs = (node, datetime.now()))
- if callback:
- df.addCallbacks(callback, errback)
- def _joinHandler(self, dict, node, start):
- """Node responded properly, extract the response."""
- self.stats.completedAction('join', start)
- # Create the node using the returned contact info
- n = self.Node(dict['id'], dict['_krpc_sender'][0], dict['_krpc_sender'][1])
- reactor.callLater(0, self.insertNode, n)
- return (dict['ip_addr'], dict['port'])
- def _joinError(self, err, node, start):
- """Error occurred, fail node."""
- log.msg("action join failed on %s/%s: %s" % (node.host, node.port, err.getErrorMessage()))
- self.stats.completedAction('join', start)
- self.nodeFailed(node)
- return err
- def findCloseNodes(self, callback=lambda a: None):
- """Perform a findNode on the ID one away from our own.
- This will allow us to populate our table with nodes on our network
- closest to our own. This is called as soon as we start up with an
- empty table.
- @type callback: C{method}
- @param callback: the method to call with the results, it must take 1
- parameter, the list of K closest nodes
- (optional, defaults to doing nothing with the results)
- """
- id = self.node.id[:-1] + chr((ord(self.node.id[-1]) + 1) % 256)
- self.findNode(id, callback)
- def refreshTable(self, force = False):
- """Check all the buckets for those that need refreshing.
- @param force: refresh all buckets regardless of last bucket access time
- (optional, defaults to False)
- """
- def callback(nodes):
- pass
- for bucket in self.table.buckets:
- if force or (datetime.now() - bucket.lastAccessed >
- timedelta(seconds=self.config['BUCKET_STALENESS'])):
- # Choose a random ID in the bucket and try and find it
- id = newIDInRange(bucket.min, bucket.max)
- self.findNode(id, callback)
- def shutdown(self):
- """Closes the port and cancels pending later calls."""
- self.listenport.stopListening()
- try:
- self.next_checkpoint.cancel()
- except:
- pass
- for nodeid in self.pinging.keys():
- if isinstance(self.pinging[nodeid], DelayedCall) and self.pinging[nodeid].active():
- self.pinging[nodeid].cancel()
- del self.pinging[nodeid]
- self.store.close()
- def getStats(self):
- """Gather the statistics for the DHT."""
- return self.stats.formatHTML()
- #{ Remote interface
- def krpc_ping(self, id, _krpc_sender = None):
- """Pong with our ID.
- @type id: C{string}
- @param id: the node ID of the sender node
- @type _krpc_sender: (C{string}, C{int})
- @param _krpc_sender: the sender node's IP address and port
- """
- if _krpc_sender is not None:
- n = self.Node(id, _krpc_sender[0], _krpc_sender[1])
- reactor.callLater(0, self.insertNode, n, False)
- return {"id" : self.node.id}
- def krpc_join(self, id, _krpc_sender = None):
- """Add the node by responding with its address and port.
- @type id: C{string}
- @param id: the node ID of the sender node
- @type _krpc_sender: (C{string}, C{int})
- @param _krpc_sender: the sender node's IP address and port
- """
- if _krpc_sender is not None:
- n = self.Node(id, _krpc_sender[0], _krpc_sender[1])
- reactor.callLater(0, self.insertNode, n, False)
- else:
- _krpc_sender = ('127.0.0.1', self.port)
- return {"ip_addr" : _krpc_sender[0], "port" : _krpc_sender[1], "id" : self.node.id}
- def krpc_find_node(self, id, target, _krpc_sender = None):
- """Find the K closest nodes to the target in the local routing table.
- @type target: C{string}
- @param target: the target ID to find nodes for
- @type id: C{string}
- @param id: the node ID of the sender node
- @type _krpc_sender: (C{string}, C{int})
- @param _krpc_sender: the sender node's IP address and port
- """
- if _krpc_sender is not None:
- n = self.Node(id, _krpc_sender[0], _krpc_sender[1])
- reactor.callLater(0, self.insertNode, n, False)
- else:
- _krpc_sender = ('127.0.0.1', self.port)
- nodes = self.table.findNodes(target)
- nodes = map(lambda node: node.contactInfo(), nodes)
- token = sha(self.token_secrets[0] + _krpc_sender[0]).digest()
- return {"nodes" : nodes, "token" : token, "id" : self.node.id}
- class KhashmirRead(KhashmirBase):
- """The read-only Khashmir class, which can only retrieve (not store) key/value mappings."""
- _Node = KNodeRead
- #{ Local interface
- def findValue(self, key, callback):
- """Get the nodes that have values for the key from the global table.
- @type key: C{string}
- @param key: the target key to find the values for
- @type callback: C{method}
- @param callback: the method to call with the results, it must take 1
- parameter, the list of nodes with values
- """
- # Mark the bucket as having been accessed
- self.table.touch(key)
- # Start with ourself
- nodes = [copy(self.node)]
- # Search for others starting with the locally found ones
- state = FindValue(self, key, callback, self.config, self.stats)
- reactor.callLater(0, state.goWithNodes, nodes)
- def valueForKey(self, key, callback, searchlocal = True):
- """Get the values found for key in global table.
- Callback will be called with a list of values for each peer that
- returns unique values. The final callback will be an empty list.
- @type key: C{string}
- @param key: the target key to get the values for
- @type callback: C{method}
- @param callback: the method to call with the results, it must take 2
- parameters: the key, and the values found
- @type searchlocal: C{boolean}
- @param searchlocal: whether to also look for any local values
- """
- def _getValueForKey(nodes, key=key, response=callback, self=self, searchlocal=searchlocal):
- """Use the found nodes to send requests for values to."""
- # Get any local values
- if searchlocal:
- l = self.store.retrieveValues(key)
- if len(l) > 0:
- node = copy(self.node)
- node.updateNumValues(len(l))
- nodes = nodes + [node]
- state = GetValue(self, key, self.config['RETRIEVE_VALUES'], response, self.config, self.stats)
- reactor.callLater(0, state.goWithNodes, nodes)
- # First lookup nodes that have values for the key
- self.findValue(key, _getValueForKey)
- #{ Remote interface
- def krpc_find_value(self, id, key, _krpc_sender = None):
- """Find the number of values stored locally for the key, and the K closest nodes.
- @type key: C{string}
- @param key: the target key to find the values and nodes for
- @type id: C{string}
- @param id: the node ID of the sender node
- @type _krpc_sender: (C{string}, C{int})
- @param _krpc_sender: the sender node's IP address and port
- """
- if _krpc_sender is not None:
- n = self.Node(id, _krpc_sender[0], _krpc_sender[1])
- reactor.callLater(0, self.insertNode, n, False)
- nodes = self.table.findNodes(key)
- nodes = map(lambda node: node.contactInfo(), nodes)
- num_values = self.store.countValues(key)
- return {'nodes' : nodes, 'num' : num_values, "id": self.node.id}
- def krpc_get_value(self, id, key, num, _krpc_sender = None):
- """Retrieve the values stored locally for the key.
- @type key: C{string}
- @param key: the target key to retrieve the values for
- @type num: C{int}
- @param num: the maximum number of values to retrieve, or 0 to
- retrieve all of them
- @type id: C{string}
- @param id: the node ID of the sender node
- @type _krpc_sender: (C{string}, C{int})
- @param _krpc_sender: the sender node's IP address and port
- """
- if _krpc_sender is not None:
- n = self.Node(id, _krpc_sender[0], _krpc_sender[1])
- reactor.callLater(0, self.insertNode, n, False)
- l = self.store.retrieveValues(key)
- if num == 0 or num >= len(l):
- return {'values' : l, "id": self.node.id}
- else:
- shuffle(l)
- return {'values' : l[:num], "id": self.node.id}
- class KhashmirWrite(KhashmirRead):
- """The read-write Khashmir class, which can store and retrieve key/value mappings."""
- _Node = KNodeWrite
- #{ Local interface
- def storeValueForKey(self, key, value, callback=None):
- """Stores the value for the key in the global table.
- No status in this implementation, peers respond but don't indicate
- status of storing values.
- @type key: C{string}
- @param key: the target key to store the value for
- @type value: C{string}
- @param value: the value to store with the key
- @type callback: C{method}
- @param callback: the method to call with the results, it must take 3
- parameters: the key, the value stored, and the result of the store
- (optional, defaults to doing nothing with the results)
- """
- def _storeValueForKey(nodes, key=key, value=value, response=callback, self=self):
- """Use the returned K closest nodes to store the key at."""
- if not response:
- def _storedValueHandler(key, value, sender):
- """Default callback that does nothing."""
- pass
- response = _storedValueHandler
- action = StoreValue(self, key, value, self.config['STORE_REDUNDANCY'], response, self.config, self.stats)
- reactor.callLater(0, action.goWithNodes, nodes)
- # First find the K closest nodes to operate on.
- self.findNode(key, _storeValueForKey)
- #{ Remote interface
- def krpc_store_value(self, id, key, value, token, _krpc_sender = None):
- """Store the value locally with the key.
- @type key: C{string}
- @param key: the target key to store the value for
- @type value: C{string}
- @param value: the value to store with the key
- @param token: the token to confirm that this peer contacted us previously
- @type id: C{string}
- @param id: the node ID of the sender node
- @type _krpc_sender: (C{string}, C{int})
- @param _krpc_sender: the sender node's IP address and port
- """
- if _krpc_sender is not None:
- n = self.Node(id, _krpc_sender[0], _krpc_sender[1])
- reactor.callLater(0, self.insertNode, n, False)
- else:
- _krpc_sender = ('127.0.0.1', self.port)
- for secret in self.token_secrets:
- this_token = sha(secret + _krpc_sender[0]).digest()
- if token == this_token:
- self.store.storeValue(key, value)
- return {"id" : self.node.id}
- raise krpc.KrpcError, (krpc.KRPC_ERROR_INVALID_TOKEN, 'token is invalid, do a find_nodes to get a fresh one')
- class Khashmir(KhashmirWrite):
- """The default Khashmir class (currently the read-write L{KhashmirWrite})."""
- _Node = KNodeWrite
- class SimpleTests(unittest.TestCase):
- timeout = 10
- DHT_DEFAULTS = {'VERSION': 'A000', 'PORT': 9977,
- 'CHECKPOINT_INTERVAL': 300, 'CONCURRENT_REQS': 8,
- 'STORE_REDUNDANCY': 6, 'RETRIEVE_VALUES': -10000,
- 'MAX_FAILURES': 3, 'LOCAL_OK': True,
- 'MIN_PING_INTERVAL': 900,'BUCKET_STALENESS': 3600,
- 'KRPC_TIMEOUT': 9, 'KRPC_INITIAL_DELAY': 2,
- 'KEY_EXPIRE': 3600, 'SPEW': True, }
- def setUp(self):
- d = self.DHT_DEFAULTS.copy()
- d['PORT'] = 4044
- self.a = Khashmir(d)
- d = self.DHT_DEFAULTS.copy()
- d['PORT'] = 4045
- self.b = Khashmir(d)
- def tearDown(self):
- self.a.shutdown()
- self.b.shutdown()
- os.unlink(self.a.store.db)
- os.unlink(self.b.store.db)
- def testAddContact(self):
- self.failUnlessEqual(len(self.a.table.buckets), 1)
- self.failUnlessEqual(len(self.a.table.buckets[0].nodes), 0)
- self.failUnlessEqual(len(self.b.table.buckets), 1)
- self.failUnlessEqual(len(self.b.table.buckets[0].nodes), 0)
- self.a.addContact('127.0.0.1', 4045)
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- self.failUnlessEqual(len(self.a.table.buckets), 1)
- self.failUnlessEqual(len(self.a.table.buckets[0].nodes), 1)
- self.failUnlessEqual(len(self.b.table.buckets), 1)
- self.failUnlessEqual(len(self.b.table.buckets[0].nodes), 1)
- def testStoreRetrieve(self):
- self.a.addContact('127.0.0.1', 4045)
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- self.got = 0
- self.a.storeValueForKey(sha('foo').digest(), 'foobar')
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- self.a.valueForKey(sha('foo').digest(), self._cb)
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- def _cb(self, key, val):
- if not val:
- self.failUnlessEqual(self.got, 1)
- elif 'foobar' in val:
- self.got = 1
- class MultiTest(unittest.TestCase):
- timeout = 30
- num = 20
- DHT_DEFAULTS = {'VERSION': 'A000', 'PORT': 9977,
- 'CHECKPOINT_INTERVAL': 300, 'CONCURRENT_REQS': 8,
- 'STORE_REDUNDANCY': 6, 'RETRIEVE_VALUES': -10000,
- 'MAX_FAILURES': 3, 'LOCAL_OK': True,
- 'MIN_PING_INTERVAL': 900,'BUCKET_STALENESS': 3600,
- 'KRPC_TIMEOUT': 9, 'KRPC_INITIAL_DELAY': 2,
- 'KEY_EXPIRE': 3600, 'SPEW': True, }
- def _done(self, val):
- self.done = 1
- def setUp(self):
- self.l = []
- self.startport = 4088
- for i in range(self.num):
- d = self.DHT_DEFAULTS.copy()
- d['PORT'] = self.startport + i
- self.l.append(Khashmir(d))
- reactor.iterate()
- reactor.iterate()
- for i in self.l:
- i.addContact('127.0.0.1', self.l[randrange(0,self.num)].port)
- i.addContact('127.0.0.1', self.l[randrange(0,self.num)].port)
- i.addContact('127.0.0.1', self.l[randrange(0,self.num)].port)
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- reactor.iterate()
- for i in self.l:
- self.done = 0
- i.findCloseNodes(self._done)
- while not self.done:
- reactor.iterate()
- for i in self.l:
- self.done = 0
- i.findCloseNodes(self._done)
- while not self.done:
- reactor.iterate()
- def tearDown(self):
- for i in self.l:
- i.shutdown()
- os.unlink(i.store.db)
- reactor.iterate()
- def testStoreRetrieve(self):
- for i in range(10):
- K = newID()
- V = newID()
- for a in range(3):
- self.done = 0
- def _scb(key, value, result):
- self.done = 1
- self.l[randrange(0, self.num)].storeValueForKey(K, V, _scb)
- while not self.done:
- reactor.iterate()
- def _rcb(key, val):
- if not val:
- self.done = 1
- self.failUnlessEqual(self.got, 1)
- elif V in val:
- self.got = 1
- for x in range(3):
- self.got = 0
- self.done = 0
- self.l[randrange(0, self.num)].valueForKey(K, _rcb)
- while not self.done:
- reactor.iterate()
- bazar@ao756:~/apt-p2p/apt_p2p_Khashmir$ ls
- actions.py db.py __init__.py khash.py krpc.py node.py util.py
- bencode.py DHT.py khashmir.py knode.py ktable.py stats.py
- bazar@ao756:~/apt-p2p/apt_p2p_Khashmir$ apt-p2p.py
- 2020-01-31 15:12:28+0300 [-] Log opened.
- 2020-01-31 15:12:28+0300 [-] Loading config files: '/etc/apt-p2p/apt-p2p.conf', '/home/bazar/.apt-p2p/apt-p2p.conf', ''
- 2020-01-31 15:12:28+0300 [-] Successfully loaded config files: ''
- 2020-01-31 15:12:28+0300 [-] Starting application with uid/gid None/None
- 2020-01-31 15:12:28+0300 [-] Traceback (most recent call last):
- 2020-01-31 15:12:28+0300 [-] File "/usr/local/bin/apt-p2p.py", line 68, in <module>
- 2020-01-31 15:12:28+0300 [-] DHT = __import__(config.get('DEFAULT', 'DHT')+'.DHT', globals(), locals(), ['DHT'])
- 2020-01-31 15:12:28+0300 [-] File "/usr/local/lib/python2.7/dist-packages/apt_p2p_Khashmir/DHT.py", line 17, in <module>
- 2020-01-31 15:12:28+0300 [-] from khashmir import Khashmir
- 2020-01-31 15:12:28+0300 [-] File "/usr/local/lib/python2.7/dist-packages/apt_p2p_Khashmir/khashmir.py", line 23, in <module>
- 2020-01-31 15:12:28+0300 [-] from db import DB
- 2020-01-31 15:12:28+0300 [-] File "/usr/local/lib/python2.7/dist-packages/apt_p2p_Khashmir/db.py", line 5, in <module>
- 2020-01-31 15:12:28+0300 [-] from pysqlite2 import dbapi2 as sqlite
- 2020-01-31 15:12:28+0300 [-] ImportError: No module named pysqlite2
- bazar@ao756:~/apt-p2p/apt_p2p_Khashmir$ nano db.py
- bazar@ao756:~/apt-p2p/apt_p2p_Khashmir$ cd ..
- bazar@ao756:~/apt-p2p$ ls
- apt_p2p apt_p2p_Khashmir bootstrap1 debian downloader1 LICENSE.md setup.py TODO.md
- apt-p2p.conf apt-p2p.py build docs downloader2 README.md test.py
- bazar@ao756:~/apt-p2p$ ./apt_p2p.py
- bash: ./apt_p2p.py: Нет такого файла или каталога
- bazar@ao756:~/apt-p2p$ python apt_p2p.py
- python: can't open file 'apt_p2p.py': [Errno 2] No such file or directory
- bazar@ao756:~/apt-p2p$ python apt_p2p
- apt_p2p/ apt_p2p_Khashmir/
- bazar@ao756:~/apt-p2p$ python apt_p2p
- apt_p2p/ apt_p2p_Khashmir/
- bazar@ao756:~/apt-p2p$ chmod +x apt-p2p.py
- apt_p2p/ bootstrap1/ downloader1/ .gitignore test.py
- apt-p2p.conf build/ downloader2/ LICENSE.md TODO.md
- apt_p2p_Khashmir/ debian/ .gbp.conf README.md
- apt-p2p.py docs/ .git/ setup.py
- bazar@ao756:~/apt-p2p$ chmod +x apt-p2p.py
- bazar@ao756:~/apt-p2p$ python apt_p2p.py
- python: can't open file 'apt_p2p.py': [Errno 2] No such file or directory
- bazar@ao756:~/apt-p2p$ python apt
- apt_p2p/ apt_p2p_Khashmir/ apt-p2p.py
- bazar@ao756:~/apt-p2p$ python apt-p2p.py
- 2020-01-31 15:14:28+0300 [-] Log opened.
- 2020-01-31 15:14:28+0300 [-] Loading config files: '/etc/apt-p2p/apt-p2p.conf', '/home/bazar/.apt-p2p/apt-p2p.conf', ''
- 2020-01-31 15:14:28+0300 [-] Successfully loaded config files: ''
- 2020-01-31 15:14:28+0300 [-] Starting application with uid/gid None/None
- 2020-01-31 15:14:29+0300 [-] Starting main application server
- 2020-01-31 15:14:29+0300 [-] Traceback (most recent call last):
- 2020-01-31 15:14:29+0300 [-] File "apt-p2p.py", line 73, in <module>
- 2020-01-31 15:14:29+0300 [-] from apt_p2p.apt_p2p import AptP2P
- 2020-01-31 15:14:29+0300 [-] File "/home/bazar/apt-p2p/apt_p2p/apt_p2p.py", line 11, in <module>
- 2020-01-31 15:14:29+0300 [-] from twisted.web2 import static
- 2020-01-31 15:14:29+0300 [-] ImportError: No module named web2
- bazar@ao756:~/apt-p2p$ nano apt
- apt_p2p/ apt-p2p.conf apt_p2p_Khashmir/ apt-p2p.py
- bazar@ao756:~/apt-p2p$ nano apt-p2p.py
- bazar@ao756:~/apt-p2p$ cat apt-p2p.py | grep twisted.web2
- bazar@ao756:~/apt-p2p$ cd apt_p2p/
- bazar@ao756:~/apt-p2p/apt_p2p$ nano apt_p2p.py
- bazar@ao756:~/apt-p2p/apt_p2p$
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement