예제 #1
0
        public ChatRoom CreateRoom(string name, RoomKind kind)
        {
            ulong id = Utilities.RandUInt64(Core.RndGen);

            if (kind == RoomKind.Public)
            {
                id = ChatService.GetPublicRoomID(name);
            }

            ChatRoom room = new ChatRoom(kind, id, name);

            room.Active = true;
            room.AddMember(Core.UserID);

            RoomMap.SafeAdd(id, room);

            if (kind == RoomKind.Secret)
            {
                room.Host = Core.UserID;
                room.Verified[Core.UserID] = true;
                SendInviteRequest(room, Core.UserID); // send invite to copies of ourself that exist
            }

            Core.RunInGuiThread(Refresh);

            if (room.PublishRoom)
            {
                SetupPublic(room);
            }

            return(room);
        }
예제 #2
0
        public void SendInviteRequest(ChatRoom room, ulong id)
        {
            if (Core.InvokeRequired)
            {
                Core.RunInCoreAsync(delegate() { SendInviteRequest(room, id); });
                return;
            }

            room.AddMember(id);


            ChatInvite invite = null;

            // if user explicitly chooses to invite users, invalidate previous recorded attempts
            invite        = new ChatInvite();
            invite.RoomID = room.RoomID;
            invite.Title  = room.Title;


            // if private room sign remote users id with our private key
            if (room.Kind == RoomKind.Secret)
            {
                invite.Host = Core.KeyMap[Core.UserID];

                if (!Core.KeyMap.ContainsKey(id))
                {
                    return;
                }

                invite.SignedInvite = Core.User.Settings.KeyPair.SignData(Core.KeyMap[id], new SHA1CryptoServiceProvider());

                room.Verified[id] = true;
            }

            room.Invites[id] = new Tuple <ChatInvite, List <ushort> >(invite, new List <ushort>());

            // try to conncet to all of id's locations
            foreach (ClientInfo loc in Core.Locations.GetClients(id))
            {
                Network.RudpControl.Connect(loc.Data);
            }

            // send invite to already connected locations
            foreach (RudpSession session in Network.RudpControl.GetActiveSessions(id))
            {
                session.SendData(ServiceID, 0, invite);
                room.Invites[id].Param2.Add(session.ClientID);
                ProcessMessage(room, "Invite sent to " + GetNameAndLocation(session));
                SendStatus(room); // so we get added as active to new room invitee creates
                SendWhoResponse(room, session);
            }
        }
예제 #3
0
        public void JoinRoom(ChatRoom room)
        {
            if (Core.InvokeRequired)
            {
                Core.RunInCoreAsync(() => JoinRoom(room));
                return;
            }

            if (IsCommandRoom(room.Kind))
            {
                JoinCommand(room.ProjectID, room.Kind);
                return;
            }

            room.Active = true;
            room.AddMember(Core.UserID);

            // for private rooms, send proof of invite first
            if (room.Kind == RoomKind.Secret)
            {
                SendInviteProof(room);
            }

            SendStatus(room);

            SendWhoRequest(room);

            ConnectRoom(room);

            if (room.PublishRoom)
            {
                SetupPublic(room);
            }

            Core.RunInGuiThread(Refresh);
            Core.RunInGuiThread(room.MembersUpdate);
        }
예제 #4
0
        void Search_FoundRoom(byte[] data, object arg)
        {
            ChatRoom room = arg as ChatRoom;

            if (!room.Active)
            {
                return;
            }

            // add locations to running transfer
            LocationData loc    = LocationData.Decode(data);
            DhtClient    client = new DhtClient(loc.UserID, loc.Source.ClientID);

            Core.Network.LightComm.Update(loc);

            if (!room.Members.SafeContains(client.UserID))
            {
                room.AddMember(client.UserID);
                Core.Locations.Research(client.UserID);
            }

            // connect to new members
            ConnectRoom(room);
        }
예제 #5
0
        public void RefreshCommand(ChatRoom room) // sends status updates to all members of room
        {
            if (!IsCommandRoom(room.Kind))
            {
                Debug.Assert(false);
                return;
            }

            // remember connection status from before
            // nodes we arent connected to do try connect
            // if socket already active send status request

            OpLink localLink = Trust.LocalTrust.GetLink(room.ProjectID);

            if (localLink == null)
            {
                return;
            }

            OpLink uplink = localLink.GetHigher(true);

            // updates room's member list

            if (room.Kind == RoomKind.Command_High)
            {
                room.Members = new ThreadedList <ulong>();

                if (uplink != null)
                {
                    if (localLink.LoopRoot != null)
                    {
                        uplink      = localLink.LoopRoot;
                        room.Host   = uplink.UserID; // use loop id cause 0 is reserved for no root
                        room.IsLoop = true;
                    }
                    else
                    {
                        room.Host   = uplink.UserID;
                        room.IsLoop = false;
                        room.AddMember(room.Host);
                    }

                    foreach (OpLink downlink in uplink.GetLowers(true))
                    {
                        room.AddMember(downlink.UserID);
                    }
                }
            }

            else if (room.Kind == RoomKind.Command_Low)
            {
                room.Members = new ThreadedList <ulong>();

                room.Host = Core.UserID;
                room.AddMember(room.Host);

                foreach (OpLink downlink in localLink.GetLowers(true))
                {
                    room.AddMember(downlink.UserID);
                }
            }

            else if (room.Kind == RoomKind.Live_High)
            {
                // find highest thats online and make that the host,

                // if host changes, clear members

                // higher should send live lowers which members are conneted to it so everyone can sync up
                // location update should trigger a refresh of the live rooms
            }

            else if (room.Kind == RoomKind.Live_Low)
            {
                // just add self, dont remove members
            }


            // update dispaly that members has been refreshed
            Core.RunInGuiThread(room.MembersUpdate);
        }
예제 #6
0
        void ReceiveInvite(ChatInvite invite, RudpSession session)
        {
            // if in global im, only allow if on buddies list
            if (Core.User.Settings.GlobalIM)
            {
                if (!Core.Buddies.BuddyList.SafeContainsKey(session.UserID))
                {
                    return;
                }
            }

            if (Core.Buddies.IgnoreList.SafeContainsKey(session.UserID))
            {
                return;
            }

            bool showInvite = false;

            ChatRoom room;

            if (!RoomMap.TryGetValue(invite.RoomID, out room))
            {
                RoomKind kind = invite.SignedInvite != null ? RoomKind.Secret : RoomKind.Private;
                room        = new ChatRoom(kind, invite.RoomID, invite.Title);
                room.RoomID = invite.RoomID;
                room.Kind   = kind;
                room.AddMember(session.UserID);

                if (invite.Host != null)
                {
                    room.Host = Utilities.KeytoID(invite.Host);
                    Core.IndexKey(room.Host, ref invite.Host);
                }

                RoomMap.SafeAdd(room.RoomID, room);

                showInvite = true;
            }

            // private room
            if (room.Kind == RoomKind.Secret)
            {
                if (!Core.KeyMap.ContainsKey(room.Host))
                {
                    return;
                }

                byte[] hostKey = Core.KeyMap[room.Host];


                // if this is host sending us our verification
                if (session.UserID == room.Host)
                {
                    // check that host signed our public key with his private
                    if (!Utilities.CheckSignedData(hostKey, Core.KeyMap[Core.UserID], invite.SignedInvite))
                    {
                        return;
                    }

                    if (!room.Invites.ContainsKey(Core.UserID)) // would fail if a node's dupe on network sends invite back to itself
                    {
                        room.Invites.Add(Core.UserID, new Tuple <ChatInvite, List <ushort> >(invite, new List <ushort>()));
                    }
                }

                // else this is node in room sending us proof of being invited
                else
                {
                    if (!Core.KeyMap.ContainsKey(session.UserID))
                    {
                        return; // key should def be in map, it was added when session was made to sender
                    }
                    // check that host signed remote's key with host's private
                    if (!Utilities.CheckSignedData(hostKey, Core.KeyMap[session.UserID], invite.SignedInvite))
                    {
                        return;
                    }
                }

                // if not verified yet, add them and send back our own verification
                if (!room.Verified.ContainsKey(session.UserID))
                {
                    room.Verified[session.UserID] = true;

                    if (room.Active)
                    {
                        SendInviteProof(room, session); // someone sends us their proof, we send it back in return
                        SendStatus(session);            // send status here because now it will include private rooms
                    }
                }
            }

            if (Trust != null && !Trust.TrustMap.SafeContainsKey(session.UserID))
            {
                Trust.Research(session.UserID, 0, false);
            }

            if (showInvite)
            {
                Core.RunInGuiThread(NewInvite, session.UserID, room);
            }
        }