tree checksum vpatch file split hunks

all signers:

antecedents: 9986-rebroadcast-simple-hearsay-and-more 9987-embargoing

press order:

genesis
9992-handle-edge-cases-add-feedback
9991-improved-logging
9990-keep-ephemeral-ports-open
9989-show-wot-nicks
9988-hash-dedup
9987-embargoing
9986-rebroadcast-simple-hearsay-and-more
9985-single-thread

patch:

- 87FB4A6177C042B76E8C0E34DC153BC2F574E78B90521124A44CF41E02F57AAF13BA15BE758F3A67056F53064C8928F3DA47DBC0CFFB88019AE5456B6F06A9BF
+ 0DCE4472982646FFA031D3C88C98DCDC52C94627A4E046DA8D403A501A118E74D9893604B3DAAB04AF8677711A32CCAC2D12C3A765A64BD8E36A250E0F8986BB
blatta/blatta
(39 . 9)(39 . 8)
5 action="store_true",
6 help="fork and become a daemon")
7 op.add_option(
8 "--debug",
9 action="store_true",
10 help="print debug messages to stdout")
11 "--log-level",
12 help="specify priority level for logging: info or debug")
13 op.add_option(
14 "--listen",
15 metavar="X",
(71 . 11)(70 . 7)
17 op.add_option(
18 "--statedir",
19 metavar="X",
20 help="save persistent channel state (topic, key) in directory X")
21 op.add_option(
22 "--verbose",
23 action="store_true",
24 help="be verbose (print some progress messages to stdout)")
25 help="save persistent channel state (topic) in directory X")
26 if os.name == "posix":
27 op.add_option(
28 "--chroot",
(92 . 7)(87 . 7)
30 if options.channel_name is None:
31 options.channel_name = "#pest"
32 log_format = "%(levelname)s %(asctime)s: %(message)s"
33 if options.debug:
34 if options.log_level == 'debug':
35 logging.basicConfig(level=logging.DEBUG, format=log_format, stream=sys.stdout)
36 else:
37 logging.basicConfig(level=logging.INFO, format=log_format, stream=sys.stdout)
(145 . 5)(140 . 4)
39 except KeyboardInterrupt:
40 logging.error("Interrupted.")
41
42
43 main(sys.argv)
- 481B05A7A3816E07A04DF8C5F0B541F666F4F5975119DFE5609FDD4ECB1A07DEEFB03E2ED3D804C9F916AD8D6D05D4140F2F479F1064DB4B3EF6EC4E75DB2130
+ EAC411466552678C425D22B90318AD903BCAD61213F50DDC38A35DD9DB76C771414F6E63E4DF35282FEF40C3C0B12177B8856DC41BE4887307AB871080FC9E3B
blatta/lib/client.py
(7 . 12)(7 . 12)
48 import base64
49 import traceback
50 import logging
51 from lib.state import State
52 from lib.message import Message
53 from lib.server import VERSION
54 from state import State
55 from message import Message
56 from server import VERSION
57 from funcs import *
58 from lib.commands import BROADCAST
59 from lib.commands import DIRECT
60 from commands import BROADCAST
61 from commands import DIRECT
62
63 class Client(object):
64 __linesep_regexp = re.compile(r"\r?\n")
(181 . 8)(181 . 7)
66 channelname,
67 " ".join(sorted(x
68 for x in self.state.get_peer_handles()))))
69 self.reply("366 %s %s :End of NAMES list"
70 % (self.nickname, channelname))
71 self.reply("366 %s %s :End of NAMES list" % (self.nickname, channelname))
72
73 def list_handler():
74 if len(arguments) < 1:
(289 . 7)(288 . 6)
76 return
77 targetname = arguments[0]
78 message = arguments[1]
79 client = server.get_client(targetname)
80
81 if server.has_channel(targetname):
82 channel = server.get_channel(targetname)
(312 . 8)(310 . 6)
84 "bounces": 0,
85 "command": DIRECT
86 }))
87 if(client):
88 client.message(formatted_message)
89
90 def part_handler():
91 if len(arguments) < 1:
(560 . 9)(556 . 9)
93 try:
94 handler_table[command]()
95 except KeyError:
96 self.reply("421 %s %s :Unknown command" % (self.nickname, command))
97 stack = traceback.format_exc()
98 logging.debug(stack)
99 self.reply("421 %s %s :Unknown command" % (self.nickname, command))
100 stack = traceback.format_exc()
101 logging.debug(stack)
102
103 def socket_readable_notification(self):
104 try:
- A7F781100F32373DF224F187126FCC44DCFB4B4A8BB53E60E1ACAFDCFF0A9CFD71D47F40E50C6C6F3F7C92A5EB4821B8EEC22ECAC01A84AA1E7F67204A9A220E
+ F6B26AA5D1367C471975FF5E943315E7136AB40D21C7A329E030A2CFFFC06B4E8C3C143844560DB05B9233087617D571B0D460F0C4FF63E61AFC58D79FD4A986
blatta/lib/infosec.py
(1 . 12)(1 . 12)
109 import hashlib
110 import lib.serpent
111 from lib.serpent import Serpent
112 from lib.serpent import serpent_cbc_encrypt
113 from lib.serpent import serpent_cbc_decrypt
114 import serpent
115 from serpent import Serpent
116 from serpent import serpent_cbc_encrypt
117 from serpent import serpent_cbc_decrypt
118 from commands import BROADCAST
119 from commands import DIRECT
120 from commands import IGNORE
121 from lib.message import Message
122 from message import Message
123 import base64
124 import binascii
125 import time
(33 . 12)(33 . 17)
127 MALFORMED_PACKET = 2
128 INVALID_SIGNATURE = 3
129 IGNORED = 4
130 MESSAGE_LOGGING_FORMAT = "[%s:%d %s] <- %s %s %s"
131
132 class Infosec(object):
133 def __init__(self, state=None):
134 self.state = state
135
136 def message(self, message):
137 if not message.speaker:
138 logging.error("aborting message send due speaker not being set")
139 return
140
141 # if we are not rebroadcasting we need to set the timestamp
142 if message.timestamp == None:
143 message.original = True
(63 . 8)(68 . 9)
145 else:
146 message_bytes = message.message_bytes
147
148 message_hash = binascii.hexlify(hashlib.sha256(message_bytes).digest())
149
150 if message.command != IGNORE:
151 message_hash = binascii.hexlify(hashlib.sha256(message_bytes).digest())
152 logging.debug("generated message_hash: %s" % message_hash)
153 self.state.add_to_dedup_queue(message_hash)
154 self.state.log(message.speaker, message_bytes, target_peer)
(72 . 10)(78 . 17)
156 if message.command == DIRECT:
157 signed_packet_bytes = self.pack(target_peer, message, message_bytes)
158 target_peer.send(signed_packet_bytes)
159 logging.info(MESSAGE_LOGGING_FORMAT % (target_peer.address,
160 target_peer.port,
161 target_peer.handles[0],
162 message.body,
163 message.bounces,
164 message_hash))
165
166 elif message.command == BROADCAST or message.command == IGNORE:
167 # sanity check
168 if message.message_bytes and message_bytes != message_bytes:
169 logging.debug("aborting send: message modified by station!")
170 logging.error("aborting send: message modified by station!")
171 return
172
173 for peer in self.state.get_keyed_peers():
(86 . 8)(99 . 13)
175
176 signed_packet_bytes = self.pack(peer, message, message_bytes)
177 peer.send(signed_packet_bytes)
178 else:
179 pass
180 if message.command != IGNORE:
181 logging.info(MESSAGE_LOGGING_FORMAT % (peer.address,
182 peer.port,
183 peer.handles[0],
184 message.body,
185 message.bounces,
186 message_hash))
187
188 def get_message_bytes(self, message, peer=None):
189 timestamp = message.timestamp
- 543B50FA952DEA77A3A28AC4166697877605D330DD65B74B50F2E27393F7AA0C3CC08585515661194D65F23F208818A32D2DFF7C3C81385A9473803B4FEE61E6
+ 81527BDB79D3F7C5F42234E6355A530D86FCDC3974A0461782DCD4FE5FC245F8CDCA423F4F033CF207224544525EC222A647F8BF56E70BF5A0F04FBB73120D89
blatta/lib/server.py
(1 . 10)(1 . 9)
194 VERSION = "9986"
195 VERSION = "9985"
196
197 import os
198 import select
199 import socket
200 import sys
201 import sys
202 import tempfile
203 import time
204 import string
(12 . 11)(11 . 13)
206 import sqlite3
207 from datetime import datetime
208 from funcs import *
209 from lib.client import Client
210 from lib.channel import Channel
211 from lib.station import Station
212 from lib.message import Message
213 from lib.infosec import PACKET_SIZE
214 from client import Client
215 from channel import Channel
216 from station import Station
217 from station import EMBARGO_INTERVAL
218 from station import RUBBISH_INTERVAL
219 from message import Message
220 from infosec import PACKET_SIZE
221 import imp
222 import pprint
223 import logging
(28 . 7)(29 . 6)
225 self.channel_name = options.channel_name
226 self.password = options.password
227 self.motdfile = options.motd
228 self.verbose = options.verbose
229 self.logdir = options.logdir
230 self.chroot = options.chroot
231 self.setuid = options.setuid
(37 . 13)(37 . 14)
233 self.pp = pprint.PrettyPrinter(indent=4)
234 self.db_path = options.db_path
235 self.address_table_path = options.address_table_path
236 self.irc_server_address = "127.0.0.1"
237
238 if options.listen:
239 self.address = socket.gethostbyname(options.listen)
240 self.udp_address = socket.gethostbyname(options.listen)
241 else:
242 self.address = ""
243 self.udp_address = ""
244 server_name_limit = 63 # From the RFC.
245 self.name = socket.getfqdn(self.address)[:server_name_limit]
246 self.name = socket.getfqdn(self.udp_address)[:server_name_limit]
247
248 self.channels = {} # irc_lower(Channel name) --> Channel instance.
249 self.client = None
(124 . 13)(125 . 11)
251 def start(self):
252 # Setup UDP first
253 self.udp_server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
254 self.udp_server_socket.bind((self.address, self.udp_port))
255 self.udp_server_socket.bind((self.udp_address, self.udp_port))
256 self.station = Station({ "socket": self.udp_server_socket,
257 "db_path": self.db_path,
258 "address_table_path": self.address_table_path
259 })
260 self.station.start_embargo_queue_checking()
261 self.station.start_rubbish()
262 logging.info("Listening for Pest packets on udp port %d." % self.udp_port)
263
264 serversockets = []
(138 . 7)(137 . 7)
266 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
267 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
268 try:
269 s.bind((self.address, port))
270 s.bind((self.irc_server_address, port))
271 except socket.error as e:
272 logging.error("Could not bind port %s: %s." % (port, e))
273 sys.exit(1)
(155 . 36)(154 . 62)
275 os.setuid(self.setuid[0])
276 logging.info("Setting uid:gid to %s:%s"
277 % (self.setuid[0], self.setuid[1]))
278
279 # event loop setup
280 last_aliveness_check = time.time()
281 last_embargo_queue_check = time.time()
282 last_rubbish_dispatch = time.time()
283 while True:
284 (inputready,outputready,exceptready) = select.select([self.udp_server_socket],[],[],0)
285 (iwtd, owtd, ewtd) = select.select(
286 serversockets + ([self.client.socket] if self.client else []),
287 [self.client.socket] if self.client and self.client.write_queue_size() > 0 else [],
288 [],
289 .2)
290 for x in inputready:
291 if x == self.udp_server_socket:
292 bytes_address_pair = self.udp_server_socket.recvfrom(PACKET_SIZE)
293 self.station.handle_udp_data(bytes_address_pair)
294 # we don't want to be listening for client connections if there's already a client connected
295 if self.client == None:
296 input_sockets = serversockets
297 else:
298 input_sockets = [self.client.socket]
299 output_sockets = ([self.client.socket]
300 if self.client and self.client.write_queue_size() > 0 else [])
301
302 # handle tcp socket events
303 (iwtd, owtd, ewtd) = select.select(input_sockets, output_sockets, [], .2)
304 for x in iwtd:
305 if self.client != None:
306 self.client.socket_readable_notification()
307 else:
308 (conn, addr) = x.accept()
309 self.client = Client(self, conn)
310 self.station.client = self.client
311 logging.info("Accepted connection from %s:%s." % (
312 addr[0], addr[1]))
313 try:
314 (conn, addr) = x.accept()
315 self.client = Client(self, conn)
316 self.station.client = self.client
317 logging.info("Accepted connection from %s:%s." % (
318 addr[0], addr[1]))
319 except socket.error as e:
320 logging.error("Failed to accept new client connection: %s" % e)
321 for x in owtd:
322 if self.client and x == self.client.socket: # client may have been disconnected
323 self.client.socket_writable_notification()
324
325 # handle udp socket events
326 (inputready,outputready,exceptready) = select.select([self.udp_server_socket],[],[],0)
327 for x in inputready:
328 if x == self.udp_server_socket:
329 bytes_address_pair = self.udp_server_socket.recvfrom(PACKET_SIZE)
330 self.station.handle_udp_data(bytes_address_pair)
331
332 # ping pong
333 now = time.time()
334 if last_aliveness_check + 10 < now:
335 if self.client:
336 self.client.check_aliveness()
337 if self.client:
338 self.client.check_aliveness()
339 last_aliveness_check = now
340
341 # clear embargo queue if enough time has elapsed
342 if last_embargo_queue_check + EMBARGO_INTERVAL < now:
343 self.station.check_embargo_queue()
344 last_embargo_queue_check = now
345
346 # spray rubbish
347 if last_rubbish_dispatch + RUBBISH_INTERVAL < now:
348 self.station.send_rubbish()
349 last_rubbish_dispatch = now
350
351 def create_directory(path):
352 if not os.path.isdir(path):
353 os.makedirs(path)
- 8CEB7B9145164136BE138992805EAF4B9565362E11A87AF8D28E0F172B45400FE324CD0A24F4221DBD8E694972B03931C7594D0E9F7BBD064F2C86CD0ED25DD0
+ 034E0AF7BE67265B08FA39744E1AE5637F0B6BF28021748B964CBC1DCB5147F95B6B94EE94160946C54198669F4DAD4F1C98552ADE5B16BB78F327C20958777F
blatta/lib/state.py
(1 . 9)(1 . 8)
358 from lib.peer import Peer
359 from peer import Peer
360 import sqlite3
361 import imp
362 import hashlib
363 import logging
364 import threading
365 from itertools import chain
366
367 class State(object):
(18 . 59)(17 . 61)
369 if State.__instance != None:
370 raise Exception("This class is a singleton")
371 else:
372 self.write_lock = threading.Lock()
373 with self.write_lock:
374 self.socket = socket
375 self.conn = sqlite3.connect(db_path, check_same_thread=False)
376 self.cursor = self.conn.cursor()
377 self.cursor.execute("create table if not exists at(handle_id integer,\
378 address text not null,\
379 port integer not null,\
380 active_at datetime default null,\
381 updated_at datetime default current_timestamp,\
382 unique(handle_id, address, port))")
383
384 self.cursor.execute("create table if not exists wot(peer_id integer primary key)")
385
386 self.cursor.execute("create table if not exists handles(handle_id integer primary key,\
387 peer_id integer,\
388 handle text,\
389 unique(handle))")
390
391 self.cursor.execute("create table if not exists keys(peer_id intenger,\
392 key text,\
393 used_at datetime default current_timestamp,\
394 unique(key))")
395
396 self.cursor.execute("create table if not exists logs(\
397 handle text not null,\
398 peer_id integer,\
399 message_bytes blob not null,\
400 created_at datetime default current_timestamp)")
401
402 self.cursor.execute("create table if not exists dedup_queue(\
403 hash text not null,\
404 created_at datetime default current_timestamp)")
405 self.socket = socket
406 self.conn = sqlite3.connect(db_path, check_same_thread=False)
407 cursor = self.cursor()
408 cursor.execute("create table if not exists at(handle_id integer,\
409 address text not null,\
410 port integer not null,\
411 active_at datetime default null,\
412 updated_at datetime default current_timestamp,\
413 unique(handle_id, address, port))")
414
415 cursor.execute("create table if not exists wot(peer_id integer primary key)")
416
417 cursor.execute("create table if not exists handles(handle_id integer primary key,\
418 peer_id integer,\
419 handle text,\
420 unique(handle))")
421
422 cursor.execute("create table if not exists keys(peer_id intenger,\
423 key text,\
424 used_at datetime default current_timestamp,\
425 unique(key))")
426
427 cursor.execute("create table if not exists logs(\
428 handle text not null,\
429 peer_id integer,\
430 message_bytes blob not null,\
431 created_at datetime default current_timestamp)")
432
433 cursor.execute("create table if not exists dedup_queue(\
434 hash text not null,\
435 created_at datetime default current_timestamp)")
436 State.__instance = self
437
438 def cursor(self):
439 return self.conn.cursor()
440
441 def get_at(self, handle=None):
442 cursor = self.cursor()
443 at = []
444 if handle == None:
445 results = self.cursor.execute("select handle_id,address,port,active_at from at\
446 results = cursor.execute("select handle_id,address,port,active_at from at\
447 order by updated_at desc").fetchall()
448 else:
449 result = self.cursor.execute("select handle_id from handles where handle=?",
450 result = cursor.execute("select handle_id from handles where handle=?",
451 (handle,)).fetchone()
452 if None != result:
453 handle_id = result[0]
454 else:
455 return []
456 results = self.cursor.execute("select handle_id,address,port,active_at from at \
457 results = cursor.execute("select handle_id,address,port,active_at from at \
458 where handle_id=? order by updated_at desc",
459 (handle_id,)).fetchall()
460 for result in results:
461 handle_id, address, port, updated_at = result
462 h = self.cursor.execute("select handle from handles where handle_id=?",
463 h = cursor.execute("select handle from handles where handle_id=?",
464 (handle_id,)).fetchone()[0]
465 at.append({"handle": h,
466 "address": "%s:%s" % (address, port),
(79 . 34)(80 . 35)
468
469
470 def is_duplicate_message(self, message_hash):
471 with self.write_lock:
472 self.cursor.execute("delete from dedup_queue where created_at < datetime(current_timestamp, '-1 hour')")
473 self.conn.commit()
474 result = self.cursor.execute("select hash from dedup_queue where hash=?",
475 (message_hash,)).fetchone()
476 logging.debug("checking if %s is dupe" % message_hash)
477 if(result != None):
478 return True
479 else:
480 return False
481 cursor = self.cursor()
482 cursor.execute("delete from dedup_queue where created_at < datetime(current_timestamp, '-1 hour')")
483 self.conn.commit()
484 result = cursor.execute("select hash from dedup_queue where hash=?",
485 (message_hash,)).fetchone()
486 logging.debug("checking if %s is dupe" % message_hash)
487 if(result != None):
488 return True
489 else:
490 return False
491
492 def add_to_dedup_queue(self, message_hash):
493 with self.write_lock:
494 self.cursor.execute("insert into dedup_queue(hash)\
495 values(?)",
496 (message_hash,))
497 logging.debug("added %s to dedup" % message_hash)
498 self.conn.commit()
499 cursor = self.cursor()
500 cursor.execute("insert into dedup_queue(hash)\
501 values(?)",
502 (message_hash,))
503 logging.debug("added %s to dedup" % message_hash)
504 self.conn.commit()
505
506 def get_last_message_hash(self, handle, peer_id=None):
507 cursor = self.cursor()
508 if peer_id:
509 message_bytes = self.cursor.execute("select message_bytes from logs\
510 message_bytes = cursor.execute("select message_bytes from logs\
511 where handle=? and peer_id=?\
512 order by created_at desc limit 1",
513 (handle, peer_id)).fetchone()
514
515 else:
516 message_bytes = self.cursor.execute("select message_bytes from logs\
517 message_bytes = cursor.execute("select message_bytes from logs\
518 where handle=? and peer_id is null\
519 order by created_at desc limit 1",
520 (handle,)).fetchone()
(117 . 121)(119 . 125)
522 return "\x00" * 32
523
524 def log(self, handle, message_bytes, peer=None):
525 with self.write_lock:
526 if peer != None:
527 peer_id = peer.peer_id
528 else:
529 peer_id = None
530 cursor = self.cursor()
531 if peer != None:
532 peer_id = peer.peer_id
533 else:
534 peer_id = None
535
536 self.cursor.execute("insert into logs(handle, peer_id, message_bytes)\
537 values(?, ?, ?)",
538 (handle, peer_id, buffer(message_bytes)))
539 cursor.execute("insert into logs(handle, peer_id, message_bytes)\
540 values(?, ?, ?)",
541 (handle, peer_id, buffer(message_bytes)))
542
543 def import_at_and_wot(self, at_path):
544 with self.write_lock:
545 wot = imp.load_source('wot', at_path)
546 for peer in wot.peers:
547 results = self.cursor.execute("select * from handles where handle=? limit 1",
548 (peer["name"],)).fetchall()
549 if len(results) == 0:
550 key = peer["key"]
551 port = peer["port"]
552 address = peer["address"]
553 self.cursor.execute("insert into wot(peer_id) values(null)")
554 peer_id = self.cursor.lastrowid
555 self.cursor.execute("insert into handles(peer_id, handle) values(?, ?)",
556 (peer_id, peer["name"]))
557 handle_id = self.cursor.lastrowid
558 self.cursor.execute("insert into at(handle_id, address, port, updated_at) values(?, ?, ?, ?)",
559 (handle_id, peer["address"], peer["port"], None))
560 self.cursor.execute("insert into keys(peer_id, key) values(?, ?)",
561 (peer_id, key))
562 cursor = self.cursor()
563 wot = imp.load_source('wot', at_path)
564 for peer in wot.peers:
565 results = cursor.execute("select * from handles where handle=? limit 1",
566 (peer["name"],)).fetchall()
567 if len(results) == 0:
568 key = peer["key"]
569 port = peer["port"]
570 address = peer["address"]
571 cursor.execute("insert into wot(peer_id) values(null)")
572 peer_id = cursor.lastrowid
573 cursor.execute("insert into handles(peer_id, handle) values(?, ?)",
574 (peer_id, peer["name"]))
575 handle_id = cursor.lastrowid
576 cursor.execute("insert into at(handle_id, address, port, updated_at) values(?, ?, ?, ?)",
577 (handle_id, peer["address"], peer["port"], None))
578 cursor.execute("insert into keys(peer_id, key) values(?, ?)",
579 (peer_id, key))
580
581 self.conn.commit()
582 self.conn.commit()
583
584 def update_at(self, peer, set_active_at=True):
585 with self.write_lock:
586 row = self.cursor.execute("select handle_id from handles where handle=?",
587 (peer["handle"],)).fetchone()
588 if row != None:
589 handle_id = row[0]
590 else:
591 return
592
593 try:
594 self.cursor.execute("insert into at(handle_id, address, port) values(?, ?, ?)",
595 (handle_id, peer["address"], peer["port"]))
596 except sqlite3.IntegrityError as ex:
597 self.cursor.execute("update at set updated_at = current_timestamp\
598 where handle_id=? and address=? and port=?",
599 (handle_id, peer["address"], peer["port"]))
600 if set_active_at:
601 self.cursor.execute("update at set active_at = current_timestamp\
602 where handle_id=? and address=? and port=?",
603 (handle_id, peer["address"], peer["port"]))
604 self.conn.commit()
605 cursor = self.cursor()
606 row = cursor.execute("select handle_id from handles where handle=?",
607 (peer["handle"],)).fetchone()
608 if row != None:
609 handle_id = row[0]
610 else:
611 return
612
613 try:
614 cursor.execute("insert into at(handle_id, address, port) values(?, ?, ?)",
615 (handle_id, peer["address"], peer["port"]))
616 except sqlite3.IntegrityError as ex:
617 cursor.execute("update at set updated_at = current_timestamp\
618 where handle_id=? and address=? and port=?",
619 (handle_id, peer["address"], peer["port"]))
620 if set_active_at:
621 cursor.execute("update at set active_at = current_timestamp\
622 where handle_id=? and address=? and port=?",
623 (handle_id, peer["address"], peer["port"]))
624 self.conn.commit()
625
626 def add_peer(self, handle):
627 with self.write_lock:
628 self.cursor.execute("insert into wot(peer_id) values(null)")
629 peer_id = self.cursor.lastrowid
630 self.cursor.execute("insert into handles(peer_id, handle) values(?, ?)",
631 (peer_id, handle))
632 self.conn.commit()
633 cursor = self.cursor()
634 cursor.execute("insert into wot(peer_id) values(null)")
635 peer_id = self.cursor.lastrowid
636 cursor.execute("insert into handles(peer_id, handle) values(?, ?)",
637 (peer_id, handle))
638 self.conn.commit()
639
640
641 def remove_peer(self, handle):
642 with self.write_lock:
643 # get peer id
644 result = self.cursor.execute("select peer_id from handles where handle=?",
645 (handle,)).fetchone()
646 if result == None:
647 return
648 else:
649 peer_id = result[0]
650 # get all aliases
651 cursor = self.cursor()
652
653 # get peer id
654 result = cursor.execute("select peer_id from handles where handle=?",
655 (handle,)).fetchone()
656 if result == None:
657 return
658 else:
659 peer_id = result[0]
660 # get all aliases
661
662 handle_ids = self.get_handle_ids_for_peer(peer_id)
663 for handle_id in handle_ids:
664 # delete at entries for each alias
665 handle_ids = self.get_handle_ids_for_peer(peer_id)
666 for handle_id in handle_ids:
667 # delete at entries for each alias
668
669 self.cursor.execute("delete from at where handle_id=?", (handle_id,))
670 cursor.execute("delete from at where handle_id=?", (handle_id,))
671
672 self.cursor.execute("delete from handles where peer_id=?", (peer_id,))
673 cursor.execute("delete from handles where peer_id=?", (peer_id,))
674
675 # delete all keys for peer id
676 # delete all keys for peer id
677
678 self.cursor.execute("delete from keys where peer_id=?", (handle_id,))
679
680 # delete peer from wot
681
682 self.cursor.execute("delete from wot where peer_id=?", (peer_id,))
683 self.conn.commit()
684 cursor.execute("delete from keys where peer_id=?", (handle_id,))
685
686 # delete peer from wot
687
688 cursor.execute("delete from wot where peer_id=?", (peer_id,))
689 self.conn.commit()
690
691
692 def add_key(self, handle, key):
693 with self.write_lock:
694 peer_id = self.cursor.execute("select peer_id from handles where handle=?", (handle,)).fetchone()[0]
695 if peer_id != None:
696 self.cursor.execute("insert into keys(peer_id, key) values(?, ?)", (peer_id, key))
697 self.conn.commit()
698 cursor = self.cursor()
699 peer_id = cursor.execute("select peer_id from handles where handle=?", (handle,)).fetchone()[0]
700 if peer_id != None:
701 cursor.execute("insert into keys(peer_id, key) values(?, ?)", (peer_id, key))
702 self.conn.commit()
703
704 def remove_key(self, key):
705 with self.write_lock:
706 self.cursor.execute("delete from keys where key=?", (key,))
707 self.conn.commit()
708 cursor = self.cursor()
709 cursor.execute("delete from keys where key=?", (key,))
710 self.conn.commit()
711
712 def get_handle_ids_for_peer(self, peer_id):
713 return list(chain.from_iterable(self.cursor.execute("select handle_id from handles where peer_id=?",
714 cursor = self.cursor()
715 return list(chain.from_iterable(cursor.execute("select handle_id from handles where peer_id=?",
716 (peer_id,)).fetchall()))
717
718 def get_peer_handles(self):
719 handles = self.listify(self.cursor.execute("select handle from handles").fetchall())
720 cursor = self.cursor()
721 handles = self.listify(cursor.execute("select handle from handles").fetchall())
722 return handles
723
724 def get_peers(self):
725 cursor = self.cursor()
726 peers = []
727 handles = self.cursor.execute("select handle from handles").fetchall()
728 handles = cursor.execute("select handle from handles").fetchall()
729
730 for handle in handles:
731 peer = self.get_peer_by_handle(handle[0])
(243 . 10)(249 . 11)
733 return list(chain.from_iterable(results))
734
735 def get_keyed_peers(self):
736 peer_ids = self.listify(self.cursor.execute("select peer_id from keys").fetchall())
737 cursor = self.cursor()
738 peer_ids = self.listify(cursor.execute("select peer_id from keys").fetchall())
739 peers = []
740 for peer_id in peer_ids:
741 handle = self.cursor.execute("select handle from handles where peer_id=?", (peer_id,)).fetchone()[0]
742 handle = cursor.execute("select handle from handles where peer_id=?", (peer_id,)).fetchone()[0]
743 peer = self.get_peer_by_handle(handle)
744 if self.is_duplicate(peers, peer):
745 continue
(257 . 18)(264 . 19)
747
748
749 def get_peer_by_handle(self, handle):
750 handle_info = self.cursor.execute("select handle_id, peer_id from handles where handle=?",
751 cursor = self.cursor()
752 handle_info = cursor.execute("select handle_id, peer_id from handles where handle=?",
753 (handle,)).fetchone()
754
755 if handle_info == None:
756 return None
757
758 address = self.cursor.execute("select address, port from at where handle_id=?\
759 address = cursor.execute("select address, port from at where handle_id=?\
760 order by updated_at desc limit 1",
761 (handle_info[0],)).fetchone()
762 handles = self.listify(self.cursor.execute("select handle from handles where peer_id=?",
763 handles = self.listify(cursor.execute("select handle from handles where peer_id=?",
764 (handle_info[1],)).fetchall())
765 keys = self.listify(self.cursor.execute("select key from keys where peer_id=?\
766 keys = self.listify(cursor.execute("select key from keys where peer_id=?\
767 order by used_at desc",
768 (handle_info[1],)).fetchall())
769 return Peer(self.socket, {
- AF78FE5EF8EC6919AE03EE8DA359DEBB290963F184560C69C7005D483819040E1D34C5E00E40092F1A962BFBC60922741018FEE44A8CB5764FCE8B594D29934D
+ 05F39E51685760A96A63D9D96565FF66C8D6A44A521787AF7E992EC7F0FD50B589DF8EE69FF81DB69823D98CBE223FB157047157F43C43F4CCC504498530F027
blatta/lib/station.py
(1 . 23)(1 . 23)
774 import time
775 import threading
776 import binascii
777 import logging
778 import os
779 from lib.state import State
780 from lib.infosec import MAX_BOUNCES
781 from lib.infosec import STALE_PACKET
782 from lib.infosec import DUPLICATE_PACKET
783 from lib.infosec import MALFORMED_PACKET
784 from lib.infosec import INVALID_SIGNATURE
785 from lib.infosec import IGNORED
786 from lib.infosec import Infosec
787 from state import State
788 from infosec import MAX_BOUNCES
789 from infosec import STALE_PACKET
790 from infosec import DUPLICATE_PACKET
791 from infosec import MALFORMED_PACKET
792 from infosec import INVALID_SIGNATURE
793 from infosec import IGNORED
794 from infosec import Infosec
795 from commands import IGNORE
796 from lib.message import Message
797 from message import Message
798 from commands import BROADCAST
799 from commands import DIRECT
800 from lib.peer import Peer
801 from peer import Peer
802
803 RUBBISH_INTERVAL = 10
804 EMBARGO_INTERVAL = 1
805
806 class Station(object):
807 def __init__(self, options):
(27 . 14)(27 . 6)
809 self.state.import_at_and_wot(options.get("address_table_path"))
810 self.infosec = Infosec(self.state)
811 self.embargo_queue = {}
812 self.embargo_queue_lock = threading.Lock()
813
814 def start_embargo_queue_checking(self):
815 threading.Thread(target=self.check_embargo_queue).start()
816
817 def start_rubbish(self):
818 pass
819 threading.Thread(target=self.send_rubbish).start()
820
821 def handle_udp_data(self, bytes_address_pair):
822 data = bytes_address_pair[0]
(47 . 7)(39 . 12)
824 message = self.infosec.unpack(peer, data)
825 error_code = message.error_code
826 if(error_code == None):
827 logging.debug("%s(%s) -> %s bounces: %d" % (message.speaker, peer.handles[0], message.body, message.bounces))
828 logging.info("[%s:%d %s] -> %s %d %s" % (peer.address,
829 peer.port,
830 peer.handles[0],
831 message.body,
832 message.bounces,
833 message.message_hash))
834 self.conditionally_update_at(peer, message, address)
835
836 # if this is a direct message, just deliver it and return
(87 . 22)(84 . 14)
838 def embargo(self, message):
839 # initialize the key/value to empty array if not in the hash
840 # append message to array
841 with self.embargo_queue_lock:
842 if not message.message_hash in self.embargo_queue.keys():
843 self.embargo_queue[message.message_hash] = []
844 self.embargo_queue[message.message_hash].append(message)
845 if not message.message_hash in self.embargo_queue.keys():
846 self.embargo_queue[message.message_hash] = []
847 self.embargo_queue[message.message_hash].append(message)
848
849 def check_embargo_queue(self):
850 # get a lock so other threads can't mess with the db or the queue
851 with self.embargo_queue_lock:
852 self.check_for_immediate_messages()
853 self.flush_hearsay_messages()
854
855 # release the lock
856
857 # continue the thread loop after interval
858 time.sleep(1)
859 threading.Thread(target=self.check_embargo_queue).start()
860 self.check_for_immediate_messages()
861 self.flush_hearsay_messages()
862
863 def check_for_immediate_messages(self):
864 for key in dict(self.embargo_queue).keys():
(169 . 18)(158 . 14)
866 message.bounces = message.bounces + 1
867 self.infosec.message(message)
868 else:
869 logging.debug("[%s:%d] -> packet TTL expired: %s" % packet_info)
870 logging.debug("message TTL expired: %s" % message.message_hash)
871
872
873 def send_rubbish(self):
874 logging.debug("sending rubbish...")
875 with self.embargo_queue_lock:
876 if self.client:
877 self.infosec.message(Message({
878 "speaker": self.client.nickname,
879 "command": IGNORE,
880 "bounces": 0,
881 "body": self.infosec.gen_rubbish_body()
882 }))
883 time.sleep(RUBBISH_INTERVAL)
884 threading.Thread(target=self.send_rubbish).start()
885 if self.client:
886 self.infosec.message(Message({
887 "speaker": self.client.nickname,
888 "command": IGNORE,
889 "bounces": 0,
890 "body": self.infosec.gen_rubbish_body()
891 }))
- 24A5C19318989DA9F79790107499E2EBDA16BC5389B739E4E3AE686C3FF024317517203B9C5C3324AE1A391A63F94939E22C8DE730E758ECBC6AFEE4F54E108D
+ 2D26B4E88714111204FDFFB51AA603BC94F517781589411BD72BE924ABE9FC4DDF6F344EBF3DEC070580C4211B0FD533B3C8A45617F8C07A685166A33AE3118D
blatta/start_test_net.sh
(1 . 6)(1 . 6)
896 #!/bin/bash
897
898 # start 3 servers on different ports
899 ./blatta --debug --channel-name \#aleth --irc-port 9968 --udp-port 7778 --db-path a.db --address-table-path test_net_configs/a.py > logs/a &
900 ./blatta --debug --channel-name \#aleth --irc-port 6669 --udp-port 7779 --db-path b.db --address-table-path test_net_configs/b.py > logs/b &
901 ./blatta --debug --channel-name \#aleth --irc-port 6670 --udp-port 7780 --db-path c.db --address-table-path test_net_configs/c.py > logs/c &
902 ./blatta --log-level info --channel-name \#aleth --irc-port 9968 --udp-port 7778 --db-path a.db --address-table-path test_net_configs/a.py > logs/a &
903 ./blatta --log-level info --channel-name \#aleth --irc-port 6669 --udp-port 7779 --db-path b.db --address-table-path test_net_configs/b.py > logs/b &
904 ./blatta --log-level debug --channel-name \#aleth --irc-port 6670 --udp-port 7780 --db-path c.db --address-table-path test_net_configs/c.py > logs/c &