Skip to content

Commit

Permalink
Merge branch 'main' of github.com:slavashell/dht-messenger into main
Browse files Browse the repository at this point in the history
  • Loading branch information
slavashell committed Mar 24, 2022
2 parents bb73adc + 1403511 commit 7c8c856
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
FROM python:3.8-slim

ENV PYTHONUNBUFFERED=1

COPY requirements.txt /
RUN pip install -r requirements.txt

Expand Down
35 changes: 34 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,34 @@
# dht-messenger
# dht-messenger

Простой мессенджер на базе DHT Kademlia.

Все сообщения распределённо хранятся на нодах участников сети, при этом система переживает выходы участников и перераспределяет нагрузку при добавлении новых.

# Приницип работы

Допустим Bob и Alice хотят обмениваться сообщениями:
1. Bob и Alice обмениваются своими публичными ключами pkbob и pkalice
2. Alice хочет отправить первое зашифрованное сообщение - она кладет его на адрес `h(pkalice, pkbob)`
4. Alice добавляет в сообщение адрес её следующего сообщения
5. `1st message = (key=h(pkalice, pkbob), encrypt(message(text1, next_key=h(key, text1), ts=t1)))`
6. Alice отправляет второе сообщение по сгенерированному адресу
7. `2nd message = (key=next_key, encrypt(message(text2, next_key=h(next_key, text2), ts=t2)))`
8. Образуется цепочка сообщений Alice, которую могут читать как Alice, так и Bob
9. Bob аналогично пишет сообщения в цепочку, начиная с адреса `h(pkbob, pkalice)`
10. Для восстановления диалога Alice или Bob считывают обе цепочки, начиная с генезисных ключей, и мержат по timestamp-ам


# Развертывание
1. Поднимае dht ноду на сервере до которого смогут достучаться остальные участники сети.

```
cd messenger
uvicorn server:app
```

2. Подключаемся к ноде консольным клиентом

```
cd app
python3 app.py
```
36 changes: 36 additions & 0 deletions messenger/bootstrap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import logging
import asyncio

from node import DHTServer

handler = logging.StreamHandler()
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
log = logging.getLogger("kademlia")
log.addHandler(handler)
log.setLevel(logging.DEBUG)

server = DHTServer()


def create_bootstrap_node():
loop = asyncio.get_event_loop()
loop.set_debug(True)

loop.run_until_complete(server.listen(8468))
server.ping_neighbors()
try:
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
server.stop()
loop.close()


def main():
create_bootstrap_node()


if __name__ == "__main__":
main()
29 changes: 28 additions & 1 deletion messenger/node.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,39 @@
import asyncio
import typing as tp

from kademlia.network import Server


class DHTServer(Server):
def ping_neighbors(self):
asyncio.ensure_future(self._ping_neighbors())
loop = asyncio.get_event_loop()
self.ping_loop = loop.call_later(1, self.ping_neighbors)

async def _ping_neighbors(self):
neighbors = self.protocol.router.find_neighbors(self.node)
for node in neighbors:
await self.protocol.call_ping(node)

def stop(self):
if self.transport is not None:
self.transport.close()

if self.refresh_loop:
self.refresh_loop.cancel()

if self.save_state_loop:
self.save_state_loop.cancel()

if self.ping_loop:
self.ping_loop.cancel()


class DHTNode:
def __init__(self, port: int, nodes: tp.List[tp.Tuple[str, int]]) -> None:
self._nodes = nodes
self._port = port
self._server = Server()
self._server = DHTServer()

async def __aenter__(self) -> "DHTNode":
await self.connect()
Expand All @@ -19,6 +45,7 @@ async def __aexit__(self, exc_type, exc, tb) -> None:
async def connect(self) -> None:
await self._server.listen(self._port)
await self._server.bootstrap(self._nodes)
self._server.ping_neighbors()

def stop(self) -> None:
self._server.stop()
Expand Down
9 changes: 9 additions & 0 deletions messenger/server.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import logging

from fastapi import FastAPI, Response

from client import Client
Expand All @@ -8,6 +10,13 @@
app = FastAPI()
client = Client(DHTNode(8469, [("84.201.160.14", 8468)]))

handler = logging.StreamHandler()
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
log = logging.getLogger("kademlia")
log.addHandler(handler)
log.setLevel(logging.DEBUG)

try:
user_manager = UserManager.from_file(".")
client.init(User(public_key=user_manager.public_key, private_key=user_manager.private_key))
Expand Down

0 comments on commit 7c8c856

Please sign in to comment.