private void BeginReceiveCallback(IAsyncResult results) { var state = (AuthenticationState)results.AsyncState; // Timeout, socket has been closed. if (state.client.Client == null) { return; } var packet = (AuthenticationPacket)PacketSerializer.Deserialize(state.buffer)[0]; var auth = state.auth; if (packet.version == auth.version && packet.time == auth.time && !string.IsNullOrEmpty(packet.response) && Guid.Parse(packet.guid) == state.guid) { AuthenticationSuccess?.Invoke(state.client, packet); } else { AuthenticationFailed?.Invoke(state.client); } }
/// <summary> /// Processes an incoming command frame from the connection. /// Captures the call if it is a Rpc command. /// </summary> /// <param name="frame">Command frame to process.</param> protected override void ProcessCommand(MqFrame frame) { var commandType = (MqCommandType)frame.ReadByte(0); // If this is a base MqCommand, pass this directly on to the base command handler. if (commandType != MqCommandType.RpcCommand) { base.ProcessCommand(frame); return; } try { var rpcCommandType = (RpcCommandType)frame.ReadByte(1); if (rpcCommandType == RpcCommandType.WelcomeMessage) { // RpcCommand:byte; RpcCommandType:byte; RpcServerInfoDataContract:byte[]; // Ensure that this command is running on the client. if (BaseSocket.Mode != SocketMode.Client) { Close(SocketCloseReason.ProtocolError); return; } var serializer = SerializationCache.Get(new MqMessage(frame)); // Forward the reader two bytes to the data. serializer.MessageReader.ReadBytes(2); serializer.PrepareDeserializeReader(); // Try to read the information from the server about the server. Client.ServerInfo = serializer.DeserializeFromReader(typeof(RpcServerInfoDataContract)) as RpcServerInfoDataContract; if (Client.ServerInfo == null) { Close(SocketCloseReason.ProtocolError); return; } // Check to see if the server requires authentication. If so, send a auth check. if (Client.ServerInfo.RequireAuthentication) { var authArgs = new RpcAuthenticateEventArgs <TSession, TConfig>((TSession)this); // Start the authentication event to get the auth data. Authenticate?.Invoke(this, authArgs); serializer.MessageWriter.Write((byte)MqCommandType.RpcCommand); serializer.MessageWriter.Write((byte)RpcCommandType.AuthenticationRequest); if (authArgs.AuthData == null) { authArgs.AuthData = new byte[] { 0 }; } serializer.MessageWriter.Write(authArgs.AuthData, 0, authArgs.AuthData.Length); var authMessage = serializer.MessageWriter.ToMessage(true); authMessage[0].FrameType = MqFrameType.Command; _authTimeout = new Task(async() => { try { await Task.Delay(Config.ConnectionTimeout, _authTimeoutCancel.Token); } catch { return; } if (!_authTimeoutCancel.IsCancellationRequested) { Close(SocketCloseReason.TimeOut); } }); // RpcCommand:byte; RpcCommandType:byte; AuthData:byte[]; Send(authMessage); _authTimeout.Start(); } else { // If no authentication is required, set this client to authenticated. Authenticated = true; // Alert the server that this session is ready for usage. Task.Run( () => { Ready?.Invoke(this, new SessionEventArgs <TSession, TConfig>((TSession)this)); }); } SerializationCache.Put(serializer); } else if (rpcCommandType == RpcCommandType.AuthenticationRequest) { // RpcCommand:byte; RpcCommandType:byte; AuthData:byte[]; // If this is not run on the server, quit. if (BaseSocket.Mode != SocketMode.Server) { Close(SocketCloseReason.ProtocolError); return; } // Ensure that the server requires authentication. if (Server.Config.RequireAuthentication == false) { Close(SocketCloseReason.ProtocolError); return; } byte[] authBytes = new byte[frame.DataLength - 2]; frame.Read(2, authBytes, 0, authBytes.Length); var authArgs = new RpcAuthenticateEventArgs <TSession, TConfig>((TSession)this) { AuthData = authBytes }; Authenticate?.Invoke(this, authArgs); Authenticated = authArgs.Authenticated; if (Authenticated == false) { Close(SocketCloseReason.AuthenticationFailure); } else { var authFrame = CreateFrame(new byte[authArgs.AuthData.Length + 2], MqFrameType.Command); authFrame.Write(0, (byte)MqCommandType.RpcCommand); authFrame.Write(1, (byte)RpcCommandType.AuthenticationResult); // State of the authentication authFrame.Write(2, Authenticated); // RpcCommand:byte; RpcCommandType:byte; AuthResult:bool; Send(authFrame); // Alert the server that this session is ready for usage. Task.Run( () => { Ready?.Invoke(this, new SessionEventArgs <TSession, TConfig>((TSession)this)); }); } } else if (rpcCommandType == RpcCommandType.AuthenticationResult) { // RpcCommand:byte; RpcCommandType:byte; AuthResult:bool; // Cancel the timeout request. _authTimeoutCancel.Cancel(); // Ensure that this command is running on the client. if (BaseSocket.Mode != SocketMode.Client) { Close(SocketCloseReason.ProtocolError); return; } if (Client.Config.RequireAuthentication == false) { Close(SocketCloseReason.ProtocolError); return; } Authenticated = true; var authArgs = new RpcAuthenticateEventArgs <TSession, TConfig>((TSession)this) { Authenticated = frame.ReadBoolean(2) }; // Alert the client that the sesion has been authenticated. AuthenticationSuccess?.Invoke(this, authArgs); // Alert the client that this session is ready for usage. Task.Run(() => { Ready?.Invoke(this, new SessionEventArgs <TSession, TConfig>((TSession)this)); }); } else { Close(SocketCloseReason.ProtocolError); } } catch (Exception) { Close(SocketCloseReason.ProtocolError); } }