示例#1
0
        private void HandleUsrS(NotificationConnection c, Command cmd)
        {
            Md5AuthDetails auth       = c.AuthDetails as Md5AuthDetails;
            String         chResponse = cmd.Params[2];

            if (auth == null)
            {
                // ordinarily that would be an Exception condition
                Command response = new Command(Error.AuthenticationFailed, cmd.TrId);
                Server.Send(c, response);
            }
            else
            {
                User user;
                if (AuthenticationService.AuthenticateMd5(auth.UserHandle, auth.Challenge, chResponse, out user) == AuthenticationResult.Success)
                {
                    Command responseOk = new Command(Verb.Usr, cmd.TrId, "OK", user.UserHandle, user.FriendlyName);
                    Server.Send(c, responseOk);

                    ///////////////////////////////////////
                    // The client will now send SYN

                    // create a session, which is implicit; just bind the user to the connection
                    user.Status             = Status.Hdn;         // no-longer NLN
                    user.NotificationServer = Server;

                    c.User = user;
                }
                else
                {
                    Command responseFail = new Command(Error.AuthenticationFailed, cmd.TrId);
                    Server.Send(c, responseFail);
                }
            }
        }
示例#2
0
        protected virtual void SendLst(NotificationConnection c, int trId, String name, IEnumerable <UserListEntry> userEnum, int serverSerial)
        {
            List <UserListEntry> list = userEnum as List <UserListEntry> ?? new List <UserListEntry>(userEnum);

            int cnt = list.Count;

            if (cnt == 0)
            {
                // if list is empty:
                // LST TrID LIST Ser# 0 0

                Command response = new Command(Verb.Lst, trId, name, serverSerial.ToString(), "0", "0");
                Server.Send(c, response);

                return;
            }

            for (int i = 0; i < cnt; i++)
            {
                UserListEntry entry = list[i];

                // LST <trid> <listName> <serial> <itemIdx> <cntItems> <userHandle> <userCustomName>

                Command response = new Command(Verb.Lst, trId, name, serverSerial.ToString(), (i + 1).ToString(), cnt.ToString(), entry.User.UserHandle, entry.CustomName);
                Server.Send(c, response);
            }
        }
示例#3
0
        protected virtual void HandleUsr(NotificationConnection c, Command cmd)
        {
            // there are two steps:
            // >>> USR trID SP I userHandle
            // <<< USR trID SP S challenge
            // >>> USR trID SP S response
            // <<< USR trID OK userHandle friendlyName

            // for now, only MD5 is supported
            if (cmd.Params[0] != "MD5")
            {
                Command response = new Command(Error.NotExpected, cmd.TrId);
                Server.Send(c, response);
            }
            else
            {
                if (cmd.Params[1] == "I")
                {
                    HandleUsrI(c, cmd);
                }
                else if (cmd.Params[1] == "S")
                {
                    HandleUsrS(c, cmd);
                }
            }
        }
示例#4
0
        protected virtual void HandleXfr(NotificationConnection c, Command cmd)
        {
            // >>> XFR TrID SB
            // <<< XFR TrID SB Address SP AuthChallengeInfo

            if (cmd.Params[0] != "SB")                // only XFRs to Switchboard servers are supported, besides what else is there to XFR to?

            {
                Command errResponse = new Command(Error.SyntaxError, cmd.TrId);
                Server.Send(c, errResponse);
                return;
            }

            // provision the new session

            SwitchboardServer  sb      = SwitchboardServer.Instance;
            SwitchboardSession session = sb.CreateSession(c.User);

            SwitchboardInvitation invite = session.CreateInvitation(c.User);

            invite.Protocol = c.Protocol.Name;

            Command xfrResponse = new Command(Verb.Xfr, cmd.TrId, "SB", sb.GetEndPointForClient(c.Socket.LocalEndPoint).ToString(), "CKI", invite.Key);

            Server.Send(c, xfrResponse);
        }
示例#5
0
        protected virtual void HandleChg(NotificationConnection c, Command cmd)
        {
            Status newStatus = Enumerations.GetStatus(cmd.Params[0]);

            Command response = new Command(Verb.Chg, cmd.TrId, cmd.Params[0]);

            Server.Send(c, response);

            Server.UserStatusChanged(c.User, newStatus);

            // .SentInitialChg is a protocol dialect-dependent property, it shouldn't be a member of NotificationConnection
            // there should be a ProtocolState member instead, which contains this stuff

            if (!c.SentInitialChg)
            {
                // after the initial CHG from the client, give it the ILNs of its Forward List

                foreach (User forwardUser in c.User.Properties.VirtualAllowedForwardList)
                {
                    if (forwardUser.Status != Status.Fln && forwardUser.Status != Status.Hdn)
                    {
                        SendIln(c, cmd.TrId, forwardUser);
                    }
                }

                c.SentInitialChg = true;
            }
        }
示例#6
0
        public async Task GetUsersConnectedAsyncTest()
        {
            await ExecuteTest(async (store) =>
            {
                var context   = store.Context;
                var connected = new ChatLeUser()
                {
                    Id       = "connected",
                    UserName = "******"
                };
                context.Add(connected);

                var nc = new NotificationConnection()
                {
                    ConnectionId     = "test",
                    UserId           = "connected",
                    NotificationType = "test"
                };
                context.NotificationConnections.Add(nc);

                var notConnected = new ChatLeUser()
                {
                    Id       = "notConnected",
                    UserName = "******",
                };
                context.Add(notConnected);

                context.SaveChanges();

                var users = await store.GetUsersConnectedAsync();
                Assert.True(users.Count() == 1);
                Assert.True(users.FirstOrDefault() == connected);
            });
        }
示例#7
0
        protected virtual void SendIln(NotificationConnection c, int trId, User user)
        {
            // <<< ILN TrID Substate UserHandle FriendlyName

            Command iln = new Command(Verb.Iln, trId, user.Status.ToString().ToUpperInvariant(), user.UserHandle, user.FriendlyName);

            Server.Send(c, iln);
        }
示例#8
0
        public override void ASNotifyRea(NotificationConnection recipient, User changedName)
        {
            // I wondered if it was an async REA command sent to the client
            // but I'll try an NLN

            //Command rea = new Command(Verb.Rea, 0, changedName.UserHandle, changedName.FriendlyName);;
            //Server.Send( recipient, rea );

            SendNln(recipient, changedName);
        }
示例#9
0
        public override void ASNotifyRemRL(NotificationConnection recipient, String removedRLEntryUserHandle)
        {
            // <<< REM 0 RL <serial> <userHandle>

            String serial     = recipient.User.Properties.Serial.ToStringInvariant();
            String userHandle = removedRLEntryUserHandle;

            Command rem = new Command(Verb.Rem, 0, "RL", serial, userHandle);

            Server.Send(recipient, rem);
        }
示例#10
0
        protected virtual void HandleOut(NotificationConnection c, Command cmd)
        {
            // for now, this server implementation is entirely reactionary
            // I'll work on async and other stuff later

            // TODO inform the user's ReverseList
            // or should that be done from within CloseConnection, as a connection can be closed in more ways than OUT

            // close the connection, which sends the OUT message
            Server.CloseConnection(c);
        }
示例#11
0
        private void HandleUsrI(NotificationConnection c, Command cmd)
        {
            String userHandle = cmd.Params[2];
            String challenge  = AuthenticationService.CreateChallengeString();

            Command response = new Command(Verb.Usr, cmd.TrId, "MD5", "S", challenge);

            Server.Send(c, response);

            c.AuthDetails = new Md5AuthDetails(userHandle, challenge);
        }
示例#12
0
        protected virtual void HandleUrl(NotificationConnection c, Command cmd)
        {
            // >>> URL trId service [parameter1] [parameterN]
            // <<< URL trId dummy URL 0

            // dummy = unknown literal string "dummy", seems to work
            // URL   = the URL-encoded URL being requested
            // 0     = unknown magic number

            // UPDATE: Messenger 3.6 doesn't seem to like the format of my response
            // UPDATE2: I got an updated syntax definition from the xMSN source, see above

            // in future, when I subclass servers by protocol I'll want to sort this table out so it only has entries relevant to the current protocol

            Dictionary <String, String> urls = new Dictionary <string, string>()
            {
                { "INBOX", "http://www.hotmail.com" },                     // Email Inbox       - MSNP2
                { "COMPOSE", "mailto:{1}" },                               // Send email        - MSNP2
//				{"COMPOSE"   , "mailto:{1}" },             // Send email to {0} - MSNP2
                { "MOBILE", "http://{1}" },                                // MSN Mobile        - MSNP4
                { "PROFILE", "http://{1}" },                               // MSN Profile       - MSNP4
                { "N2PACCOUNT", "http://{1}" },                            // Net2Phone Account - MSNP4
                { "PERSON", "http://{1}" },                                // Member Services   - MSNP4
                { "FOLDERS", "http://{1}" },                               // "MSN Home" page   - MSNP5-7?
                { "CHGMOB", "http://{1}" },                                // Mobile Settings   - MSNP5-7?
                { "CHAT", "http://{1}" },                                  // MSN Chat          - MSNP5-7?
            };

            /*
             *     *  INBOX - Hotmail inbox
             * FOLDERS - Believed to be the Hotmail's "MSN home" URL.
             * COMPOSE - Compose an email
             * COMPOSE [email protected] - Compose an email for [email protected]
             * PROFILE 0x1409 - Edit your MSN member directory profile
             * CHGMOB - Mobile settings (pager etc.)
             * PERSON 0x0409 - Member services, password, secret question, account info
             * CHAT 0x0409 - Chat rooms
             *
             */


            String url = urls.Get(cmd.Params[0]);

            if (url != null)
            {
                url = String.Format(url, cmd.Params);
            }
            url = UtilityMethods.UrlEncode(url);

            Command response = new Command(Verb.Url, cmd.TrId, "dummy", url, "0");             // I assume this is how it expects it

            Server.Send(c, response);
        }
示例#13
0
        protected virtual void HandleGtc(NotificationConnection c, Command cmd)
        {
            // >>> GTC TrID [A | N]
            // <<< GTC TrID Ser# [A | N]

            c.User.Properties.GtcSetting = cmd.Params[0] == "A" ? AllowSetting.Allow : AllowSetting.Block;
            c.User.Properties.Serial++;

            Command response = new Command(Verb.Gtc, cmd.TrId, c.User.Properties.Serial.ToStringInvariant());

            Server.Send(c, response);
        }
示例#14
0
        protected virtual void HandleBlp(NotificationConnection c, Command cmd)
        {
            // >>> BLP TrID [AL | BL]
            // <<< BLP TrID Ser# [AL | BL]

            c.User.Properties.BlpSetting = cmd.Params[0] == "AL" ? AllowSetting.Allow : AllowSetting.Block;
            c.User.Properties.Serial++;

            Command response = new Command(Verb.Blp, cmd.TrId, c.User.Properties.Serial.ToStringInvariant());

            Server.Send(c, response);
        }
示例#15
0
        public async Task Invoke(HttpContext context)
        {
            try
            {
                if (!context.WebSockets.IsWebSocketRequest)
                {
                    return;
                }

                var socket = await context.WebSockets.AcceptWebSocketAsync();

                var publisherId     = context.Request.Query[NotificationConnection.PublisherIdKey];
                var connectionExtra = new Dictionary <string, string>();

                connectionExtra.Add(NotificationConnection.PublisherIdKey, publisherId);
                var connection = new NotificationConnection(socket, connectionExtra);

                if (!_handler.OnAccept(connection))
                {
                    connection.Close();
                    return;
                }

                _handler.OnConnected(connection);

                byte[] buffer = new byte[1024];

                while (true)
                {
                    try
                    {
                        var result = await socket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None);

                        if (result.MessageType == System.Net.WebSockets.WebSocketMessageType.Close)
                        {
                            _handler.OnClose(connection);
                        }
                    }
                    catch (WebSocketException e)
                    {
                        _handler.OnClose(connection);

                        break;
                    }
                }
            }
            catch (Exception e)
            {
            }
            finally
            {
            }
        }
示例#16
0
        public override void ASNotifyAddRL(NotificationConnection recipient, UserListEntry newRLEntry)
        {
            // ADD TrID LIST ser# UserHandle CustomUserName
            // as this is async, TrID == 0

            String serial     = recipient.User.Properties.Serial.ToStringInvariant();
            String userHandle = newRLEntry.User.UserHandle;
            String customName = newRLEntry.CustomName;

            Command add = new Command(Verb.Add, 0, "RL", serial, userHandle, customName);

            Server.Send(recipient, add);
        }
示例#17
0
        public async Task NotificationConnectionAsyncTest()
        {
            await ExecuteTest(async (store) =>
            {
                var context = store.Context;
                var user    = new ChatLeUser()
                {
                    Id       = "test",
                    UserName = "******",
                };
                context.Add(user);
                context.SaveChanges();

                var nc = new NotificationConnection()
                {
                    ConnectionId     = "test",
                    UserId           = "test",
                    NotificationType = "test"
                };

                await store.CreateNotificationConnectionAsync(nc);

                Assert.Equal(1, context.NotificationConnections.Count());

                nc = await store.GetNotificationConnectionAsync("test", "test");
                await store.DeleteNotificationConnectionAsync(nc);

                Assert.Empty(context.NotificationConnections);

                var nc1 = new NotificationConnection()
                {
                    ConnectionId     = "test",
                    UserId           = "test",
                    NotificationType = "test"
                };

                await store.CreateNotificationConnectionAsync(nc1);
                var nc2 = new NotificationConnection()
                {
                    ConnectionId     = "test2",
                    UserId           = "test2",
                    NotificationType = "test"
                };

                await store.CreateNotificationConnectionAsync(nc2);

                Assert.Equal(2, context.NotificationConnections.Count());
            });
        }
示例#18
0
        public override void ASNotifyRng(UserListEntry caller, NotificationConnection recipient, SwitchboardInvitation invitation)
        {
            // <<< RNG <SessionID> <SwitchboardServerAddress> <SP> <AuthChallengeInfo> <CallingUserHandle> <CallingUserFriendlyName>

            invitation.Protocol = this.Name;             // note this property's value is appropriate for the current protocol subclass

            SwitchboardSession session = invitation.Session;

            String sessionId = session.Id.ToStringInvariant();
            String sbAddr    = session.Server.GetEndPointForClient(recipient.Socket.LocalEndPoint).ToString();

            Command rng = new Command(Verb.Rng, -1, sessionId, sbAddr, "CKI", invitation.Key, caller.User.UserHandle, caller.CustomName);

            Server.Send(recipient, rng);               // I assume this won't be null for small-scale stuff
        }
示例#19
0
        public override void ASOut(NotificationConnection c, OutReason reason)
        {
            Command outCmd;

            if (reason != OutReason.None)
            {
                outCmd = new Command(Verb.Out, -1, reason == OutReason.Oth ? "OTH" : "SSD");
            }
            else
            {
                outCmd = new Command(Verb.Out, -1);
            }

            Server.Send(c, outCmd);
        }
示例#20
0
        protected virtual void HandleLst(NotificationConnection c, Command cmd)
        {
            // >>> LST TrID list
            // <<< LST TrID list Ser# Item# TtlItems UserHandle CustomUserName

            // list is FL/RL/AL/BL for Forward List, Reverse List, Allow List, and Block List, respectively.
            // The Item# parameter contains the index of the item described in this command message. (E.g. item 1 of N, 2 of N, etc.)
            // - The TtlItems parameter contains the total number of items in this list.
            // - UserHandle is the user handle for this list item.
            // - CustomUserName is the friendly name for this list item.

            // If the list is empty, the response will be:

            // <<< LST TrID list Ser# 0 0

            switch (cmd.Params[0])
            {
            case "FL":

                SendLst(c, cmd.TrId, "FL", c.User.Properties.ForwardList.Values, c.User.Properties.Serial);

                break;

            case "AL":

                SendLst(c, cmd.TrId, "AL", c.User.Properties.VirtualAllowList, c.User.Properties.Serial);

                break;

            case "BL":

                SendLst(c, cmd.TrId, "BL", c.User.Properties.VirtualBlockList, c.User.Properties.Serial);

                break;

            case "RL":

                SendLst(c, cmd.TrId, "RL", c.User.Properties.ReverseList.Values, c.User.Properties.Serial);

                break;

            default:
                Command errorSyntax = new Command(Error.InvalidParameter, cmd.TrId);                         // or syntax error
                Server.Send(c, errorSyntax);
                return;
            }
        }
示例#21
0
        /////////////////////////////////////////////////////////
        // Notification

        protected virtual void HandleSyn(NotificationConnection c, Command cmd)
        {
            int clientSerial = Int32.Parse(cmd.Params[0]);
            int serverSerial = c.User.Properties.Serial;

            if (clientSerial > c.User.Properties.Serial)
            {
                // this should never happen as the client's cache is always older than the server
                // but in a debugging situation or if the client's cache is corrupted then just lie to the client

                c.User.Properties.Serial = serverSerial = clientSerial + 1;
                // ha! take that MSN Messenger 1.0!
            }

            Command response = new Command(Verb.Syn, cmd.TrId, serverSerial.ToString());

            Server.Send(c, response);

            ///////////////////////

            int trId = cmd.TrId;

            if (clientSerial < c.User.Properties.Serial)
            {
                // send out the lists to the client using the same TrId

                // "After the SYN reply from the server, the user property updates will be sent from the server in this sequence:
                // "GTC, BLP, LST FL, LST AL, LST BL, LST RL."

                // GTC
                SendGtc(c, trId, c.User.Properties.GtcSetting, serverSerial);

                // BLP
                SendBlp(c, trId, c.User.Properties.BlpSetting, serverSerial);

                // LST FL
                SendLst(c, trId, "FL", c.User.Properties.ForwardList.Values, serverSerial);
                SendLst(c, trId, "AL", c.User.Properties.VirtualAllowList, serverSerial);
                SendLst(c, trId, "BL", c.User.Properties.VirtualBlockList, serverSerial);
                SendLst(c, trId, "RL", c.User.Properties.ReverseList.Values, serverSerial);
            }
        }
示例#22
0
        protected virtual void HandleRea(NotificationConnection c, Command cmd)
        {
            // >>> REA trid email display-name
            // <<< REA trid ver-num email display-name

            // renames the customName in the ForwardList OR renames self
            // I don't know if I'm meant to send out any asynchronous updates to other users or anything

            // In xMSN, it sends an async version of REA (trId == 0) to everyone in the Allowed/Reverse list, so let's do that

            String userHandle = cmd.Params[0];
            String newName    = cmd.Params[1];

            if (newName.Length > 387)
            {
                Command error = new Command(Error.InvalidFriendlyName, cmd.TrId);
                Server.Send(c, error);
            }
            else
            {
                User target = User.GetUser(userHandle);
                if (target == c.User)
                {
                    Server.UserRenamed(target, newName);
                    // Server.UserRenamed sends notifications to the contact's users

                    // BTW, the 'ver-num' field is undocumented, so I guess return the userProperties serial?
                    Command response = new Command(Verb.Rea, cmd.TrId, target.Properties.Serial.ToStringInvariant(), userHandle, newName);
                    Server.Send(c, response);
                }
                else
                {
                    // rename the specified object in the ForwardList. This obviously does not send any notifications out
                    Server.UserFLRenamed(c.User, target, newName);

                    // NOTE: can it send a REA to rename something in the RL, AL, or BL?

                    Command response = new Command(Verb.Rea, cmd.TrId, c.User.Properties.Serial.ToStringInvariant(), userHandle, newName);
                    Server.Send(c, response);
                }
            }
        }
示例#23
0
        /// <summary>Sends an NLN to the specified connection, this NLN shows the current state of <param name="user"/>'s connection</summary>
        protected virtual void SendNln(NotificationConnection c, User user)
        {
            // now online:    <<< NLN Substate UserHandle FriendlyName
            // initial state: <<< ILN TrID Substate UserHandle FriendlyName
            // now offline:   <<< FLN UserHandle

            // I don't understand ILN just yet, so I'll just implement NLN and FLN
            // UPDATE: ILN is sent only when logging on or when adding someone to your FL (and you're allowed to see them)

            if ((user.Status & Status.Nln) == Status.Nln)
            {
                Command nln = new Command(Verb.Nln, -1, user.Status.ToString().ToUpperInvariant(), user.UserHandle, user.FriendlyName);
                Server.Send(c, nln);
            }
            else
            {
                Command fln = new Command(Verb.Fln, -1, user.UserHandle);
                Server.Send(c, fln);
            }
        }
示例#24
0
        protected virtual void HandleAdd(NotificationConnection c, Command cmd)
        {
            // >>> ADD TrID LIST UserHandle CustomUserName
            // <<< ADD TrID LIST ser# UserHandle CustomUserName

            String listName   = cmd.Params[0];
            String userHandle = cmd.Params[1];
            String customName = cmd.Params[2];

            User owner  = c.User;
            User target = User.GetUser(userHandle);

            if (target == null)
            {
                Command errorDoesntExist = new Command(Error.InvalidUser, cmd.TrId);
                Server.Send(c, errorDoesntExist);
                return;
            }

            switch (listName)
            {
            case "FL":
            case "RL":
            case "AL":
            case "BL":

                Server.AddToList(owner, listName, target, customName);

                Command response = new Command(Verb.Add, cmd.TrId, listName, owner.Properties.Serial.ToStringInvariant(), userHandle, customName);
                Server.Send(c, response);

                break;

            default:

                Command errorSyntax = new Command(Error.SyntaxError, cmd.TrId);
                Server.Send(c, errorSyntax);
                return;
            }
        }
示例#25
0
        public static void Main(string[] args)
        {
            var connection = new NotificationConnection(true, "certificate.pfx", "lalala");
            var client     = new PushNotification(connection);

            var notification = new NotificationPayload("<334b1ddf c30c4582 c497c058 c0d94ccf ad6409b2 7fa1ffbf 6f372427 7ba33e54>");

            notification.Badge = 0;
            notification.Alert = new Alert()
            {
                Body = "hello"
            };
            client.SendAsync(new[] { notification, notification, notification }).Wait();

            var feedbackConnection = new FeedbackConnection(true, "certificate.pfx", "lalala");
            var feedbackReader     = new FeedbackReader(feedbackConnection);


            var feedback = feedbackReader.GetFeedBackAsync().Result;

            System.Console.ReadLine();
        }
示例#26
0
 public override void ASNotifyFln(NotificationConnection recipient, User flnUser)
 {
     // this doesn't work if the FLN is meant to be sent in a case of blocking
     SendNln(recipient, flnUser);
 }
示例#27
0
 public override void ASNotifyIln(NotificationConnection recipient, User ilnUser)
 {
     SendIln(recipient, 0, ilnUser);
 }
示例#28
0
 public override void ASNotifyNln(NotificationConnection recipient, User updatedUser)
 {
     SendNln(recipient, updatedUser);
 }
示例#29
0
        public override void HandleCommand(NotificationConnection c, Command cmd)
        {
            switch (cmd.Verb)
            {
            // Dispatch Tasks
            case Verb.Cvr:
                HandleCvr(c, cmd);
                break;

            case Verb.Cvq:
                HandleCvr(c, cmd);
                break;

            case Verb.Inf:
                HandleInf(c, cmd);
                break;

            case Verb.Usr:
                HandleUsr(c, cmd);
                break;

            // Notification
            // Initial
            case Verb.Syn:
                HandleSyn(c, cmd);
                break;

            case Verb.Lst:
                HandleLst(c, cmd);
                break;

            // List Management
            case Verb.Add:
                HandleAdd(c, cmd);
                break;

            case Verb.Rem:
                HandleRem(c, cmd);
                break;

            case Verb.Rea:
                HandleRea(c, cmd);
                break;

            case Verb.Chg:
                HandleChg(c, cmd);
                break;

            case Verb.Blp:
                HandleBlp(c, cmd);
                break;

            case Verb.Gtc:
                HandleBlp(c, cmd);
                break;

            // Info
            case Verb.Url:
                HandleUrl(c, cmd);
                break;

            case Verb.Out:
                HandleOut(c, cmd);
                break;

            case Verb.Xfr:
                HandleXfr(c, cmd);
                break;

// TODO
//				case Verb.Fnd:
//				case Verb.Sdc:
//				case Verb.Snd:
//					break;

            default:
                HandleUnrecognised(c, cmd);
                break;
            }
        }
示例#30
0
        protected virtual void SendBlp(NotificationConnection c, int trId, AllowSetting gtcSetting, int serverSerial)
        {
            Command response = new Command(Verb.Blp, trId, serverSerial.ToString(), gtcSetting == AllowSetting.Allow ? "AL" : "BL");

            Server.Send(c, response);
        }