def dealWithMessage(message): '''Examine the received message and decide what to do with it''' print("Hmm, the MessageShuffler has been given some kind of message") # We must be online if we've received a message Contacts.comeOnline(MessageShuffler.getOwnTorId()) if message.senderMustBeTrusted: sender = DbClient.getProfile(message.senderId, False) if not sender or sender['status'] != "trusted": return # throw message away if not message.isComplete(): print("A message of type", message.encryptionType, "was received but it's not complete - throwing away") return # throw message away # if it's not encrypted, it's for us -> save in inbox if message.encryptionType == Message.ENCTYPE_NONE: MessageShuffler.dealWithUnencryptedMessage(message) elif message.encryptionType == Message.ENCTYPE_SYMM: # if it's symmetric, forget it for now pass elif message.encryptionType == Message.ENCTYPE_ASYM: MessageShuffler.dealWithAsymmetricMessage(message) else: print("Hä? What kind of encryption type is that? ", message.encryptionType) # Log receipt of message (do we want to know about relays at all?) if message.encryptionType in [Message.ENCTYPE_NONE, Message.ENCTYPE_ASYM]: logMessage = "Message of type: %s received from %s" % (message.getMessageTypeKey(), message.senderId) MessageShuffler.getTannoy().shout(logMessage)
def testComingOnline(self): '''Check that a contact coming online is handled properly''' contacts = Contacts() contacts.comeOnline("abcdef") self.assertTrue(contacts.isOnline("abcdef")) self.assertIsNotNone(contacts.lastSeen("abcdef"), "last seen time should be filled now") # Other contacts should still be offline self.assertFalse(contacts.isOnline("abcdef2")) self.assertFalse(contacts.isOnline("ABCDEF")) self.assertFalse(contacts.isOnline("ghijklmn")) self.assertIsNone(contacts.lastSeen("ghijklmn"), "last seen time should be None") self.assertIsNone(contacts.lastSeen(None), "last seen time should be None") self.assertIsNone(contacts.lastSeen(""), "last seen time should be None")
def testGoingOffline(self): '''Check that a contact going offline is handled properly''' contacts = Contacts() contacts.comeOnline("abcdef") self.assertTrue(contacts.isOnline("abcdef")) self.assertIsNotNone(contacts.lastSeen("abcdef"), "last seen time should be filled now") goOnlineTime = contacts.lastSeen("abcdef") # Now go offline again contacts.goneOffline("abcdef") self.assertFalse(contacts.isOnline("abcdef")) self.assertIsNotNone(contacts.lastSeen("abcdef"), "last seen time should be filled now") goOfflineTime = contacts.lastSeen("abcdef") self.assertNotEqual(goOnlineTime, goOfflineTime) # Reappear contacts.comeOnline("abcdef") self.assertTrue(contacts.isOnline("abcdef")) self.assertIsNotNone(contacts.lastSeen("abcdef"), "last seen time should be filled now") reappearTime = contacts.lastSeen("abcdef") self.assertNotEqual(goOnlineTime, reappearTime) self.assertNotEqual(goOfflineTime, reappearTime)
def sendMessage(self, message, whoto): # Check status of recipient in profile profile = DbClient.getProfile(whoto, False) status = profile['status'] if profile else "deleted" if status in ['deleted', 'blocked']: return self.RC_MESSAGE_IGNORED print("Trying to send message to '%s'" % whoto) if whoto is not None and len(whoto) == 16: try: s = socks.socksocket() s.setproxy(socks.PROXY_TYPE_SOCKS4, "localhost", 11109) s.connect((whoto + ".onion", 11009)) numsent = s.send(message) s.close() if numsent != len(message): print("Oops - num bytes sent:", numsent, "but message has length:", len(message)) # For really long messages, maybe need to chunk into 4k blocks or something? else: Contacts.comeOnline(whoto) return self.RC_MESSAGE_SENT except Exception as e: print("Woah, that threw something:", e) print("Bailed from the send attempt, returning failure") return self.RC_MESSAGE_FAILED # it didn't work
def dealWithAsymmetricMessage(message): '''Decide what to do with the given asymmetric message''' if message.senderId == MessageShuffler.getOwnTorId(): print("*** Shouldn't receive a message from myself!") return # Sort message according to type if message.messageType == Message.TYPE_CONTACT_RESPONSE: print("Received a contact accept from", message.senderId, "name", message.senderName) if MessageShuffler._isProfileStatusOk(message.senderId, ['pending', 'requested', 'untrusted']): print(message.senderName, "'s public key is", message.senderKey) ContactMaker.handleReceiveAccept(message.senderId, message.senderName, message.senderKey) # Call DbClient to store new message in inbox rowToStore = {"messageType":"contactresponse", "fromId":message.senderId, "fromName":message.senderName, "messageBody":message.introMessage, "accepted":True, "messageRead":False, "messageReplied":False, "timestamp":message.timestamp, "recipients":MessageShuffler.getOwnTorId()} DbClient.addMessageToInbox(rowToStore) elif MessageShuffler._isProfileStatusOk(message.senderId, [None, 'blocked']): print("Received a contact response but I didn't send them a request!") print("Encrypted contents are:", message.encryptedContents) rowToStore = {"messageType":"contactresponse", "fromId":message.senderId, "fromName":message.senderName, "messageBody":message.introMessage, "accepted":True, "timestamp":message.timestamp, "encryptedMsg":message.encryptedContents} DbClient.addMessageToPendingContacts(rowToStore) elif message.messageType == Message.TYPE_STATUS_NOTIFY: if message.online: print("One of our contacts has just come online- ", message.senderId, "and hash is", message.profileHash) prof = DbClient.getProfile(userid=message.senderId, extend=False) if prof: storedHash = prof.get("profileHash", "empty") if message.profileHash != storedHash: reply = InfoRequestMessage(infoType=InfoRequestMessage.INFO_PROFILE) reply.recipients = [message.senderId] DbClient.addMessageToOutbox(reply) if message.ping: print("Now sending back a pong, too") reply = StatusNotifyMessage(online=True, ping=False, profileHash=None) reply.recipients = [message.senderId] DbClient.addMessageToOutbox(reply) else: print("It's already a pong so I won't reply") Contacts.comeOnline(message.senderId) else: print("One of our contacts is going offline -", message.senderId) Contacts.goneOffline(message.senderId) elif message.messageType == Message.TYPE_INFO_REQUEST: print("I've received an info request message for type", message.infoType) if MessageShuffler._isProfileStatusOk(message.senderId, ['trusted']): reply = InfoResponseMessage(message.messageType) reply.recipients = [message.senderId] DbClient.addMessageToOutbox(reply) elif message.messageType == Message.TYPE_INFO_RESPONSE: if message.profile and MessageShuffler._isProfileStatusOk(message.senderId, ['trusted', 'untrusted']): if message.profileHash: message.profile['profileHash'] = message.profileHash DbClient.updateContact(message.senderId, message.profile) elif message.messageType == Message.TYPE_ASYM_MESSAGE: print("It's a general kind of message, this should go in the Inbox, right?") if MessageShuffler._isProfileStatusOk(message.senderId, ['trusted', 'untrusted']): Contacts.comeOnline(message.senderId) else: # It's another asymmetric message type print("Hä? What kind of asymmetric message type is that? ", message.messageType)