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); }
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; } }
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 }
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); } }
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); }
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); }