Exemplo n.º 1
0
        /// <summary>
        /// Creates a new multiparty (Group chat)
        /// </summary>
        /// <param name="inviteQueue">Contacts to be invited (don't add yourself)</param>
        /// <param name="onCreated">The handler to be executed when multiparty created (must be provided)</param>
        /// <exception cref="ArgumentNullException">inviteQueue or event handler is null</exception>
        /// <exception cref="InvalidOperationException">At least 2 contacts is required except you and contacts must support multiparty</exception>
        /// <returns>Transaction ID</returns>
        public int CreateMultiparty(List<Contact> inviteQueue, EventHandler<MultipartyCreatedEventArgs> onCreated)
        {
            if (inviteQueue == null || inviteQueue.Count == 0)
                throw new ArgumentNullException("inviteQueue");

            if (onCreated == null)
                throw new ArgumentNullException("onCreated");

            List<string> newQueue = new List<string>();

            foreach (Contact c in inviteQueue)
            {
                if (c != null &&
                    !c.IsSibling(Owner) &&
                    !newQueue.Contains(c.SiblingString) &&
                    c.SupportsMultiparty)
                {
                    newQueue.Add(c.SiblingString);
                }
            }

            if (newQueue.Count < 2)
                throw new InvalidOperationException("At least 2 contacts is required except you and contacts must support multiparty.");

            NSMessageProcessor nsmp = (NSMessageProcessor)MessageProcessor;
            int transId = nsmp.IncreaseTransactionID();

            lock (multiParties)
                multiParties[transId] = new MultipartyObject(transId, newQueue, null, onCreated);

            string to = ((int)IMAddressInfoType.TemporaryGroup).ToString() + ":" + Guid.Empty.ToString("D").ToLowerInvariant() + "@" + Contact.DefaultHostDomain;
            string from = ((int)Owner.ClientType).ToString() + ":" + Owner.Account;
            MultiMimeMessage mmMessage = new MultiMimeMessage(to, from);
            mmMessage.RoutingHeaders[MIMERoutingHeaders.From][MIMERoutingHeaders.EPID] = MachineGuid.ToString("B").ToLowerInvariant();

            mmMessage.ContentKey = MIMEContentHeaders.Publication;
            mmMessage.ContentHeaders[MIMEContentHeaders.URI] = "/circle";
            mmMessage.ContentHeaders[MIMEContentHeaders.ContentType] = "application/multiparty+xml";

            mmMessage.InnerBody = new byte[0];

            NSMessage putPayload = new NSMessage("PUT");
            putPayload.InnerMessage = mmMessage;
            nsmp.SendMessage(putPayload, transId);

            return transId;
        }
Exemplo n.º 2
0
        private void OnNFYPUTReceived(MultiMimeMessage multiMimeMessage, RoutingInfo routingInfo)
        {
            switch (multiMimeMessage.ContentHeaders[MIMEContentHeaders.ContentType].Value)
            {
                #region user xml
                case "application/user+xml":
                    {

                        if (multiMimeMessage.ContentHeaders[MIMEHeaderStrings.NotifType].Value == "Sync")
                        {
                            if (routingInfo.SenderGateway != null && routingInfo.SenderGateway.ClientType == IMAddressInfoType.Circle)
                            {
                                JoinMultiparty(routingInfo.SenderGateway);
                            }

                            //Sync the contact in contact list with the contact in gateway.
                            // TODO: Set the NSMessagehandler.ContactList contact to the gateway
                            // TODO: triger the ContactOnline event for the gateway contact.

                            //Just wait for my fix.
                        }

                        if (multiMimeMessage.InnerBody == null || multiMimeMessage.InnerBody.Length == 0)
                            return;  //No xml content.

                        if (multiMimeMessage.ContentHeaders[MIMEHeaderStrings.NotifType].Value == "Full")
                        {
                            //This is an initial NFY
                        }

                        XmlDocument xmlDoc = new XmlDocument();
                        xmlDoc.LoadXml(Encoding.UTF8.GetString(multiMimeMessage.InnerBody));
                        XmlNodeList services = xmlDoc.SelectNodes("//user/s");
                        XmlNodeList serviceEndPoints = xmlDoc.SelectNodes("//user/sep");

                        if (services.Count > 0)
                        {
                            foreach (XmlNode service in services)
                            {
                                ServiceShortNames serviceEnum = (ServiceShortNames)Enum.Parse(typeof(ServiceShortNames), service.Attributes["n"].Value);
                                switch (serviceEnum)
                                {
                                    case ServiceShortNames.IM:
                                        {
                                            foreach (XmlNode node in service.ChildNodes)
                                            {
                                                switch (node.Name)
                                                {
                                                    case "Status":

                                                        if (routingInfo.FromOwner && IsSignedIn == false)
                                                        {
                                                            // We have already signed in another place, but not here...
                                                            // Don't set status... This place will set the status later.
                                                            return;
                                                        }

                                                        PresenceStatus oldStatus = routingInfo.Sender.Status;
                                                        PresenceStatus newStatus = ParseStatus(node.InnerText);
                                                        routingInfo.Sender.SetStatus(newStatus);

                                                        OnContactStatusChanged(new ContactStatusChangedEventArgs(routingInfo.Sender, routingInfo.SenderGateway, oldStatus, newStatus));
                                                        OnContactOnline(new ContactStatusChangedEventArgs(routingInfo.Sender, routingInfo.SenderGateway, oldStatus, newStatus));

                                                        break;

                                                    case "CurrentMedia":
                                                        //MSNP21TODO: UBX implementation

                                                        break;
                                                }
                                            }
                                            break;
                                        }

                                    case ServiceShortNames.PE:
                                        {
                                            // Create a new reference to fire PersonalMessageChanged event.
                                            PersonalMessage personalMessage = new PersonalMessage(service.ChildNodes);

                                            if (!String.IsNullOrEmpty(personalMessage.Payload) &&
                                                routingInfo.Sender.PersonalMessage != personalMessage)
                                            {
                                                // FriendlyName
                                                if (!String.IsNullOrEmpty(personalMessage.FriendlyName))
                                                {
                                                    //Only Windows Live Messenger Contact has friendly name.
                                                    routingInfo.Sender.SetName(personalMessage.FriendlyName);
                                                }

                                                // UserTileLocation
                                                if (!String.IsNullOrEmpty(personalMessage.UserTileLocation) && routingInfo.Sender.UserTileLocation != personalMessage.UserTileLocation)
                                                {
                                                    routingInfo.Sender.UserTileLocation = personalMessage.UserTileLocation;
                                                    routingInfo.Sender.FireDisplayImageContextChangedEvent(personalMessage.UserTileLocation);
                                                }

                                                // Scene
                                                if (!String.IsNullOrEmpty(personalMessage.Scene))
                                                {
                                                    if (routingInfo.Sender.SceneContext != personalMessage.Scene)
                                                    {
                                                        routingInfo.Sender.SceneContext = personalMessage.Scene;
                                                        routingInfo.Sender.FireSceneImageContextChangedEvent(personalMessage.Scene);
                                                    }
                                                }

                                                // ColorScheme
                                                if (personalMessage.ColorScheme != Color.Empty)
                                                {
                                                    if (routingInfo.Sender.ColorScheme != personalMessage.ColorScheme)
                                                    {
                                                        routingInfo.Sender.ColorScheme = personalMessage.ColorScheme;
                                                        routingInfo.Sender.OnColorSchemeChanged();
                                                    }
                                                }

                                                // This must be final...
                                                routingInfo.Sender.PersonalMessage = personalMessage;

                                            }
                                            break;
                                        }

                                    case ServiceShortNames.PF:
                                        {
                                            // Profile Annotation, it is AB.Me.annotations/Live.Profile.Expression.LastChanged
                                            // <user><s n="PF" ts="2011-04-16T06:00:58Z"></s></user>
                                            if (routingInfo.FromOwner)
                                            {
                                                DateTime ts = WebServiceDateTimeConverter.ConvertToDateTime(service.Attributes["ts"].Value);
                                            }
                                            break;
                                        }
                                }
                            }
                        }

                        if (serviceEndPoints.Count > 0)
                        {
                            foreach (XmlNode serviceEndPoint in serviceEndPoints)
                            {
                                ServiceShortNames serviceEnum = (ServiceShortNames)Enum.Parse(typeof(ServiceShortNames), serviceEndPoint.Attributes["n"].Value);
                                Guid epid = serviceEndPoint.Attributes["epid"] == null ? Guid.Empty : new Guid(serviceEndPoint.Attributes["epid"].Value);

                                if (!routingInfo.Sender.EndPointData.ContainsKey(epid))
                                {
                                    lock (routingInfo.Sender.SyncObject)
                                        routingInfo.Sender.EndPointData.Add(epid, routingInfo.FromOwner ? new PrivateEndPointData(routingInfo.Sender.Account, epid) : new EndPointData(routingInfo.Sender.Account, epid));
                                }

                                switch (serviceEnum)
                                {
                                    case ServiceShortNames.IM:
                                        {
                                            foreach (XmlNode node in serviceEndPoint.ChildNodes)
                                            {
                                                switch (node.Name)
                                                {
                                                    case "Capabilities":

                                                        ClientCapabilities cap = ClientCapabilities.None;
                                                        ClientCapabilitiesEx capEx = ClientCapabilitiesEx.None;

                                                        string[] caps = node.InnerText.Split(':');
                                                        if (caps.Length > 1)
                                                        {
                                                            capEx = (ClientCapabilitiesEx)long.Parse(caps[1]);
                                                        }
                                                        cap = (ClientCapabilities)long.Parse(caps[0]);

                                                        routingInfo.Sender.EndPointData[epid].IMCapabilities = cap;
                                                        routingInfo.Sender.EndPointData[epid].IMCapabilitiesEx = capEx;

                                                        break;
                                                }
                                            }
                                            break;
                                        }

                                    case ServiceShortNames.PE:
                                        {
                                            foreach (XmlNode node in serviceEndPoint.ChildNodes)
                                            {
                                                switch (node.Name)
                                                {
                                                    case "Capabilities":

                                                        ClientCapabilities cap = ClientCapabilities.None;
                                                        ClientCapabilitiesEx capEx = ClientCapabilitiesEx.None;

                                                        string[] caps = node.InnerText.Split(':');
                                                        if (caps.Length > 1)
                                                        {
                                                            capEx = (ClientCapabilitiesEx)long.Parse(caps[1]);
                                                        }
                                                        cap = (ClientCapabilities)long.Parse(caps[0]);

                                                        routingInfo.Sender.EndPointData[epid].PECapabilities = cap;
                                                        routingInfo.Sender.EndPointData[epid].PECapabilitiesEx = capEx;

                                                        break;
                                                }
                                            }

                                            routingInfo.Sender.SetChangedPlace(new PlaceChangedEventArgs(routingInfo.Sender.EndPointData[epid], PlaceChangedReason.SignedIn));

                                            break;
                                        }

                                    case ServiceShortNames.PD:
                                        {
                                            PrivateEndPointData privateEndPoint = routingInfo.Sender.EndPointData[epid] as PrivateEndPointData;

                                            foreach (XmlNode node in serviceEndPoint.ChildNodes)
                                            {
                                                switch (node.Name)
                                                {
                                                    case "ClientType":
                                                        privateEndPoint.ClientType = node.InnerText;
                                                        break;

                                                    case "EpName":
                                                        privateEndPoint.Name = node.InnerText;
                                                        break;

                                                    case "Idle":
                                                        privateEndPoint.Idle = bool.Parse(node.InnerText);
                                                        break;

                                                    case "State":
                                                        privateEndPoint.State = ParseStatus(node.InnerText);
                                                        break;
                                                }
                                            }

                                            Owner.SetChangedPlace(new PlaceChangedEventArgs(privateEndPoint, PlaceChangedReason.SignedIn));

                                            break;
                                        }
                                }
                            }
                        }

                    }
                    break;
                #endregion

                #region circles xml
                case "application/circles+xml":
                    {
                        if (routingInfo.SenderType == IMAddressInfoType.Circle)
                        {
                            Contact circle = ContactList.GetCircle(routingInfo.SenderAccount);

                            if (circle == null)
                            {
                                Trace.WriteLineIf(Settings.TraceSwitch.TraceError,
                                    "[OnNFYReceived] Cannot complete the operation since circle not found: " + multiMimeMessage.From.ToString());

                                return;
                            }

                            if (multiMimeMessage.InnerBody == null || multiMimeMessage.InnerBody.Length == 0 ||
                                    "<circle></circle>" == Encoding.UTF8.GetString(multiMimeMessage.InnerBody))
                            {
                                // No xml content and full notify... Circle goes online...
                                if (multiMimeMessage.ContentHeaders[MIMEHeaderStrings.NotifType].Value == "Full")
                                {
                                    PresenceStatus oldStatus = circle.Status;
                                    PresenceStatus newStatus = PresenceStatus.Online;
                                    circle.SetStatus(newStatus);

                                    // The contact changed status
                                    OnContactStatusChanged(new ContactStatusChangedEventArgs(circle, oldStatus, newStatus));

                                    // The contact goes online
                                    OnContactOnline(new ContactStatusChangedEventArgs(circle, oldStatus, newStatus));
                                }
                                return;
                            }

                            XmlDocument xmlDoc = new XmlDocument();
                            xmlDoc.LoadXml(Encoding.UTF8.GetString(multiMimeMessage.InnerBody));
                            XmlNodeList ids = xmlDoc.SelectNodes("//circle/roster/user/id");

                            if (ids.Count == 0)
                            {
                                return;  //I hate indent.
                            }

                            foreach (XmlNode node in ids)
                            {
                                IMAddressInfoType accountAddressType;
                                string account;
                                IMAddressInfoType viaAccountAddressType;
                                string viaAccount;
                                string fullAccount = node.InnerText;

                                if (false == Contact.ParseFullAccount(fullAccount,
                                    out accountAddressType, out account,
                                    out viaAccountAddressType, out viaAccount))
                                {
                                    continue;
                                }

                                if (account == Owner.Account)
                                    continue;

                                if (circle.ContactList.HasContact(account, accountAddressType))
                                {
                                    Contact contact = circle.ContactList.GetContact(account, accountAddressType);
                                    OnJoinedGroupChat(new GroupChatParticipationEventArgs(contact, circle));
                                }
                            }
                        }
                        else if (routingInfo.SenderType == IMAddressInfoType.TemporaryGroup)
                        {
                            MultipartyObject mpo = GetMultipartyObject(routingInfo.SenderAccount);
                            Contact group = null;

                            if (mpo == null)
                            {
                                // Created remotely.
                                NSMessageProcessor nsmp = (NSMessageProcessor)MessageProcessor;
                                int transId = nsmp.IncreaseTransactionID();

                                group = new Contact(routingInfo.SenderAccount, IMAddressInfoType.TemporaryGroup, this);
                                group.ContactList = new ContactList(new Guid(routingInfo.SenderAccount.Split('@')[0]), null, group, this);

                                mpo = new MultipartyObject(transId, new List<string>(), group, null);

                                lock (multiParties)
                                    multiParties[transId] = mpo;

                                OnMultipartyCreatedRemotely(new MultipartyCreatedEventArgs(group));

                                group.SetStatus(PresenceStatus.Online);
                            }
                            else
                            {
                                group = mpo.MultiParty;
                            }

                            if (multiMimeMessage.InnerBody == null || multiMimeMessage.InnerBody.Length == 0)
                            {
                                // No xml content and full notify... Circle goes online...
                                if (multiMimeMessage.ContentHeaders[MIMEHeaderStrings.NotifType].Value == "Full")
                                {
                                    PresenceStatus oldStatus = group.Status;
                                    PresenceStatus newStatus = PresenceStatus.Online;
                                    group.SetStatus(newStatus);

                                    // The contact changed status
                                    OnContactStatusChanged(new ContactStatusChangedEventArgs(group, oldStatus, newStatus));

                                    // The contact goes online
                                    OnContactOnline(new ContactStatusChangedEventArgs(group, oldStatus, newStatus));

                                }
                                return;
                            }

                            // Join multiparty if state is Pending
                            XmlDocument xmlDoc = new XmlDocument();
                            xmlDoc.LoadXml(Encoding.UTF8.GetString(multiMimeMessage.InnerBody));
                            XmlNodeList rosters = xmlDoc.SelectNodes("//circle/roster/user");
                            foreach (XmlNode roster in rosters)
                            {
                                string state = (roster["state"] == null) ? string.Empty : roster["state"].InnerText;
                                string[] fullAccount = roster["id"].InnerText.Split(':');
                                IMAddressInfoType addressType = (IMAddressInfoType)int.Parse(fullAccount[0]);
                                string memberAccount = fullAccount[1].ToLowerInvariant();

                                // Me contact
                                if ("pending" == state.ToLowerInvariant() &&
                                    addressType == Owner.ClientType &&
                                    memberAccount == Owner.Account)
                                {
                                    JoinMultiparty(group);
                                }
                                else
                                {
                                    Contact part = group.ContactList.GetContactWithCreate(memberAccount, addressType);
                                    Contact real = ContactList.GetContactWithCreate(memberAccount, addressType);
                                    part.SetStatus(real.Status);
                                    OnJoinedGroupChat(new GroupChatParticipationEventArgs(part, group));

                                    if (mpo.InviteQueueHash.Contains(part.SiblingString))
                                        mpo.InviteQueueHash.Remove(part.SiblingString);
                                }
                            }
                        }
                    }
                    break;
                #endregion

                #region network xml
                case "application/network+xml":
                    {
                        if (routingInfo.Sender.ClientType == IMAddressInfoType.RemoteNetwork &&
                            routingInfo.Sender.Account == RemoteNetworkGateways.FaceBookGatewayAccount)
                        {
                            string status = Encoding.UTF8.GetString(multiMimeMessage.InnerBody);

                            PresenceStatus oldStatus = routingInfo.Sender.Status;
                            PresenceStatus newStatus = PresenceStatus.Unknown;

                            if (status.Contains("SignedIn"))
                                newStatus = PresenceStatus.Online;
                            else if (status.Contains("SignedOut"))
                                newStatus = PresenceStatus.Offline;

                            if (newStatus != PresenceStatus.Unknown)
                            {
                                routingInfo.Sender.SetStatus(newStatus);

                                // The contact changed status
                                OnContactStatusChanged(new ContactStatusChangedEventArgs(routingInfo.Sender, routingInfo.SenderGateway, oldStatus, newStatus));

                                if (newStatus == PresenceStatus.Online)
                                    OnContactOnline(new ContactStatusChangedEventArgs(routingInfo.Sender, routingInfo.SenderGateway, oldStatus, newStatus));
                                else
                                    OnContactOffline(new ContactStatusChangedEventArgs(routingInfo.Sender, routingInfo.SenderGateway, oldStatus, newStatus));
                            }
                        }
                    }
                    break;
                #endregion
            }
        }