Пример #1
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);
        }
Пример #2
0
        protected virtual void HandleMsg(SwitchboardConnection c, Command cmd)
        {
            // >>> MSG TrID [U | N | A] Length\r\nMessage
            // <<< NAK TrID
            // <<< ACK TrID

            String ackMode = cmd.Params[0];
            String message = cmd.Payload;
            int    messLen = Int32.Parse(cmd.Params[1]);

            if (messLen != message.Length)
            {
                throw new ProtocolException();
            }

            SwitchboardSession session = c.Session;

            // TODO: I'll need to convert MSGs or do some kind of special handling if there's any protocol-specific functionality
            // <<< MSG UserHandle FriendlyName Length\r\nMessage
            Command broadcastMsg = Command.CreateWithPayload(Verb.Msg, -1, message, c.User.UserHandle, c.User.FriendlyName);
            bool    succeeded    = Server.BroadcastCommand(session, broadcastMsg, c);

            // TODO: I'll need to separate out ACK code because it is NOT as simple as this

            switch (ackMode)
            {
            case "U":
                // Send nothing
                return;

            case "N":
                // Send only if it fails
                if (!succeeded)
                {
                    Server.Send(c, new Command(Verb.Nak, cmd.TrId));
                }
                break;

            case "A":

                // the spec didn't say what the response was in A mode (as it isn't implemented in MSNP2) but I assume this is what the client expects
                // ACK if it succeeds, and NAK if it fails
                Command response = new Command(succeeded ? Verb.Ack : Verb.Nak, cmd.TrId);
                Server.Send(c, response);

                break;

            default:

                Command errResponse = new Command(Error.InvalidParameter, cmd.TrId);
                Server.Send(c, errResponse);
                break;
            }
        }
Пример #3
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
        }
Пример #4
0
        protected virtual void HandleUsr(SwitchboardConnection c, Command cmd)
        {
            // >>> USR TrID UserHandle AuthResponseInfo
            // <<< USR TrID OK UserHandle FriendlyName

            // authenticate and ensure there's a matching session invite

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

            User user = User.GetUser(userHandle);

            SwitchboardInvitation invite = Server.GetInvitationByUserAndKey(user, keyToken);

            if (invite == null)
            {
                Command err = new Command(Error.AuthenticationFailed, cmd.TrId);
                Server.Send(c, err);
            }
            else
            {
                invite.SetRsvp();

                if (c.Protocol == null)
                {
                    c.Protocol = _protocols.Find(p => p.CompatibleWithProtocol(invite.Protocol));                         //( p => p.Name == invite.Protocol );
                }
                SwitchboardSession session = invite.Session;
                c.User    = user;
                c.Session = session;
                session.Connections.Add(c);

                User thisUser = User.GetUser(userHandle);

                Command response = new Command(Verb.Usr, cmd.TrId, "OK", userHandle, thisUser.FriendlyName);
                Server.Send(c, response);
            }
        }
Пример #5
0
        protected virtual void HandleCal(SwitchboardConnection c, Command cmd)
        {
            // >>> CAL TrID UserHandle
            // <<< CAL TrID Status SessionID

            String recipientHandle = cmd.Params[0];

            User recipient = User.GetUser(recipientHandle);

            if (recipient.NotificationServer == null ||
                (recipient.Status & Status.Nln) != Status.Nln)
            {
                // the user is not online (or is hidden)

                Command responseErr = new Command(Error.SwitchboardFailed, cmd.TrId);                 // I guess?
                Server.Send(c, responseErr);

                return;
            }

            // if the invited user is allowed to contact the calling user (or vice-versa) then that user's notification server sends a RNG
            // otherwise, SB returns an error

            // TODO: Check permissions first

            User caller = c.User;
            SwitchboardSession session = c.Session;

            SwitchboardInvitation invite = session.CreateInvitation(recipient);

            recipient.NotificationServer.ASNotifyRng(caller, recipient, invite);

            Command responseOk = new Command(Verb.Cal, cmd.TrId, "RINGING", session.Id.ToStringInvariant());

            Server.Send(c, responseOk);
        }
Пример #6
0
        protected virtual void HandleAns(SwitchboardConnection c, Command cmd)
        {
            // >>> ANS TrID LocalUserHandle AuthResponseInfo SessionID
            // <<< IRO TrID Participant# TotalParticipants UserHandle FriendlyName
            // <<< ANS TrID OK

            // add this user to that session, assuming it authenticates

            String sessionKey = cmd.Params[1];
            Int32  sessionId  = Int32.Parse(cmd.Params[2]);

            User user = User.GetUser(cmd.Params[0]);

            if (user == null)
            {
                Command responseErr = new Command(Error.AuthenticationFailed, cmd.TrId);
                Server.Send(c, responseErr);
                return;
            }

            SwitchboardInvitation invite = Server.GetInvitationByUserKeyAndId(user, sessionKey, sessionId);

            if (invite == null)
            {
                Command responseErr = new Command(Error.AuthenticationFailed, cmd.TrId);
                Server.Send(c, responseErr);
                return;
            }

            invite.SetRsvp();

            if (c.Protocol == null)
            {
                c.Protocol = _protocols.Find(p => p.CompatibleWithProtocol(invite.Protocol));                     //( p => p.Name == invite.Protocol );
            }
            SwitchboardSession session = invite.Session;

            int cnt = session.Connections.Count;

            for (int i = 0; i < session.Connections.Count; i++)
            {
                SwitchboardConnection sc = session.Connections[i];

                if (sc != c)
                {
                    Command iro = new Command(Verb.Iro, cmd.TrId, (i + 1).ToStringInvariant(), cnt.ToStringInvariant(), sc.User.UserHandle, sc.User.FriendlyName);
                    Server.Send(c, iro);
                }
            }

            c.User    = user;
            c.Session = session;

            session.Connections.Add(c);

            Command respOk = new Command(Verb.Ans, cmd.TrId, "OK");

            Server.Send(c, respOk);

            // When a new user joins a Switchboard session, the server sends the
            // following command to all participating clients, including the client
            // joining the session:

            // <<< JOI CalleeUserHandle CalleeUserFriendlyName

            // UPDATE: Actually, I think not; don't send it to the person joining

            Command joi = new Command(Verb.Joi, -1, user.UserHandle, user.FriendlyName);

            Server.BroadcastCommand(session, joi, c);
        }