def connectToNodeServer(self): debug("Connecting to node server @ %s"%repr(self.nodeServer)) while True: self.updateNodeState(NS_CONNECTING) if self.sock != None: self.sock.close() self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sockQueue = net_helpers.SocketQueue(self.sock) self.sockPacker = net_helpers.Packer() try: self.sock.connect(self.nodeServer) break except: debug("Connect failed, trying again in 5s...") self.updateNodeState(NS_FAILED) time.sleep(5) self.updateNodeState(NS_CONNECTED) debug("Connected.") # Reset last packet counter so we don't time out. self.lastPacketReceived = time.time() # send register packet debug("Registering with node server...") b = ByteStream() b.writeByte(P_REGISTER) self.send(b)
def connectToNodeServer(self): debug("Connecting to node server @ %s" % repr(self.nodeServer)) while True: self.updateNodeState(NS_CONNECTING) if self.sock != None: self.sock.close() self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sockQueue = net_helpers.SocketQueue(self.sock) self.sockPacker = net_helpers.Packer() try: self.sock.connect(self.nodeServer) break except: debug("Connect failed, trying again in 5s...") self.updateNodeState(NS_FAILED) time.sleep(5) self.updateNodeState(NS_CONNECTED) debug("Connected.") # Reset last packet counter so we don't time out. self.lastPacketReceived = time.time() # send register packet debug("Registering with node server...") b = ByteStream() b.writeByte(P_REGISTER) self.send(b)
def sendRelayPacket(self, targetId, targetPort, data): """ Sends tunnel info to a node. """ out = ByteStream() out.writeByte(P_RELAY_PACKET) out.writeString(targetId) out.writeString(targetPort) out.writeString(data) self.send(out)
def sendConnectFailed(self, targetId, targetPort, errorCode): """ Sends the connection failed packet back to node. """ out = ByteStream() out.writeByte(P_CONNECT_RESPONSE) out.writeString(targetId) out.writeString(targetPort) out.writeByte(errorCode) self.send(out)
def sendConnectSuccess(self, targetId, targetPort): """ Sends the connection success packet back to node. """ out = ByteStream() out.writeByte(P_CONNECT_RESPONSE) out.writeString(targetId) out.writeString(targetPort) out.writeByte(ERR_NO_ERROR) self.send(out)
def test_can_resume_reading_after_nothing_available(): b = ByteStream() b.write(b"hello") b.read(5) read = b.read(1) assert read is None b.write(b"world") read = b.read(5) assert read.tobytes() == b"world"
def reflectAddress(self): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto("", self.reflectionServer) privIp, privPort = sock.getsockname() data = sock.recv(128) sock.close() response = ByteStream(data) pubIp = response.readString() pubPort = response.readInt() return (privPort, pubIp, pubPort)
def reflectAddress(self): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto('', self.reflectionServer) privIp, privPort = sock.getsockname() data = sock.recv(128) sock.close() response = ByteStream(data) pubIp = response.readString() pubPort = response.readInt() return (privPort, pubIp, pubPort)
def thread(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: sock.connect(PARSER_SERVER_ADDR) except: prnt("Failed to connect:") prnt(traceback.format_exc()) wx.CallAfter(failureFunc) return stream = ByteStream() stream.writeByte(pkt.GET_KEY) stream.writeString(vanityKey) sock.send(stream.toString()) data = sock.recv(1024) sock.close() stream = ByteStream(data) success = stream.readByte() == 1 if success: key = stream.readString() wx.CallAfter(successFunc, key) else: wx.CallAfter(failureFunc)
def run(self): prnt("RaidServer: Booting up...") self.port = net.node.bind("swap:raid") self.centralSock.setblocking(False) while not self.stoppedEvent.isSet(): now = time() # Central server r, w, e = select([self.centralSock], [self.centralSock], [], 0) if r: data = self.centralSock.recv(1024) stream = ByteStream(data) packetType = stream.readByte() if self.port.connectionPending(): conn = self.port.accept() self.clientList.append({'conn': conn, 'playerInfo': None}) for client in self.clientList: conn = client['conn'] if conn.recvPending(): data = conn.recv() if data == None: playerName = client['playerInfo']['name'] if client[ 'playerInfo'] else "<NoInfo>" prnt("Client (%s) left raid, reason=%s" % (playerName, fuzion.formatError( conn.closedReason))) self.lastRaidUpdatePoke = time() self.clientList.remove(client) continue packetType = data.readByte() if packetType == pkt.PLAYER_UPDATE: self.processPlayerUpdate(client, data) if now - self.lastRaidUpdateSent > 2 and now - self.lastRaidUpdatePoke < 5: self.sendRaidUpdate() self.lastRaidUpdateSent = now sleep(0.1) self.port.close() for client in self.clientList: conn = client['conn'] conn.close() self.centralSock.close() prnt("RaidServer: Shutting down...")
def setUp(self): self.HasUri = namedtuple('HasUri', ['uri']) self.bytestream = ByteStream(chunksize=3) self.port = '9876' path = os.path.dirname(__file__) server = os.path.join(path, 'dummyserver.py') self.expected = ''.join(uuid4().hex for _ in xrange(100)) devnull = open(os.devnull, 'w') self.process = subprocess.Popen( [sys.executable, server, self.port, self.expected], stdout=devnull, stderr=devnull) time.sleep(0.1)
def connect(self, targetId, targetPort): self.waitForNS() # Prevent connecting if there is already a outbound connection. if self.getConnection(targetId, targetPort, True): debug("Duplicate connection to %s:%s found."%(targetId, targetPort)) # Yes, this may throw an error in the app, but they shouldn't # be creating duplicate connections anyway, so it doesn't matter. return None debug("Connecting to %s"%targetId) out = ByteStream() out.writeByte(P_CONNECT_REQUEST) out.writeString(targetId) out.writeString(targetPort) self.send(out) conn = NodeConnection(self, targetId, targetPort, True) conn.requestTime = time.time() self.connections.append(conn) while True: # Wait till connected. if conn.state == CS_CONNECTED or conn.state >= CS_FAILED_BASE: if conn.state == CS_FAILED_NO_NODE: debug("Failed to connect: no such node") elif conn.state == CS_FAILED_REJECTED: debug("Failed to connect: rejected") break time.sleep(0.1) return conn
def sendConnectRequest(self, sourceId, targetPort): """ Sends the connection request from sourceId to this node. """ out = ByteStream() out.writeByte(P_CONNECT_REQUEST) out.writeString(sourceId) out.writeString(targetPort) self.send(out)
def run(self): prnt("RaidServer: Booting up...") self.port = net.node.bind("swap:raid") self.centralSock.setblocking(False) while not self.stoppedEvent.isSet(): now = time() # Central server r, w, e = select([self.centralSock], [self.centralSock], [], 0) if r: data = self.centralSock.recv(1024) stream = ByteStream(data) packetType = stream.readByte() if self.port.connectionPending(): conn = self.port.accept() self.clientList.append({ 'conn': conn, 'playerInfo': None }) for client in self.clientList: conn = client['conn'] if conn.recvPending(): data = conn.recv() if data == None: playerName = client['playerInfo']['name'] if client['playerInfo'] else "<NoInfo>" prnt("Client (%s) left raid, reason=%s"%(playerName, fuzion.formatError(conn.closedReason))) self.lastRaidUpdatePoke = time() self.clientList.remove(client) continue packetType = data.readByte() if packetType == pkt.PLAYER_UPDATE: self.processPlayerUpdate(client, data) if now - self.lastRaidUpdateSent > 2 and now - self.lastRaidUpdatePoke < 5: self.sendRaidUpdate() self.lastRaidUpdateSent = now sleep(0.1) self.port.close() for client in self.clientList: conn = client['conn'] conn.close() self.centralSock.close() prnt("RaidServer: Shutting down...")
def closeInternal(self, reason): with self.closedLock: if self.closed: return if reason == ERR_CLOSED_BY_SELF: packet = ByteStream() packet.writeByte(P_CLOSE) self._send(packet.toString()) self.threadStopped.set() self.node.connectionDied(self) self.closed = True self.closedReason = reason if not self.loopback and not self.relay: self.sock.close()
def test_can_find_bytes_several_chunks_ahead(): b = ByteStream() b.write(b"xxx") b.write(b"xxx") b.write(b"xxx") b.write(b"abc") distance = b.until(97) assert distance == 10 distance = b.until(98) assert distance == 11 distance = b.until(99) assert distance == 12
def test_can_write_several_then_read_across_boundaries(): b = ByteStream() b.write(b"aaa") b.write(b"bbb") b.write(b"ccc") b.write(b"ddd") read = b.read(4) assert read.tobytes() == b"aaab" read = b.read(4) assert read.tobytes() == b"bbcc" read = b.read(4) assert read.tobytes() == b"cddd"
def recv(self, raw=False): while len(self.pendingRecv) == 0 and not self.closed: time.sleep(0.1) if self.closed: return None data = self.pendingRecv.pop(0) return ByteStream(data) if not raw else data
def __init__(self,filename): if filename == None: raise(Exception("Null File Name.")) self.bs = ByteStream(filename) self._dex = dxlib.dx_parse(self.bs._bs)
def test_can_accept_chunksize_implementing_int(self): class SemanticChunksize(object): THING_SIZE_BYTES = 64 def __init__(self, n_things=10): self.n_things = n_things def __int__(self): return self.n_things * self.THING_SIZE_BYTES bs = ByteStream(chunksize=SemanticChunksize(n_things=100)) bio = BytesIO() bio.write(os.urandom(int(1e5))) bio.seek(0) chunks = list(bs._process(bio)) self.assertEqual(6400, len(chunks[0]))
def connect(self, targetId, targetPort): self.waitForNS() # Prevent connecting if there is already a outbound connection. if self.getConnection(targetId, targetPort, True): debug("Duplicate connection to %s:%s found." % (targetId, targetPort)) # Yes, this may throw an error in the app, but they shouldn't # be creating duplicate connections anyway, so it doesn't matter. return None debug("Connecting to %s" % targetId) out = ByteStream() out.writeByte(P_CONNECT_REQUEST) out.writeString(targetId) out.writeString(targetPort) self.send(out) conn = NodeConnection(self, targetId, targetPort, True) conn.requestTime = time.time() self.connections.append(conn) while True: # Wait till connected. if conn.state == CS_CONNECTED or conn.state >= CS_FAILED_BASE: if conn.state == CS_FAILED_NO_NODE: debug("Failed to connect: no such node") elif conn.state == CS_FAILED_REJECTED: debug("Failed to connect: rejected") break time.sleep(0.1) return conn
def run(self): global PUBLIC_IP_UPDATE_LAST self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.bind(('', REFLECTION_SERVER_PORT)) debug("Reflection Server listening on %d"%REFLECTION_SERVER_PORT) refreshPublicIP() PUBLIC_IP_UPDATE_LAST = time.time() while True: r, w, e = select([self.sock], [self.sock], [], 0) if r: data, addr = self.sock.recvfrom(1024) ip = addr[0] port = addr[1] if ip == SERVER_GATEWAY_IP: ip = SERVER_PUBLIC_IP out = ByteStream() out.writeString(ip) out.writeInt(port) self.sock.sendto(out.toString(), addr) now = time.time() if now - PUBLIC_IP_UPDATE_LAST > PUBLIC_IP_UPDATE_INTERVAL: PUBLIC_IP_UPDATE_LAST = now threading.Thread(target=refreshPublicIP).start() time.sleep(0.01) self.sock.close()
def test_distance_only_measured_to_next_matching_byte(): b = ByteStream() b.write(b"abcabc") distance = b.until(97) assert distance == 1 distance = b.until(98) assert distance == 2 distance = b.until(99) assert distance == 3
def test_can_find_bytes(): b = ByteStream() b.write(b"abc") distance = b.until(97) assert distance == 1 distance = b.until(98) assert distance == 2 distance = b.until(99) assert distance == 3
def sendRelay(self, targetId, targetPort, data, fromOutbound): # Loopback if self.id == targetId: # Send it to the opposite connection. conn = self.getConnection(targetId, targetPort, not fromOutbound) if conn: conn.injectRelayRead(data) else: debug("sendRelay: Loopback endpoint not found.") return if self.nodeState != NS_REGISTERED: debug("sendRelay: Node not registered. State is %d"%self.nodeState) return out = ByteStream() out.writeByte(P_RELAY_PACKET) out.writeString(targetId) out.writeString(targetPort) out.writeString(data) self.send(out)
def test_can_write_one_then_read_as_two(): b = ByteStream() b.write(b"hello, world") read = b.read(6) assert read.tobytes() == b"hello," read = b.read(6) assert read.tobytes() == b" world"
def send(self, data): if isinstance(data, ByteStream): data = data.toString() packet = ByteStream() packet.writeByte(P_DATA) packet.writeString(data) data = packet.toString() self._send(data) self.lastPacketSent = time.time()
def mainLoop(self): self.connectToNodeServer() while True: now = time.time() if now - self.lastPacketReceived > NS_KEEPALIVE_TIMEOUT: debug("Timed out.") self._disconnected() continue r, w, e = select([self.sock], [self.sock], [self.sock], 0) if r or e: try: d = self.sock.recv(2048) except socket.error as e: d = None if e.errno == 10053: debug("Connection aborted by software, maybe firewall?") else: debug("recv() error: errno=%d"%e.errno) if not d: self._disconnected() continue self.sockPacker.read(d) self.lastPacketReceived = now packet = self.sockPacker.popPacket() if packet: packet = ByteStream(packet) self.gotDataFromNodeServer(packet) if w: if now - self.lastKeepAliveSent > NS_KEEPALIVE_INTERVAL: self.lastKeepAliveSent = now self.send('') self.sockQueue.processNext() # Process stale requested connections. with self.connectionsLock: for connection in self.connections: if connection.state == CS_REQUESTED and now - connection.requestTime > 4: debug("Connection request for %s:%s timed out."%(connection.targetId, connection.targetPort)) connection.state = CS_FAILED_TIMED_OUT self.connections.remove(connection) time.sleep(0.001) self.sock.close()
def sendRelay(self, targetId, targetPort, data, fromOutbound): # Loopback if self.id == targetId: # Send it to the opposite connection. conn = self.getConnection(targetId, targetPort, not fromOutbound) if conn: conn.injectRelayRead(data) else: debug("sendRelay: Loopback endpoint not found.") return if self.nodeState != NS_REGISTERED: debug("sendRelay: Node not registered. State is %d" % self.nodeState) return out = ByteStream() out.writeByte(P_RELAY_PACKET) out.writeString(targetId) out.writeString(targetPort) out.writeString(data) self.send(out)
def run(self): while True: now = time.time() r, w, e = select([self.sock], [self.sock], [self.sock], 0) if r or e: try: data = self.sock.recv(2048) except socket.error as e: debug("%s: .recv() died! errno=%d"%(self.id, e.errno)) break if not data: if self.id: debug("%s: closed"%self.id) else: debug("lost unknown connection") break self.sockPacker.read(data) self.lastPacketReceived = now packet = self.sockPacker.popPacket() if packet: packet = ByteStream(packet) try: self.handlePacket(packet) except: debug("handlePacket crashed.") debug(traceback.format_exc()) if now - self.lastPacketReceived > KEEPALIVE_TIMEOUT: debug("%s: timed out."%self.id) self.sock.close() break if w: if now - self.lastKeepAliveSent > KEEPALIVE_INTERVAL: self.lastKeepAliveSent = now self.send('') self.sockQueue.processNext() time.sleep(0.01) self.ns.nodeDied(self.id)
def __init__(self, output_stream, number, name, access, lock, reclen=128): """ Initialise random-access file. """ # all text-file operations on a RANDOM file (PRINT, WRITE, INPUT, ...) # actually work on the FIELD buffer; the file stream itself is not # touched until PUT or GET. self.reclen = reclen # replace with empty field if already exists self.field = state.io_state.fields[number] self.field.reset(self.reclen) devices.CRLFTextFileBase.__init__(self, ByteStream(self.field.buffer), b'D', b'R') self.operating_mode = b'I' # note that for random files, output_stream must be a seekable stream. self.output_stream = output_stream self.lock_type = lock self.access = access self.lock_list = set() self.number = number self.name = name # position at start of file self.recpos = 0 self.output_stream.seek(0)
def handlePacket(self, data): packet = data.readByte() if packet == P_REGISTER: self.id = self.ns.pushNode(self) out = ByteStream() out.writeByte(P_REGISTER) out.writeString(self.id) self.send(out) elif packet == P_CONNECT_REQUEST: # from source node targetId = data.readString() targetPort = data.readString() debug("%s: requesting connect to %s"%(self.id, targetId)) self.ns.sendConnectRequest(self, targetId, targetPort) elif packet == P_CONNECT_RESPONSE: # from target nodef targetId = data.readString() targetPort = data.readString() accepted = data.readBoolean() debug("%s: response for %s=%s"%(self.id, targetId, repr(accepted))) if accepted: self.ns.sendConnectSuccess(self, targetId, targetPort) else: self.ns.sendConnectRejected(self, targetId, targetPort) elif packet == P_TUNNEL_INFO: targetId = data.readString() targetPort = data.readString() privIp = data.readString() privPort = data.readInt() pubIp = data.readString() pubPort = data.readInt() debug("%s: sending tunnel info to %s"%(self.id, targetId)) self.ns.sendTunnelInfo(self, targetId, targetPort, privIp, privPort, pubIp, pubPort) elif packet == P_RELAY_PACKET: targetId = data.readString() targetPort = data.readString() data = data.readString() self.ns.sendRelayPacket(self, targetId, targetPort, data)
def updateNotConnected(self): if self.state == CS_TUNNELING: debug("Tunneling") self.tunnelTicks += 1 # 0.2 x 20 = 4s for tunnel establishment if self.tunnelTicks == 21: # Switch to relay for now :( debug("Fallback to relay.") self.state = CS_CONNECTED self.relay = True if not self.outbound: self.pushToPort() return mySyn = ByteStream() mySyn.writeByte(P_TUNNEL_SYN) mySyn.writeString(self.node.id) mySyn.writeString(self.targetPort) mySyn = mySyn.toString() myAck = ByteStream() myAck.writeByte(P_TUNNEL_ACK) myAck.writeString(self.node.id) myAck.writeString(self.targetPort) myAck = myAck.toString() theirSyn = ByteStream() theirSyn.writeByte(P_TUNNEL_SYN) theirSyn.writeString(self.targetId) theirSyn.writeString(self.targetPort) theirSyn = theirSyn.toString() theirAck = ByteStream() theirAck.writeByte(P_TUNNEL_ACK) theirAck.writeString(self.targetId) theirAck.writeString(self.targetPort) theirAck = theirAck.toString() while True: r, w, e = select([self.sock], [self.sock], [], 0) if r: try: data, addr = self.sock.recvfrom(4096) except socket.error as e: if e.errno == 10054: # UDP returns a ECONNRESET for IMCP failures, ignore them data = None if data == theirSyn and not self.tunnelGotSyn: self.tunnelGotSyn = True debug("Got syn for tunnel.") elif data == theirAck and self.tunnelGotSyn: self.state = CS_CONNECTED # Lock in the address self.addr = addr self.sock.connect(addr) if not self.outbound: self.pushToPort() debug("Got ack. Tunnel established.") break else: break packetToSend = mySyn if self.tunnelGotSyn: self.sock.sendto(myAck, self.tunnelPrivAddr) self.sock.sendto(myAck, self.tunnelPubAddr) debug("Sending ack...") self.sock.sendto(mySyn, self.tunnelPrivAddr) self.sock.sendto(mySyn, self.tunnelPubAddr) debug("Sending syn...") if self.state != CS_CONNECTED and time.time() - self.acceptTime > 5: debug("Connect timed out. current=%d, accept=%d"%(time.time(), self.acceptTime)) self.state = CS_FAILED_TIMED_OUT self.threadStopped.set() self.node.connectionDied(self)
def sendTunnelInfo(self, targetId, targetPort, privIp, privPort, pubIp, pubPort): """ Sends tunnel info to a node. """ out = ByteStream() out.writeByte(P_TUNNEL_INFO) out.writeString(targetId) out.writeString(targetPort) out.writeString(privIp) out.writeInt(privPort) out.writeString(pubIp) out.writeInt(pubPort) self.send(out)
def run(self): self.acceptTime = time.time() if self.state != CS_CONNECTED: if not self.loopback: # Get tunnel info privIp = socket.gethostbyname(socket.gethostname()) while True: (privPort, pubIp, pubPort) = self.node.reflectAddress() self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: self.sock.bind(("", privPort)) except: debug("Fuzion: Port %d taken, selecting new port." % (privPort)) continue break debug("Bound at", privPort) self.node.sendTunnelInfo(self.targetId, self.targetPort, privIp, privPort, pubIp, pubPort) else: self.state = CS_CONNECTED if not self.outbound: self.pushToPort() while not self.threadStopped.isSet(): now = time.time() if self.state != CS_CONNECTED: self.updateNotConnected() time.sleep(0.2) continue if self.relay: r = len(self.relayedRead) > 0 w = 1 e = 0 else: r, w, e = select([self.sock], [self.sock], [], 0) if r: try: data = ByteStream(self._recv()) except socket.error as e: if e.errno == 10054: # UDP returns a ECONNRESET for IMCP failures, ignore them pass else: debug("Connection errno=%d" % e.errno) else: if data: packetType = data.readByte() if packetType == P_DATA: self.pendingRecv.append(data.readString()) elif packetType == P_CLOSE: self.closeInternal(ERR_CLOSED_BY_REMOTE) break elif packetType == P_KEEP_ALIVE: pass self.lastPacketReceived = now if not data and data is not None: debug("Empty, but not None packet?") if now - self.lastPacketSent > 5: packet = ByteStream() packet.writeByte(P_KEEP_ALIVE) self._send(packet.toString()) self.lastPacketSent = now if self.lastPacketReceived > 0 and now - self.lastPacketReceived > 20: debug( "Timeout, now=%d, lastPacket=%d, diff=%d" % (now, self.lastPacketReceived, now - self.lastPacketReceived) ) self.closeInternal(ERR_TIMED_OUT) break time.sleep(0.01)
def thread(): global currentKey, raidServer, raidClient net.node.waitForNS() # Connect to server... sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(5) try: sock.connect(PARSER_SERVER_ADDR) except: prnt("Failed to connect:") prnt(traceback.format_exc()) wx.CallAfter(failureFunc, "connect_failed") return # Write data stream = ByteStream() stream.writeByte(pkt.JOIN_RAID) stream.writeByte(VERSION_INT) stream.writeString(key) stream.writeString(net.node.getId()) sock.send(stream.toString()) # Read data data = sock.recv(1024) stream = ByteStream(data) # Process data success = stream.readBoolean() if success: currentKey = key isHost = stream.readBoolean() serverNode = net.node.getId() if isHost: prnt("Raid: Joined raid, became host") raidServer = RaidServer(sock) raidServer.start() else: prnt("Raid: Joined raid, didn't become host") serverNode = stream.readString() sock.close() raidClient = RaidClient(serverNode, failureFunc, successFunc) raidClient.start() else: reason = stream.readString() wx.CallAfter(failureFunc, reason) sock.close()
def run(self): self.acceptTime = time.time() if self.state != CS_CONNECTED: if not self.loopback: # Get tunnel info privIp = socket.gethostbyname(socket.gethostname()) while True: (privPort, pubIp, pubPort) = self.node.reflectAddress() self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: self.sock.bind(('', privPort)) except: debug("Fuzion: Port %d taken, selecting new port."%(privPort)) continue break debug("Bound at", privPort) self.node.sendTunnelInfo(self.targetId, self.targetPort, privIp, privPort, pubIp, pubPort) else: self.state = CS_CONNECTED if not self.outbound: self.pushToPort() while not self.threadStopped.isSet(): now = time.time() if self.state != CS_CONNECTED: self.updateNotConnected() time.sleep(0.2) continue if self.relay: r = len(self.relayedRead) > 0 w = 1 e = 0 else: r, w, e = select([self.sock], [self.sock], [], 0) if r: try: data = ByteStream(self._recv()) except socket.error as e: if e.errno == 10054: # UDP returns a ECONNRESET for IMCP failures, ignore them pass else: debug("Connection errno=%d"%e.errno) else: if data: packetType = data.readByte() if packetType == P_DATA: self.pendingRecv.append(data.readString()) elif packetType == P_CLOSE: self.closeInternal(ERR_CLOSED_BY_REMOTE) break elif packetType == P_KEEP_ALIVE: pass self.lastPacketReceived = now if not data and data is not None: debug("Empty, but not None packet?") if now - self.lastPacketSent > 5: packet = ByteStream() packet.writeByte(P_KEEP_ALIVE) self._send(packet.toString()) self.lastPacketSent = now if self.lastPacketReceived > 0 and now - self.lastPacketReceived > 20: debug("Timeout, now=%d, lastPacket=%d, diff=%d"%(now, self.lastPacketReceived, now - self.lastPacketReceived)) self.closeInternal(ERR_TIMED_OUT) break time.sleep(0.01)
def sendTunnelInfo(self, targetId, targetPort, privIp, privPort, pubIp, pubPort): out = ByteStream() out.writeByte(P_TUNNEL_INFO) out.writeString(targetId) out.writeString(targetPort) out.writeString(privIp) out.writeInt(privPort) out.writeString(pubIp) out.writeInt(pubPort) self.send(out)
def getNewServerNode(): global currentKey, raidServer # Connect to server... sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: sock.connect(PARSER_SERVER_ADDR) except: prnt("Failed to connect:") prnt(traceback.format_exc()) return # Write data stream = ByteStream() stream.writeByte(pkt.JOIN_RAID) stream.writeByte(VERSION_INT) stream.writeString(currentKey) stream.writeString(net.node.getId()) sock.send(stream.toString()) # Read data data = sock.recv(1024) stream = ByteStream(data) # Process data success = stream.readBoolean() if success: isHost = stream.readBoolean() serverNode = net.node.getId() if isHost: prnt("Raid: Became host") raidServer = RaidServer(sock) raidServer.start() else: prnt("Raid: Didn't become host") serverNode = stream.readString() sock.close() return serverNode return None
def updateNotConnected(self): if self.state == CS_TUNNELING: debug("Tunneling") self.tunnelTicks += 1 # 0.2 x 20 = 4s for tunnel establishment if self.tunnelTicks == 21: # Switch to relay for now :( debug("Fallback to relay.") self.state = CS_CONNECTED self.relay = True if not self.outbound: self.pushToPort() return mySyn = ByteStream() mySyn.writeByte(P_TUNNEL_SYN) mySyn.writeString(self.node.id) mySyn.writeString(self.targetPort) mySyn = mySyn.toString() myAck = ByteStream() myAck.writeByte(P_TUNNEL_ACK) myAck.writeString(self.node.id) myAck.writeString(self.targetPort) myAck = myAck.toString() theirSyn = ByteStream() theirSyn.writeByte(P_TUNNEL_SYN) theirSyn.writeString(self.targetId) theirSyn.writeString(self.targetPort) theirSyn = theirSyn.toString() theirAck = ByteStream() theirAck.writeByte(P_TUNNEL_ACK) theirAck.writeString(self.targetId) theirAck.writeString(self.targetPort) theirAck = theirAck.toString() while True: r, w, e = select([self.sock], [self.sock], [], 0) if r: try: data, addr = self.sock.recvfrom(4096) except socket.error as e: if e.errno == 10054: # UDP returns a ECONNRESET for IMCP failures, ignore them data = None if data == theirSyn and not self.tunnelGotSyn: self.tunnelGotSyn = True debug("Got syn for tunnel.") elif data == theirAck and self.tunnelGotSyn: self.state = CS_CONNECTED # Lock in the address self.addr = addr self.sock.connect(addr) if not self.outbound: self.pushToPort() debug("Got ack. Tunnel established.") break else: break packetToSend = mySyn if self.tunnelGotSyn: self.sock.sendto(myAck, self.tunnelPrivAddr) self.sock.sendto(myAck, self.tunnelPubAddr) debug("Sending ack...") self.sock.sendto(mySyn, self.tunnelPrivAddr) self.sock.sendto(mySyn, self.tunnelPubAddr) debug("Sending syn...") if self.state != CS_CONNECTED and time.time() - self.acceptTime > 5: debug("Connect timed out. current=%d, accept=%d" % (time.time(), self.acceptTime)) self.state = CS_FAILED_TIMED_OUT self.threadStopped.set() self.node.connectionDied(self)
def gotDataFromNodeServer(self, b): p = b.readByte() if p == P_REGISTER: with self.stateLock: self.id = b.readString() debug("Registered with node server, id is", self.id) self.updateNodeState(NS_REGISTERED) elif p == P_CONNECT_REQUEST: targetId = b.readString() targetPort = b.readString() port = self.getPort(targetPort) if port == None: debug("Rejecting unsilicited connection request from %s at port %s"%(targetId, targetPort)) out = ByteStream() out.writeByte(P_CONNECT_RESPONSE) out.writeString(targetId) out.writeString(targetPort) out.writeBoolean(False) self.send(out) else: debug("Connection request from %s at port %s"%(targetId, targetPort)) out = ByteStream() out.writeByte(P_CONNECT_RESPONSE) out.writeString(targetId) out.writeString(targetPort) out.writeBoolean(True) self.send(out) conn = NodeConnection(self, targetId, targetPort, False) conn.state = CS_ACCEPTED conn.start() self.connections.append(conn) elif p == P_CONNECT_RESPONSE: targetId = b.readString() targetPort = b.readString() errorCode = b.readByte() state = CS_ACCEPTED if errorCode == ERR_NO_NODE: state = CS_FAILED_NO_NODE elif errorCode == ERR_REJECTED: state = CS_FAILED_REJECTED self.updateConnectionState(targetId, targetPort, state, True) if state == CS_ACCEPTED: self.startConnection(targetId, targetPort, True) else: self.removeConnection(targetId, targetPort, True) elif p == P_TUNNEL_INFO: targetId = b.readString() targetPort = b.readString() privIp = b.readString() privPort = b.readInt() pubIp = b.readString() pubPort = b.readInt() conn = self.getConnection(targetId, targetPort) if conn != None: conn.gotTunnelInfo(privIp, privPort, pubIp, pubPort) else: debug("Got connection info for non existant connection to %s:%s"%(targetId, targetPort)) elif p == P_RELAY_PACKET: targetId = b.readString() targetPort = b.readString() data = b.readString() conn = self.getConnection(targetId, targetPort) if conn: conn.injectRelayRead(data)
def gotDataFromNodeServer(self, b): p = b.readByte() if p == P_REGISTER: with self.stateLock: self.id = b.readString() debug("Registered with node server, id is", self.id) self.updateNodeState(NS_REGISTERED) elif p == P_CONNECT_REQUEST: targetId = b.readString() targetPort = b.readString() port = self.getPort(targetPort) if port == None: debug("Rejecting unsilicited connection request from %s at port %s" % (targetId, targetPort)) out = ByteStream() out.writeByte(P_CONNECT_RESPONSE) out.writeString(targetId) out.writeString(targetPort) out.writeBoolean(False) self.send(out) else: debug("Connection request from %s at port %s" % (targetId, targetPort)) out = ByteStream() out.writeByte(P_CONNECT_RESPONSE) out.writeString(targetId) out.writeString(targetPort) out.writeBoolean(True) self.send(out) conn = NodeConnection(self, targetId, targetPort, False) conn.state = CS_ACCEPTED conn.start() self.connections.append(conn) elif p == P_CONNECT_RESPONSE: targetId = b.readString() targetPort = b.readString() errorCode = b.readByte() state = CS_ACCEPTED if errorCode == ERR_NO_NODE: state = CS_FAILED_NO_NODE elif errorCode == ERR_REJECTED: state = CS_FAILED_REJECTED self.updateConnectionState(targetId, targetPort, state, True) if state == CS_ACCEPTED: self.startConnection(targetId, targetPort, True) else: self.removeConnection(targetId, targetPort, True) elif p == P_TUNNEL_INFO: targetId = b.readString() targetPort = b.readString() privIp = b.readString() privPort = b.readInt() pubIp = b.readString() pubPort = b.readInt() conn = self.getConnection(targetId, targetPort) if conn != None: conn.gotTunnelInfo(privIp, privPort, pubIp, pubPort) else: debug("Got connection info for non existant connection to %s:%s" % (targetId, targetPort)) elif p == P_RELAY_PACKET: targetId = b.readString() targetPort = b.readString() data = b.readString() conn = self.getConnection(targetId, targetPort) if conn: conn.injectRelayRead(data)