Ejemplo n.º 1
0
        private static void Stream_DataRow(object sender, EventStreamRow e)
        {
            if (e.Kind != EventStreamRow.RowKind.Event)
            {
                return;                                         // We don't parse state events
            }
            if (!EmojiEventParser.CanParse(e.EventType))
            {
                return;
            }

            EventJson ev;

            using (var db = new SynapseDbContext(_config.GetConnectionString("synapse")))
            {
                ev = db.EventsJson.FirstOrDefault(e2 => e2.RoomId == e.RoomId && e2.EventId == e.EventId);
                if (ev == null)
                {
                    return;
                }
            }

            var emoji = EmojiEventParser.CountEmoji(e.EventType, ev).Where(c => c.Value > 0);

            foreach (var pair in emoji)
            {
                log.Information("Found {0} instances of {1} emoji in type {2}", pair.Value, pair.Key, e.EventType);
                _redis.GetSubscriber().PublishAsync(EmojiChannel.IncrementCommands, IncrementCommand.Make(pair.Key, pair.Value, e.EventType));
                _redisDb.StringIncrementAsync(pair.Key, pair.Value, CommandFlags.FireAndForget);
            }
        }
        private async Task <int> GetFederationPos(string type)
        {
            using (var db = new SynapseDbContext(connectionString))
            {
                var query = db.FederationStreamPosition.Where(r => r.Type == type);
                var res   = await query.FirstOrDefaultAsync();

                return(res?.StreamId ?? -1);
            }
        }
        private void ClearDeviceMessages(Transaction transaction)
        {
            var deviceMsgs = transaction.edus.Where(m => m.edu_type == "m.direct_to_device").ToList()
                             .ConvertAll(m => m.StreamId);

            var deviceLists = transaction.edus.Where(m => m.edu_type == "m.device_list_update").ToList()
                              .ConvertAll(m => Tuple.Create(m.StreamId, (string)m.content["user_id"]));

            using (var db = new SynapseDbContext(_connString))
            {
                if (deviceMsgs.Count != 0)
                {
                    _destLastDeviceMsgStreamId[transaction.destination] = deviceMsgs.Max();
                    var deviceMsgEntries = db.DeviceFederationOutboxes.Where(m => deviceMsgs.Contains(m.StreamId));

                    if (deviceMsgEntries.Any())
                    {
                        db.DeviceFederationOutboxes.RemoveRange(deviceMsgEntries);
                        db.SaveChanges();
                    }
                    else
                    {
                        log.Warning("No messages to delete in outbox, despite sending messages in this txn");
                    }
                }

                if (deviceLists.Count == 0)
                {
                    return;
                }

                _destLastDeviceListStreamId[transaction.destination] = deviceLists.Max(e => e.Item1);

                var deviceListEntries = db.DeviceListsOutboundPokes
                                        .Where(m =>
                                               deviceLists.FindIndex(e => e.Item1 == m.StreamId &&
                                                                     e.Item2 == m.UserId) >= 0);

                if (deviceListEntries.Any())
                {
                    foreach (var msg in deviceListEntries)
                    {
                        msg.Sent = true;
                    }

                    db.SaveChanges();
                }
                else
                {
                    log.Warning("No device lists to mark as sent, despite sending lists in this txn");
                }
            }
        }
        private void UpdateFederationPos(string type, int id)
        {
            using (var db = new SynapseDbContext(connectionString))
            {
                var res = db.FederationStreamPosition.SingleOrDefault(r => r.Type == type);

                if (res != null)
                {
                    res.StreamId = id;
                    db.SaveChanges();
                }
            }
        }
        private async Task <HashSet <string> > GetHostsInRoom(string roomId)
        {
            var hosts = new HashSet <string>();

            using (var db = new SynapseDbContext(_connString))
            {
                await db.RoomMemberships.Where(m => m.RoomId == roomId)
                .ForEachAsync(m =>
                              hosts.Add(m.UserId.Split(":")[1]));
            }

            hosts.Remove(_serverName);
            return(hosts);
        }
Ejemplo n.º 6
0
        private static void Stream_DataRow(object sender, EventStreamRow e)
        {
            using (var db = new SynapseDbContext(_config.GetConnectionString("synapse")))
            {
                log.Information("Received event {0} ({1}) in {2}", e.EventId, e.EventType, e.RoomId);
                var ev = db.EventsJson.SingleOrDefault(e2 => e2.RoomId == e.RoomId && e2.EventId == e.EventId);

                if (ev != null)
                {
                    log.Information(ev.Json);
                }
                else
                {
                    log.Error("EVENT NOT FOUND");
                }
            }
        }
        private Tuple <List <DeviceFederationOutbox>, List <DeviceContentSet> > GetNewDeviceMessages(string destination)
        {
            var lastMsgId  = _destLastDeviceMsgStreamId.GetValueOrDefault(destination, 0);
            var lastListId = _destLastDeviceListStreamId.GetValueOrDefault(destination, 0);

            using (var db = new SynapseDbContext(_connString))
            {
                var messages = db
                               .DeviceFederationOutboxes
                               .Where(message =>
                                      message.Destination == destination &&
                                      message.StreamId > lastMsgId)
                               .OrderBy(message => message.StreamId).Take(MAX_EDUS_PER_TRANSACTION).ToList();

                var resLists = db.GetNewDevicesForDestination(destination, MAX_EDUS_PER_TRANSACTION);
                return(Tuple.Create(messages, resLists));
            }
        }
        /// <summary>
        ///     Get a set of remote hosts interested in this presence.
        /// </summary>
        private async Task <Dictionary <string[], PresenceState> > GetInterestedRemotes(List <PresenceState> presenceSet)
        {
            var dict = new Dictionary <string[], PresenceState>();

            using (var db = new SynapseDbContext(_connString))
            {
                // Get the list of rooms shared by these users.
                // We are intentionally skipping presence lists here.
                foreach (var presence in presenceSet)
                {
                    var membershipList = await db
                                         .RoomMemberships
                                         .Where(m =>
                                                m.Membership == "join" &&
                                                m.UserId == presence.user_id).ToListAsync();

                    var hosts = new HashSet <string>();

                    // XXX: This is NOT the way to do this, but functions well enough
                    // for a demo.
                    foreach (var roomId in membershipList.ConvertAll(m => m.RoomId))
                    {
                        await db.RoomMemberships
                        .Where(m => m.RoomId == roomId)
                        .ForEachAsync(m =>
                                      hosts.Add(m.UserId
                                                .Split(":")
                                                [1]));
                    }

                    // Never include ourselves
                    hosts.Remove(_serverName);
                    // Now get the hosts for that room.
                    dict.Add(hosts.ToArray(), presence);
                }
            }

            return(dict);
        }
        private async Task ProcessPendingEvents()
        {
            List <EventJsonSet> events;
            var top = _lastEventPoke;
            int last;

            // Get the set of events we need to process.
            using (var db = new SynapseDbContext(_connString))
            {
                last   = (await db.FederationStreamPosition.SingleAsync(m => m.Type == "events")).StreamId;
                events = db.GetAllNewEventsStream(last, top, MAX_PDUS_PER_TRANSACTION);
            }

            if (events.Count == 0)
            {
                log.Debug("No new events to handle");
                return;
            }

            if (events.Count == MAX_PDUS_PER_TRANSACTION)
            {
                log.Warning("More than {Max} events behind", MAX_PDUS_PER_TRANSACTION);
                top = events.Last().StreamOrdering;
            }

            log.Information("Processing from {last} to {top}", last, top);

            // Skip any events that didn't come from us.
            foreach (var item in events.Where(e => IsMineId(e.Sender)).GroupBy(e => e.RoomId))
            {
                var hosts = await GetHostsInRoom(item.Key);

                foreach (var roomEvent in item)
                {
                    // TODO: Support send_on_bahalf_of?

                    IPduEvent pduEv;

                    // NOTE: This is an event format version, not room version.
                    if (roomEvent.Version == 1)
                    {
                        pduEv = new PduEventV1
                        {
                            event_id = roomEvent.EventId
                        }
                    }
                    ;
                    else // Default to latest event format version.
                    {
                        pduEv = new PduEventV2();
                    }

                    pduEv.content          = roomEvent.Content["content"] as JObject;
                    pduEv.origin           = _serverName;
                    pduEv.depth            = (long)roomEvent.Content["depth"];
                    pduEv.auth_events      = roomEvent.Content["auth_events"];
                    pduEv.prev_events      = roomEvent.Content["prev_events"];
                    pduEv.origin_server_ts = (long)roomEvent.Content["origin_server_ts"];

                    if (roomEvent.Content.ContainsKey("redacts"))
                    {
                        pduEv.redacts = (string)roomEvent.Content["redacts"];
                    }

                    pduEv.room_id    = roomEvent.RoomId;
                    pduEv.sender     = roomEvent.Sender;
                    pduEv.prev_state = roomEvent.Content["prev_state"];

                    if (roomEvent.Content.ContainsKey("state_key"))
                    {
                        pduEv.state_key = (string)roomEvent.Content["state_key"];
                    }

                    pduEv.type     = (string)roomEvent.Content["type"];
                    pduEv.unsigned = (JObject)roomEvent.Content["unsigned"];
                    pduEv.hashes   = roomEvent.Content["hashes"];

                    pduEv.signatures = new Dictionary <string, Dictionary <string, string> >();

                    foreach (var sigHosts in (JObject)roomEvent.Content["signatures"])
                    {
                        pduEv.signatures.Add(sigHosts.Key, new Dictionary <string, string>());

                        foreach (var sigs in (JObject)sigHosts.Value)
                        {
                            pduEv.signatures[sigHosts.Key].Add(sigs.Key, sigs.Value.Value <string>());
                        }
                    }

                    //TODO: I guess we need to fetch the destinations for each event in a room, because someone may have got banned in between.
                    foreach (var host in hosts)
                    {
                        var transaction = GetOrCreateTransactionForDest(host);
                        transaction.pdus.Add(pduEv);
                        AttemptTransaction(host);
                    }
                }
            }

            using (var db = new SynapseDbContext(_connString))
            {
                log.Debug("Saving position {top} to DB", top);
                var streamPos = db.FederationStreamPosition.First(e => e.Type == "events");
                streamPos.StreamId = top;
                db.SaveChanges();
            }

            // Still behind?
            if (events.Count == MAX_PDUS_PER_TRANSACTION)
            {
                log.Information("Calling ProcessPendingEvents again because we are still behind");
                await ProcessPendingEvents();
            }
        }