예제 #1
0
    def publish_user(self, sender, userid, headers = None, msg = None, need_ack = MSG_ACK_NONE):
        '''Publish a message to a user, either generic or specific.'''

        # TODO many other checks
        if len(userid) != utils.USERID_LENGTH and len(userid) != utils.USERID_LENGTH_RESOURCE:
            log.warn("invalid userid format: %s" % userid)
            # TODO should we throw an exception here?
            return None

        if self.config['broker']['reject_unknown_recipients']:
            # check if user exists
            # TODO this check should be done over the whole network (?)
            if not self.storage.get_user_stat(userid) and not self.user_online(userid):
                log.warn("user %s not found" % userid)
                return c2s.MessagePostResponse.MessageSent.STATUS_USER_NOTFOUND

        # prepare message dict
        msg_id = self.message_id()
        outmsg = {
            'messageid' : msg_id,
            'sender' : sender,
            'recipient' : userid,
            'timestamp' : datetime.utcnow(),
            'need_ack' : need_ack,
            'headers' : headers,
            'payload' : msg
        }

        # process message on the next iteration
        # FIXME is this safe? Check for race conditions
        reactor.callLater(0, self._usermsg_worker, outmsg)

        return msg_id
예제 #2
0
    def _format_msg(self, msg):
        msg['content'] = base64.b64encode(msg['payload'])
        msg['need_ack'] = (msg['need_ack'] != broker.MSG_ACK_NONE)
        msg['mime'] = msg['headers']['mime']
        msg['flags'] = msg['headers']['flags']
        msg['timestamp'] = long(time.mktime(msg['timestamp'].timetuple()))

        if 'filename' in msg['headers']:
            msg['url'] = self.broker.config['fileserver']['download_url'] % msg['headers']['filename']
            try:
                (filename, _mime, _md5sum) = self.broker.storage.get_extra(msg['headers']['filename'], self.userid)
                a.length = os.path.getsize(filename)
            except:
                log.warn("attachment not found, unable to send length out")
            del msg['filename']

        # clean private data
        del msg['payload']
        del msg['need_ack']
        del msg['headers']
        return msg
예제 #3
0
    def publish_user(self,
                     sender,
                     userid,
                     headers=None,
                     msg=None,
                     need_ack=MSG_ACK_NONE):
        '''Publish a message to a user, either generic or specific.'''

        # TODO many other checks
        if len(userid) != utils.USERID_LENGTH and len(
                userid) != utils.USERID_LENGTH_RESOURCE:
            log.warn("invalid userid format: %s" % userid)
            # TODO should we throw an exception here?
            return None

        if self.config['broker']['reject_unknown_recipients']:
            # check if user exists
            # TODO this check should be done over the whole network (?)
            if not self.storage.get_user_stat(userid) and not self.user_online(
                    userid):
                log.warn("user %s not found" % userid)
                return c2s.MessagePostResponse.MessageSent.STATUS_USER_NOTFOUND

        # prepare message dict
        msg_id = self.message_id()
        outmsg = {
            'messageid': msg_id,
            'sender': sender,
            'recipient': userid,
            'timestamp': datetime.utcnow(),
            'need_ack': need_ack,
            'headers': headers,
            'payload': msg
        }

        # process message on the next iteration
        # FIXME is this safe? Check for race conditions
        reactor.callLater(0, self._usermsg_worker, outmsg)

        return msg_id
예제 #4
0
 def _incoming_box(self, data, a = None):
     # TODO check for missing keys
     # TODO avoid using c2s directly; instead create a method in C2SServerProtocol
     if not a:
         a = c2s.NewMessage()
     a.message_id = data['messageid']
     if 'originalid' in data:
         a.original_id = data['originalid']
     a.timestamp = data['timestamp'].strftime('%Y-%m-%d %H:%M:%S')
     a.sender = data['sender']
     a.mime = data['headers']['mime']
     a.flags.extend(data['headers']['flags'])
     a.content = data['payload']
     a.need_ack = (data['need_ack'] != broker.MSG_ACK_NONE)
     if 'filename' in data['headers']:
         a.url = self.config['fileserver']['download_url'] % data['headers']['filename']
         try:
             (filename, _mime, _md5sum) = self.broker.storage.get_extra(data['headers']['filename'], self.userid)
             a.length = os.path.getsize(filename)
         except:
             log.warn("attachment not found, unable to send length out")
     return a
예제 #5
0
    def _format_msg(self, msg):
        msg['content'] = base64.b64encode(msg['payload'])
        msg['need_ack'] = (msg['need_ack'] != broker.MSG_ACK_NONE)
        msg['mime'] = msg['headers']['mime']
        msg['flags'] = msg['headers']['flags']
        msg['timestamp'] = long(time.mktime(msg['timestamp'].timetuple()))

        if 'filename' in msg['headers']:
            msg['url'] = self.broker.config['fileserver'][
                'download_url'] % msg['headers']['filename']
            try:
                (filename, _mime, _md5sum) = self.broker.storage.get_extra(
                    msg['headers']['filename'], self.userid)
                a.length = os.path.getsize(filename)
            except:
                log.warn("attachment not found, unable to send length out")
            del msg['filename']

        # clean private data
        del msg['payload']
        del msg['need_ack']
        del msg['headers']
        return msg
예제 #6
0
 def _incoming_box(self, data, a=None):
     # TODO check for missing keys
     # TODO avoid using c2s directly; instead create a method in C2SServerProtocol
     if not a:
         a = c2s.NewMessage()
     a.message_id = data['messageid']
     if 'originalid' in data:
         a.original_id = data['originalid']
     a.timestamp = data['timestamp'].strftime('%Y-%m-%d %H:%M:%S')
     a.sender = data['sender']
     a.mime = data['headers']['mime']
     a.flags.extend(data['headers']['flags'])
     a.content = data['payload']
     a.need_ack = (data['need_ack'] != broker.MSG_ACK_NONE)
     if 'filename' in data['headers']:
         a.url = self.config['fileserver']['download_url'] % data[
             'headers']['filename']
         try:
             (filename, _mime, _md5sum) = self.broker.storage.get_extra(
                 data['headers']['filename'], self.userid)
             a.length = os.path.getsize(filename)
         except:
             log.warn("attachment not found, unable to send length out")
     return a
예제 #7
0
    def _usermsg_worker(self, msg):
        userid = msg['recipient']
        need_ack = msg['need_ack']
        #log.debug("queue data for user %s (need_ack=%s)" % (userid, need_ack))

        # generic user, post to every consumer
        if len(userid) == utils.USERID_LENGTH:
            try:
                for resource, q in self._consumers[userid].iteritems():
                    outmsg = dict(msg)
                    # branch the message :)
                    outmsg['messageid'] = self.message_id()
                    outmsg['originalid'] = msg['messageid']
                    outmsg['recipient'] += resource

                    # store to disk (if need_ack)
                    if need_ack:
                        try:
                            #log.debug("storing message %s to disk" % outmsg['messageid'])
                            self.storage.deliver(outmsg['recipient'], outmsg)
                        except:
                            # TODO handle errors
                            import traceback
                            traceback.print_exc()

                    # send to client listener
                    q.put(outmsg)

            except KeyError:
                #log.debug("warning: no consumer to deliver message to %s" % userid)
                # store to temporary spool
                self.storage.store(userid, msg)
                # send push notifications to all matching users
                try:
                    # do not push for receipts
                    if self.push_manager and msg['headers']['mime'] != MIME_RECEIPT:
                        self.push_manager.notify_all(userid)
                except:
                    # TODO notify errors
                    import traceback
                    traceback.print_exc()


        elif len(userid) == utils.USERID_LENGTH_RESOURCE:
            uhash, resource = utils.split_userid(userid)

            # store to disk (if need_ack)
            if need_ack:
                try:
                    #log.debug("storing message %s to disk" % msg['messageid'])
                    if 'storage' not in msg:
                        self.storage.store(userid, msg)
                except:
                    # TODO handle errors
                    import traceback
                    traceback.print_exc()

            try:
                # send to client consumer
                #log.debug("sending message %s to consumer" % msg['messageid'])
                self._consumers[uhash][resource].put(msg)
            except:
                #log.debug("warning: no consumer to deliver message to %s/%s!" % (uhash, resource))
                # send push notification
                try:
                    # do not push for receipts
                    if self.push_manager and msg['headers']['mime'] != MIME_RECEIPT:
                        self.push_manager.notify(userid)
                except:
                    # TODO notify errors
                    import traceback
                    traceback.print_exc()

        else:
            log.warn("warning: unknown userid format %s" % userid)
예제 #8
0
    def _usermbox_worker(self, mbox):
        '''
        Processes a bunch of messages to be sent massively to recipients.
        This takes every message and put it in different lists to be delivered
        to their respective channels - if available.
        TODO this method is used only to requeue messages on login, so we can
        take something for granted, e.g. userid will be the same for every
        message, push notifications are not needed, ...
        '''
        outbox = {}

        for msg in mbox:
            userid = msg['recipient']
            need_ack = msg['need_ack']
            #log.debug("queue data for user %s (need_ack=%s)" % (userid, need_ack))

            # generic user, post to every consumer
            if len(userid) == utils.USERID_LENGTH:
                try:
                    for resource, q in self._consumers[userid].iteritems():
                        outmsg = dict(msg)
                        # branch the message :)
                        outmsg['messageid'] = self.message_id()
                        outmsg['originalid'] = msg['messageid']
                        outmsg['recipient'] += resource

                        # store to disk (if need_ack)
                        if need_ack:
                            try:
                                #log.debug("storing message %s to disk" % outmsg['messageid'])
                                self.storage.deliver(outmsg['recipient'], outmsg)
                            except:
                                # TODO handle errors
                                import traceback
                                traceback.print_exc()

                        # keep in outbox
                        if outmsg['recipient'] not in outbox:
                            outbox[outmsg['recipient']] = []
                        outbox[outmsg['recipient']].append(outmsg)

                except KeyError:
                    #log.debug("warning: no consumer to deliver message to %s" % userid)
                    # store to temporary spool
                    self.storage.store(userid, msg)
                    # send push notifications to all matching users
                    try:
                        # do not push for receipts
                        if self.push_manager and msg['headers']['mime'] != MIME_RECEIPT:
                            self.push_manager.notify_all(userid)
                    except:
                        # TODO notify errors
                        import traceback
                        traceback.print_exc()

            elif len(userid) == utils.USERID_LENGTH_RESOURCE:
                uhash, resource = utils.split_userid(userid)

                # store to disk (if need_ack)
                if need_ack:
                    try:
                        #log.debug("storing message %s to disk" % msg['messageid'])
                        if 'storage' not in msg:
                            self.storage.store(userid, msg)
                    except:
                        # TODO handle errors
                        import traceback
                        traceback.print_exc()

                # keep in outbox
                if userid not in outbox:
                    outbox[userid] = []
                outbox[userid].append(msg)

            else:
                log.warn("warning: unknown userid format %s" % userid)

        for userid, msglist in outbox.iteritems():
            uhash, resource = utils.split_userid(userid)

            try:
                # send to client consumer
                #log.debug("sending message %s to consumer" % msg['messageid'])
                self._consumers[uhash][resource].put(msglist)
            except:
                #log.debug("warning: no consumer to deliver message to %s/%s!" % (uhash, resource))
                # send push notification
                try:
                    # do not push for receipts
                    receipt_found = False
                    for msg in msglist:
                        if msg['headers']['mime'] == MIME_RECEIPT:
                            receipt_found = True
                            break
                    if self.push_manager and not receipt_found:
                        self.push_manager.notify(userid)
                except:
                    # TODO notify errors
                    import traceback
                    traceback.print_exc()
예제 #9
0
    def _usermsg_worker(self, msg):
        userid = msg['recipient']
        need_ack = msg['need_ack']
        #log.debug("queue data for user %s (need_ack=%s)" % (userid, need_ack))

        # generic user, post to every consumer
        if len(userid) == utils.USERID_LENGTH:
            try:
                for resource, q in self._consumers[userid].iteritems():
                    outmsg = dict(msg)
                    # branch the message :)
                    outmsg['messageid'] = self.message_id()
                    outmsg['originalid'] = msg['messageid']
                    outmsg['recipient'] += resource

                    # store to disk (if need_ack)
                    if need_ack:
                        try:
                            #log.debug("storing message %s to disk" % outmsg['messageid'])
                            self.storage.deliver(outmsg['recipient'], outmsg)
                        except:
                            # TODO handle errors
                            import traceback
                            traceback.print_exc()

                    # send to client listener
                    q.put(outmsg)

            except KeyError:
                #log.debug("warning: no consumer to deliver message to %s" % userid)
                # store to temporary spool
                self.storage.store(userid, msg)
                # send push notifications to all matching users
                try:
                    # do not push for receipts
                    if self.push_manager and msg['headers'][
                            'mime'] != MIME_RECEIPT:
                        self.push_manager.notify_all(userid)
                except:
                    # TODO notify errors
                    import traceback
                    traceback.print_exc()

        elif len(userid) == utils.USERID_LENGTH_RESOURCE:
            uhash, resource = utils.split_userid(userid)

            # store to disk (if need_ack)
            if need_ack:
                try:
                    #log.debug("storing message %s to disk" % msg['messageid'])
                    if 'storage' not in msg:
                        self.storage.store(userid, msg)
                except:
                    # TODO handle errors
                    import traceback
                    traceback.print_exc()

            try:
                # send to client consumer
                #log.debug("sending message %s to consumer" % msg['messageid'])
                self._consumers[uhash][resource].put(msg)
            except:
                #log.debug("warning: no consumer to deliver message to %s/%s!" % (uhash, resource))
                # send push notification
                try:
                    # do not push for receipts
                    if self.push_manager and msg['headers'][
                            'mime'] != MIME_RECEIPT:
                        self.push_manager.notify(userid)
                except:
                    # TODO notify errors
                    import traceback
                    traceback.print_exc()

        else:
            log.warn("warning: unknown userid format %s" % userid)
예제 #10
0
    def _usermbox_worker(self, mbox):
        '''
        Processes a bunch of messages to be sent massively to recipients.
        This takes every message and put it in different lists to be delivered
        to their respective channels - if available.
        TODO this method is used only to requeue messages on login, so we can
        take something for granted, e.g. userid will be the same for every
        message, push notifications are not needed, ...
        '''
        outbox = {}

        for msg in mbox:
            userid = msg['recipient']
            need_ack = msg['need_ack']
            #log.debug("queue data for user %s (need_ack=%s)" % (userid, need_ack))

            # generic user, post to every consumer
            if len(userid) == utils.USERID_LENGTH:
                try:
                    for resource, q in self._consumers[userid].iteritems():
                        outmsg = dict(msg)
                        # branch the message :)
                        outmsg['messageid'] = self.message_id()
                        outmsg['originalid'] = msg['messageid']
                        outmsg['recipient'] += resource

                        # store to disk (if need_ack)
                        if need_ack:
                            try:
                                #log.debug("storing message %s to disk" % outmsg['messageid'])
                                self.storage.deliver(outmsg['recipient'],
                                                     outmsg)
                            except:
                                # TODO handle errors
                                import traceback
                                traceback.print_exc()

                        # keep in outbox
                        if outmsg['recipient'] not in outbox:
                            outbox[outmsg['recipient']] = []
                        outbox[outmsg['recipient']].append(outmsg)

                except KeyError:
                    #log.debug("warning: no consumer to deliver message to %s" % userid)
                    # store to temporary spool
                    self.storage.store(userid, msg)
                    # send push notifications to all matching users
                    try:
                        # do not push for receipts
                        if self.push_manager and msg['headers'][
                                'mime'] != MIME_RECEIPT:
                            self.push_manager.notify_all(userid)
                    except:
                        # TODO notify errors
                        import traceback
                        traceback.print_exc()

            elif len(userid) == utils.USERID_LENGTH_RESOURCE:
                uhash, resource = utils.split_userid(userid)

                # store to disk (if need_ack)
                if need_ack:
                    try:
                        #log.debug("storing message %s to disk" % msg['messageid'])
                        if 'storage' not in msg:
                            self.storage.store(userid, msg)
                    except:
                        # TODO handle errors
                        import traceback
                        traceback.print_exc()

                # keep in outbox
                if userid not in outbox:
                    outbox[userid] = []
                outbox[userid].append(msg)

            else:
                log.warn("warning: unknown userid format %s" % userid)

        for userid, msglist in outbox.iteritems():
            uhash, resource = utils.split_userid(userid)

            try:
                # send to client consumer
                #log.debug("sending message %s to consumer" % msg['messageid'])
                self._consumers[uhash][resource].put(msglist)
            except:
                #log.debug("warning: no consumer to deliver message to %s/%s!" % (uhash, resource))
                # send push notification
                try:
                    # do not push for receipts
                    receipt_found = False
                    for msg in msglist:
                        if msg['headers']['mime'] == MIME_RECEIPT:
                            receipt_found = True
                            break
                    if self.push_manager and not receipt_found:
                        self.push_manager.notify(userid)
                except:
                    # TODO notify errors
                    import traceback
                    traceback.print_exc()