Beispiel #1
0
	def testOutbox(self):
		'''Test the storage and retrieval of messages in the outbox'''
		db = supersimpledb.MurmeliDb()
		DbI.setDb(db)
		self.assertEqual(len(DbI.getOutboxMessages()), 0, "Outbox should be empty")
		# Add profile for this the target recipient
		DbI.updateProfile("ABC312", {"keyid":"ZYXW987", "status":"trusted", "name":"Best friend"})

		# add one message to the outbox
		DbI.addToOutbox(ExampleMessage(["ABC312"], "Doesn't matter really what the message is"))
		self.assertEqual(len(DbI.getOutboxMessages()), 1, "Outbox should have one message")
		self.checkMessageIndexes(DbI.getOutboxMessages())
		DbI.addToOutbox(ExampleMessage(["ABC312"], "A second message"))
		self.assertEqual(len(DbI.getOutboxMessages()), 2, "Outbox should have 2 messages")
		self.checkMessageIndexes(DbI.getOutboxMessages())
		self.assertTrue(DbI.deleteFromOutbox(0))
		self.assertEqual(len(DbI.getOutboxMessages()), 1, "Outbox should only have 1 message (1 empty)")
		nonEmptyMessages = DbI.getOutboxMessages()
		self.assertEqual(len(nonEmptyMessages), 1, "Outbox should only have 1 non-empty message")
		self.assertEqual(nonEmptyMessages[0]["_id"], 1, "Message 0 should have index 1")
		# See if index of third message is properly assigned
		DbI.addToOutbox(ExampleMessage(["ABC312"], "A third message"))
		self.assertEqual(len(DbI.getOutboxMessages()), 2, "Outbox should have 2 messages again")
		self.assertEqual(DbI.getOutboxMessages()[0]["_id"], 1, "Message 0 should have index 1")
		self.assertEqual(DbI.getOutboxMessages()[1]["_id"], 2, "Message 1 should have index 2")

		# done
		DbI.releaseDb()
Beispiel #2
0
    def flushOutboxInSeparateThread(self):
        '''This can take quite a while to do the flush'''
        if self._flushing:
            return
        print("Outgoing postman is flushing the outbox...")
        self._flushing = True
        # Look in the outbox for messages
        messagesFound = 0
        messagesSent = 0
        failedRecpts = set()
        for m in DbI.getOutboxMessages():
            if not m:
                continue  # message already deleted
            messagesFound += 1
            # Get recipient, timestamp, relays, message
            message = imageutils.stringToBytes(m['message'])
            sendTimestamp = m.get('timestamp', None)  # not used yet
            # TODO: if the timestamp is too old, then either just delete the message (if it's not to be queued) or move to inbox

            # Some messages have a single recipient (and maybe relays), others only have a recipientList
            recipient = m.get('recipient', None)
            if recipient:
                sendSuccess = self.RC_MESSAGE_FAILED if recipient in failedRecpts else self.sendMessage(
                    message, recipient)
                if sendSuccess == self.RC_MESSAGE_IGNORED:
                    print(
                        "Dealt with message so I should delete it from the db:",
                        m["_id"])
                    DbI.deleteFromOutbox(m["_id"])
                elif sendSuccess == self.RC_MESSAGE_SENT:
                    print("Sent message so I should delete it from the db:",
                          m["_id"])
                    DbI.deleteFromOutbox(m["_id"])
                    messagesSent += 1
                    testMsg = "Message sent, type was %s and recipient was %s" % (
                        m.get("msgType", "unknown"), recipient)
                    # TODO: Pass these values with the signal as an object, not a string
                    self.messageSentSignal.emit(testMsg)
                elif not m.get('queue', False):
                    print(
                        "I failed to send a message but it shouldn't be queued, deleting it"
                    )
                    DbI.deleteFromOutbox(m["_id"])
                    failedRecpts.add(recipient)
                else:
                    print(
                        "I failed to send but I'll keep the message and try again later"
                    )
                    failedRecpts.add(recipient)
                    # Message couldn't be sent directly, but maybe there are some relays we can use
                    relays = m.get('relays', None)
                    sentSomething = False
                    if relays:
                        # TODO: Check current timestamp and compare with sendTimestamp (types?)
                        failedrelays = set()
                        signedRelayMessage = m.get('relayMessage', None)
                        if not signedRelayMessage:
                            # Take the message bytes and make a RelayingMessage out of them to get the signed output
                            signedRelayMessage = RelayingMessage(
                                message).createOutput(None)
                            # TODO: Store signedRelayMessage back in m
                        # Loop over each relay in the list and try to send to each one
                        for relay in relays:
                            # Should we try to send if this relay is not online?  On the other hand it doesn't hurt.
                            if relay not in failedRecpts and self.sendMessage(
                                    signedRelayMessage,
                                    relay) == self.RC_MESSAGE_SENT:
                                print("Sent message to relay '%s'" % relay)
                                sentSomething = True
                                messagesSent += 1
                            else:
                                # Send failed, so add this relay to the list of failed ones
                                failedrelays.add(relay)
                        if sentSomething:
                            DbI.updateOutboxMessage(
                                m["_id"], {"relays": list(failedrelays)})
            else:
                # There isn't a direct recipient, so let's hope there's a recipient list
                recipientList = m.get('recipientList', None)
                if recipientList:
                    print("I've got a message to relay to: ", recipientList)
                    failedRecipientsForThisMessage = set()
                    # Try to send to each in the list
                    for rRecipient in recipientList:
                        if rRecipient in failedRecpts or self.sendMessage(
                                message, rRecipient) == self.RC_MESSAGE_FAILED:
                            # Couldn't send to this recipient
                            failedRecipientsForThisMessage.add(rRecipient)
                    if failedRecipientsForThisMessage:
                        # Update m with the recipientList = failedRecipientsForThisMessage
                        DbI.updateOutboxMessage(m["_id"], {
                            "recipientList":
                            list(failedRecipientsForThisMessage)
                        })
                        print("I failed to send a relay to:",
                              failedRecipientsForThisMessage)
                    else:
                        print(
                            "I managed to relay everything, now deleting relay message"
                        )
                        DbI.deleteFromOutbox(m["_id"])
            # TODO: Wait inbetween sending to avoid overloading the network

        # TODO: Does the parent even need to know when a send has worked?
        if messagesSent > 0:
            self.parent.postmanKnock()  # only once
        if messagesFound > 0:
            print("For %d found messages, I managed to send %d copies" %
                  (messagesFound, messagesSent))
        # We tried to send a message to these recipients but failed - set them to be offline
        for r in failedRecpts:
            Contacts.instance().goneOffline(r)
        self._flushing = False