Files
@ 3d0876534e40
Branch filter:
Location: Morevna/src/server.py - annotation
3d0876534e40
3.8 KiB
text/x-python
client can pull changes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | d0161c81635b d0161c81635b cd2ba192bf12 d0161c81635b d0161c81635b 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 cd2ba192bf12 cd2ba192bf12 cd2ba192bf12 cd2ba192bf12 34f4027c1bd6 026618d6681b 026618d6681b 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 cd2ba192bf12 026618d6681b 34f4027c1bd6 34f4027c1bd6 b73a5d69a11b 8b0dc65400f3 026618d6681b d0161c81635b 259f29140f23 8b0dc65400f3 8b0dc65400f3 026618d6681b 8b0dc65400f3 026618d6681b 8b0dc65400f3 d0161c81635b 026618d6681b 34f4027c1bd6 cd2ba192bf12 cd2ba192bf12 cd2ba192bf12 cd2ba192bf12 026618d6681b 026618d6681b 026618d6681b 34f4027c1bd6 44cf81f3b6b8 3f9fff4c9811 3f9fff4c9811 3f9fff4c9811 3f9fff4c9811 3f9fff4c9811 3f9fff4c9811 3f9fff4c9811 34f4027c1bd6 b73a5d69a11b dad65188b1a0 cd2ba192bf12 dad65188b1a0 259f29140f23 259f29140f23 dad65188b1a0 dad65188b1a0 34f4027c1bd6 dad65188b1a0 dad65188b1a0 34f4027c1bd6 dad65188b1a0 dad65188b1a0 026618d6681b 259f29140f23 dad65188b1a0 b73a5d69a11b dad65188b1a0 44cf81f3b6b8 44cf81f3b6b8 44cf81f3b6b8 44cf81f3b6b8 dad65188b1a0 dad65188b1a0 dad65188b1a0 34f4027c1bd6 dad65188b1a0 d0161c81635b 259f29140f23 dad65188b1a0 b73a5d69a11b dad65188b1a0 dad65188b1a0 34f4027c1bd6 dad65188b1a0 34f4027c1bd6 44cf81f3b6b8 44cf81f3b6b8 44cf81f3b6b8 44cf81f3b6b8 44cf81f3b6b8 44cf81f3b6b8 44cf81f3b6b8 34f4027c1bd6 44cf81f3b6b8 44cf81f3b6b8 44cf81f3b6b8 44cf81f3b6b8 44cf81f3b6b8 44cf81f3b6b8 44cf81f3b6b8 44cf81f3b6b8 44cf81f3b6b8 34f4027c1bd6 b73a5d69a11b b73a5d69a11b b73a5d69a11b b73a5d69a11b 34f4027c1bd6 b73a5d69a11b 44cf81f3b6b8 44cf81f3b6b8 026618d6681b 44cf81f3b6b8 d0161c81635b 44cf81f3b6b8 34f4027c1bd6 dad65188b1a0 d0161c81635b d0161c81635b d0161c81635b 3f9fff4c9811 3f9fff4c9811 d0161c81635b d0161c81635b 6355fe7d655f 026618d6681b 026618d6681b d0161c81635b | import hashlib
import socket
import ssl
import logging as log
from hashtree import HashTree
from networkers import NetworkReader,NetworkWriter
import config as conf
class Connection:
def __init__(self,serverSocket,sslContext):
sock, address = serverSocket.accept()
self._socket=sslContext.wrap_socket(sock,server_side=True)
log.info('Connected by {0}'.format(address))
fr=self._socket.makefile(mode="rb")
fw=self._socket.makefile(mode="wb")
self.incoming=NetworkReader(fr)
self.outcoming=NetworkWriter(fw)
def __enter__(self):
return self.incoming,self.outcoming
def __exit__(self, exc_type, exc_val, exc_tb):
self._socket.shutdown(socket.SHUT_RDWR)
self._socket.close()
class Server:
def __init__(self,filename,treeFile=""):
self._filename=filename
self._treeFile=treeFile
self._locked=False
if treeFile:
self._tree=HashTree.load(treeFile)
else:
self._tree=HashTree.fromFile(filename)
self._newLeaves=dict()
self.BLOCK_SIZE=self._tree.BLOCK_SIZE
self._ssl=ssl.create_default_context(ssl.Purpose.CLIENT_AUTH,cafile=conf.peers)
self._ssl.verify_mode=ssl.CERT_REQUIRED
self._ssl.load_cert_chain(conf.certfile,conf.keyfile)
self._ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._ss.bind(("", conf.port))
self._ss.listen(1)
self._lastIndex=-1
self._dataFileHandle=None
@property
def _dataFile(self):
if not self._dataFileHandle:
self._dataFileHandle=open(self._filename, mode="rb+")
return self._dataFileHandle
def serve(self):
while True:
with Connection(self._ss,self._ssl) as (incoming, outcoming):
try:
while self._serveOne(incoming,outcoming):
pass
except AssertionError:
continue
def _serveOne(self,incoming,outcoming):
jsonData,binData=incoming.readMsg()
if jsonData["command"]=="init":
assert jsonData["blockSize"]==self.BLOCK_SIZE
assert jsonData["blockCount"]==self._tree.leafCount
self._locked=True
outcoming.writeMsg({"command": "ack"})
elif jsonData["command"]=="req":
if jsonData["dataType"]=="data":
outcoming.writeMsg(*self._requestData(jsonData["index"]))
else:
outcoming.writeMsg(*self._requestHash(jsonData["index"]))
elif jsonData["command"]=="send" and jsonData["dataType"]=="data":
outcoming.writeMsg(*self._receiveData(jsonData,binData))
elif jsonData["command"]=="end":
self._finalize()
self._locked=False
return False
else:
assert False, jsonData["command"]
return True
def _requestHash(self,index):
log.info("received request for node #{0}".format(index))
assert index<len(self._tree.store)
nodeHash=self._tree.store[index]
jsonResponse={"command":"send", "index":index, "dataType":"hash"}
binResponse=nodeHash
return (jsonResponse,binResponse)
def _requestData(self,index):
log.info("received request for data block #{0}".format(index))
jsonResponse={"command":"send", "index":index, "dataType":"data"}
if self._lastIndex+1!=index:
self._dataFile.seek(index*self.BLOCK_SIZE)
binResponse=self._dataFile.read(self.BLOCK_SIZE)
return (jsonResponse,binResponse)
def _receiveData(self,jsonData,binData):
log.info("received data block #{0}: {1}...{2}".format(jsonData["index"],binData[:5],binData[-5:]))
i=jsonData["index"]
if self._lastIndex+1!=i:
self._dataFile.seek(i*self.BLOCK_SIZE)
self._dataFile.write(binData)
self._lastIndex=i
if self._treeFile:
self._newLeaves[i+self._tree.leafStart]=hashlib.sha256(binData).digest()[HashTree.HASH_LEN:]
return ({"command": "ack", "index": i},)
def _finalize(self):
log.info("closing session...")
self._dataFile.close()
self._dataFileHandle=None
if self._treeFile:
log.info("updating hash tree...")
for (k,v) in self._newLeaves.items():
self._tree.updateLeaf(k, v)
self._tree.save(self._treeFile)
log.info("done")
|