Ejemplo n.º 1
0
            //~~~~~~~~~~~~~~{Setter}~~~~~~~~~~~~~~

            /// <summary>Merges two connections, grabbing the socket from this conneciton</summary>
            /// <param name="OtherConnection"></param>
            public void AbsorbConnection(SwitchboardConnection OtherConnection)
            {
                while (Busy)
                {
                }                   //Wait for *this* connection to not be busy

                TickThread.Abort(); //Stop the thread

                //Close this connection's river and socket
                River.Close();
                TheSocket.Close();

                //Move everything over
                River     = OtherConnection.River;
                TheSocket = OtherConnection.TheSocket;
                IP        = OtherConnection.IP;

                //Send OK
                Send("OK", false);

                //Start async again
                StartAsync();

                //Log it
                HeadServer.ToLog("User from " + IP.Address.ToString() + " reconnected from " + OtherConnection.IP.Address.ToString());

                //Remove the other connection from the list of connections
                HeadServer.Connections.Remove(OtherConnection.ID);

                //Look at how far back we can go
                HeadServer.TheForm.ServerBWorker.ReportProgress(0); //Refresh the main form's listview.

                //Stop the other tickthread. This will stop *this* operation, so it's the last one to go.
                OtherConnection.TickThread.Abort();
            }
Ejemplo n.º 2
0
        protected virtual void HandleOut(SwitchboardConnection c, Command cmd)
        {
            // remove the user from its SB session
            // and send BYE to the users

            if (c.Session != null)
            {
                c.Session.Connections.Remove(c);                   // HACK: This isn't thread-safe

                Command bye = new Command(Verb.Bye, -1, c.User.UserHandle);

                if (c.Session.Connections.Count == 0)
                {
                    Server.EndSession(c.Session);
                }
                else
                {
                    Server.BroadcastCommand(c.Session, bye, c);
                }

                c.Session = null;
            }

            // SB servers don't echo an OUT unlike NS or DS
            Server.CloseConnection(c);
        }
Ejemplo n.º 3
0
        public override void HandleCommand(SwitchboardConnection c, Command cmd)
        {
            switch (cmd.Verb)
            {
            case Verb.Usr:
                HandleUsr(c, cmd);
                break;

            case Verb.Ans:
                HandleAns(c, cmd);
                break;

            case Verb.Cal:
                HandleCal(c, cmd);
                break;

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

            case Verb.Msg:
                HandleMsg(c, cmd);
                break;

            default:
                HandleUnrecognised(c, cmd);
                break;
            }
        }
Ejemplo n.º 4
0
        //------------------------------[Functions]------------------------------

        /// <summary>
        /// Ticks the server. Each tick, the server: <br></br><br></br>
        /// <list type="number">
        /// <item>Checks if there's a pending connection, and if so allows them in.</item>
        /// <item>Ticks each connection, essentially processing any pending commands they have.</item>
        /// <item>Checks if any connection has been closed, and if so, removes it.</item>
        /// <item>Ticks each extension.</item>
        /// </list></summary>
        public void Tick()
        {
            //Check if we need to let in another connection.
            if (Ears.Pending())
            {
                int newID = GetNewConnectionID();

                SwitchboardConnection Connection = new SwitchboardConnection(this, Ears.AcceptSocket(), newID);
                Connections.Add(newID, Connection);      //Let them in to the system.
                Connection.StartAsync();
                TheForm.ServerBWorker.ReportProgress(0); //Refresh the main form's listview.
            }

            foreach (SwitchboardConnection Connection in GetConnections())
            {
                if (!Connection.IsConnected)
                {
                    Connections.Remove(Connection.ID);       //if the connection was closed, remove it from the list
                    TheForm.ServerBWorker.ReportProgress(0); //Refresh the main form's listview.
                }
            }

            //Now tick every extension
            foreach (SwitchboardExtension extension in Extensions)
            {
                extension.Tick();
            }
        }
Ejemplo n.º 5
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;
            }
        }
Ejemplo n.º 6
0
        private void ConnectionDetailsButton_Click(object sender, EventArgs e)
        {
            //Make sure there is at least one connection selected.
            //Well, there will only ever be one because we disabled multi-select but shh its ok.
            if (ConnectionsListView.SelectedIndices.Count == 0)
            {
                MessageBox.Show("Please select a connection to see its details", "n o", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            //Get the connection index
            int ConnectionIndex = ConnectionsListView.SelectedIndices[0];

            //Get the connection.
            SwitchboardConnection Connection = MainServer.GetConnections()[ConnectionIndex];

            //Pass the connection to a connection details form
            new UserDetailsForm(ref Connection).Show();
        }
Ejemplo n.º 7
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);
            }
        }
Ejemplo n.º 8
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);
        }
Ejemplo n.º 9
0
 internal UserDetailsForm(ref SwitchboardConnection MyConnection)
 {
     InitializeComponent();
     this.MyConnection = MyConnection;
     RefreshDetails();
 }
Ejemplo n.º 10
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);
        }