raw
genesis                 1 from lib.peer import Peer
genesis 2 import sqlite3
genesis 3 import imp
genesis 4 import hashlib
genesis 5 from itertools import chain
genesis 6
genesis 7 class State(object):
genesis 8
genesis 9 def __init__(self, server, db_path):
genesis 10 self.server = server
genesis 11 self.conn = sqlite3.connect(db_path)
genesis 12 self.cursor = self.conn.cursor()
genesis 13 self.cursor.execute("create table if not exists at(handle_id integer,\
genesis 14 address text not null,\
genesis 15 port integer not null,\
genesis 16 updated_at datetime default current_timestamp,\
genesis 17 unique(handle_id, address, port))")
genesis 18
genesis 19 self.cursor.execute("create table if not exists wot(peer_id integer primary key)")
genesis 20
genesis 21 self.cursor.execute("create table if not exists handles(handle_id integer primary key,\
genesis 22 peer_id integer,\
genesis 23 handle text,\
genesis 24 unique(handle))")
genesis 25
genesis 26 self.cursor.execute("create table if not exists keys(peer_id intenger,\
genesis 27 key text,\
genesis 28 used_at datetime default current_timestamp,\
genesis 29 unique(key))")
genesis 30
genesis 31 self.cursor.execute("create table if not exists logs(\
genesis 32 handle text not null,\
genesis 33 peer_id integer,\
genesis 34 message_bytes blob not null,\
genesis 35 created_at datetime default current_timestamp)")
genesis 36
genesis 37 def get_at(self, handle=None):
genesis 38 at = []
genesis 39 if handle == None:
genesis 40 results = self.cursor.execute("select handle_id,address,port,updated_at from at\
genesis 41 order by updated_at desc").fetchall()
genesis 42 else:
9992-handle-edge-... 43 result = self.cursor.execute("select handle_id from handles where handle=?",
9992-handle-edge-... 44 (handle,)).fetchone()
9992-handle-edge-... 45 if None != result:
9992-handle-edge-... 46 handle_id = result[0]
genesis 47 else:
genesis 48 return []
9992-handle-edge-... 49 results = self.cursor.execute("select handle_id,address,port,updated_at from at \
9992-handle-edge-... 50 where handle_id=? order by updated_at desc",
9992-handle-edge-... 51 (handle_id,)).fetchall()
genesis 52 for result in results:
genesis 53 handle_id, address, port, updated_at = result
genesis 54 h = self.cursor.execute("select handle from handles where handle_id=?",
genesis 55 (handle_id,)).fetchone()[0]
genesis 56 at.append({"handle": h,
genesis 57 "address": "%s:%s" % (address, port),
genesis 58 "updated_at": updated_at})
genesis 59 return at
genesis 60
genesis 61
genesis 62 def get_last_message_hash(self, handle, peer_id=None):
genesis 63 if peer_id:
genesis 64 message_bytes = self.cursor.execute("select message_bytes from logs\
genesis 65 where handle=? and peer_id=?\
genesis 66 order by created_at desc limit 1",
genesis 67 (handle, peer_id)).fetchone()
genesis 68
genesis 69 else:
genesis 70 message_bytes = self.cursor.execute("select message_bytes from logs\
genesis 71 where handle=? and peer_id is null\
genesis 72 order by created_at desc limit 1",
genesis 73 (handle,)).fetchone()
genesis 74
genesis 75 if message_bytes:
genesis 76 return hashlib.sha256(message_bytes[0][:]).digest()
genesis 77 else:
genesis 78 return "0" * 32
genesis 79
genesis 80 def log(self, handle, message_bytes, peer_id=None):
genesis 81 self.cursor.execute("insert into logs(handle, peer_id, message_bytes)\
genesis 82 values(?, ?, ?)",
genesis 83 (handle, peer_id, buffer(message_bytes)))
genesis 84
genesis 85 def import_at_and_wot(self, at_path):
genesis 86 wot = imp.load_source('wot', at_path)
genesis 87 for peer in wot.peers:
genesis 88 results = self.cursor.execute("select * from handles where handle=? limit 1",
genesis 89 (peer["name"],)).fetchall()
genesis 90 if len(results) == 0:
genesis 91 key = peer["key"]
genesis 92 port = peer["port"]
genesis 93 address = peer["address"]
genesis 94 self.cursor.execute("insert into wot(peer_id) values(null)")
genesis 95 peer_id = self.cursor.lastrowid
genesis 96 self.cursor.execute("insert into handles(peer_id, handle) values(?, ?)",
genesis 97 (peer_id, peer["name"]))
genesis 98 handle_id = self.cursor.lastrowid
genesis 99 self.cursor.execute("insert into at(handle_id, address, port) values(?, ?, ?)",
genesis 100 (handle_id, peer["address"], peer["port"]))
genesis 101 self.cursor.execute("insert into keys(peer_id, key) values(?, ?)",
genesis 102 (peer_id, key))
genesis 103
genesis 104 self.conn.commit()
genesis 105
genesis 106 def update_address_table(self, peer):
genesis 107 row = self.cursor.execute("select handle_id from handles where handle=?",
genesis 108 (peer["handle"],)).fetchone()
genesis 109 if row != None:
genesis 110 handle_id = row[0]
genesis 111 else:
genesis 112 return
genesis 113
genesis 114 try:
genesis 115 self.cursor.execute("insert into at(handle_id, address, port) values(?, ?, ?)",
genesis 116 (handle_id, peer["address"], peer["port"]))
genesis 117 self.conn.commit()
genesis 118 except sqlite3.IntegrityError as ex:
genesis 119 self.cursor.execute("update at set updated_at = current_timestamp\
genesis 120 where handle_id=? and address=? and port=?",
genesis 121 (handle_id, peer["address"], peer["port"]))
genesis 122 self.conn.commit()
genesis 123
genesis 124 def add_peer(self, handle):
genesis 125 self.cursor.execute("insert into wot(peer_id) values(null)")
genesis 126 peer_id = self.cursor.lastrowid
genesis 127 self.cursor.execute("insert into handles(peer_id, handle) values(?, ?)",
genesis 128 (peer_id, handle))
genesis 129 self.conn.commit()
genesis 130
genesis 131 def remove_peer(self, handle):
genesis 132 # get peer id
genesis 133
9992-handle-edge-... 134 result = self.cursor.execute("select peer_id from handles where handle=?", (handle,)).fetchone()
9992-handle-edge-... 135 if result == None:
9992-handle-edge-... 136 return
genesis 137 else:
9992-handle-edge-... 138 peer_id = result[0]
genesis 139 # get all aliases
genesis 140
genesis 141 handle_ids = self.get_handle_ids_for_peer(peer_id)
genesis 142 for handle_id in handle_ids:
genesis 143 # delete at entries for each alias
genesis 144
genesis 145 self.cursor.execute("delete from at where handle_id=?", (handle_id,))
genesis 146
genesis 147 self.cursor.execute("delete from handles where peer_id=?", (peer_id,))
genesis 148
genesis 149 # delete all keys for peer id
genesis 150
genesis 151 self.cursor.execute("delete from keys where peer_id=?", (handle_id,))
genesis 152
genesis 153 # delete peer from wot
genesis 154
genesis 155 self.cursor.execute("delete from wot where peer_id=?", (peer_id,))
genesis 156 self.conn.commit()
genesis 157
genesis 158
genesis 159 def add_key(self, handle, key):
genesis 160 peer_id = self.cursor.execute("select peer_id from handles where handle=?", (handle,)).fetchone()[0]
genesis 161 if peer_id != None:
genesis 162 self.cursor.execute("insert into keys(peer_id, key) values(?, ?)", (peer_id, key))
genesis 163 self.conn.commit()
genesis 164
genesis 165 def remove_key(self, key):
genesis 166 self.cursor.execute("delete from keys where key=?", (key,))
genesis 167 self.conn.commit()
genesis 168
genesis 169 def get_handle_ids_for_peer(self, peer_id):
genesis 170 return list(chain.from_iterable(self.cursor.execute("select handle_id from handles where peer_id=?",
genesis 171 (peer_id,)).fetchall()))
genesis 172
genesis 173 def get_peers(self):
genesis 174 peers = []
genesis 175 handles = self.cursor.execute("select handle from handles").fetchall()
genesis 176
genesis 177 for handle in handles:
genesis 178 peer = self.get_peer_by_handle(handle[0])
9992-handle-edge-... 179 if not (self.is_duplicate(peers, peer)):
genesis 180 peers.append(peer)
genesis 181 return peers
genesis 182
genesis 183 def get_peer_by_handle(self, handle):
genesis 184 handle_info = self.cursor.execute("select handle_id, peer_id from handles where handle=?",
genesis 185 (handle,)).fetchone()
genesis 186
genesis 187 if handle_info == None:
genesis 188 return None
genesis 189
genesis 190 address = self.cursor.execute("select address, port from at where handle_id=?\
genesis 191 order by updated_at desc limit 1",
genesis 192 (handle_info[0],)).fetchone()
genesis 193 handles = list(chain.from_iterable(self.cursor.execute("select handle from handles where peer_id=?",
genesis 194 (handle_info[1],)).fetchall()))
genesis 195 keys = list(chain.from_iterable(self.cursor.execute("select key from keys where peer_id=?\
genesis 196 order by used_at desc",
genesis 197 (handle_info[1],)).fetchall()))
genesis 198 return Peer(self.server, {
genesis 199 "handles": handles,
genesis 200 "peer_id": handle_info[1],
genesis 201 "address": address[0] if address else "",
genesis 202 "port": address[1] if address else "",
genesis 203 "keys": keys
genesis 204 })
genesis 205 def is_duplicate(self, peers, peer):
genesis 206 for existing_peer in peers:
genesis 207 if existing_peer.address == peer.address and existing_peer.port == peer.port:
genesis 208 return True
genesis 209 return False