Skip to main content

restore_save_mte_state

/// <summary>
/// Contacts the server.
/// </summary>
/// <param name="rnd">The random.</param>
/// <param name="currentConversation">The current conversation.</param>
/// <param name="clientNum">The i.</param>
/// <param name="clients">The clients.</param>
/// <exception cref="System.ApplicationException">Error restoring the encoder mte state for
/// Client {i}: {encoder.GetStatusDescription(encoderStatus)}</exception>
/// <exception cref="System.ApplicationException">Error restoring the decoder mte state for
/// Client {i}: {decoder.GetStatusDescription(decoderStatus)}</exception>
/// <exception cref="System.ApplicationException"></exception>
private static async Task ContactServer(Random rnd,
string currentConversation,
int clientNum,
Dictionary<int, string> clients)
{
try
{
//-------------------------------------------------
// Randomly select number of trips between 1 and max number of trips
//-------------------------------------------------
int numberTrips = rnd.Next(1, _maxNumberOfTrips);

//---------------------------------------
// Send message selected number of trips
//---------------------------------------
for (int t = 0; t < numberTrips; t++)
{
//-------------------------------------
// Get the current client encoder state
//-------------------------------------
string encoderState =
Constants.MteClientState.Get($"{Constants.EncoderPrefix}{currentConversation}");
string decryptedEncState =
_enc.Decrypt(encoderState, currentConversation, _encIV);

//-------------------------------------
// Restore the Encoder ensure it works
//-------------------------------------
MteEnc encoder = new MteEnc();
MteStatus encoderStatus = encoder.RestoreStateB64(decryptedEncState);
if (encoderStatus != MteStatus.mte_status_success)
{
Console.WriteLine($"Error restoring the encoder mte state for Client " +
"{clientNum}: {encoder.GetStatusDescription(encoderStatus)}");
throw new ApplicationException($"Error restoring the encoder mte state for Client " +
"{clientNum}: {encoder.GetStatusDescription(encoderStatus)}");
}

//-------------------------------------
// Get the current client decoder state
//-------------------------------------
string decoderState =
Constants.MteClientState.Get($"{Constants.DecoderPrefix}{currentConversation}");
string decryptedDecState =
_enc.Decrypt(decoderState, currentConversation, _encIV);

//-------------------------------------
// Restore the Decoder ensure it works
//-------------------------------------
MteDec decoder = new MteDec();
MteStatus decoderStatus = decoder.RestoreStateB64(decryptedDecState);
if (decoderStatus != MteStatus.mte_status_success)
{
Console.WriteLine($"Error restoring the decoder mte state for Client " +
"{clientNum}: {decoder.GetStatusDescription(decoderStatus)}");
throw new ApplicationException($"Error restoring the decoder mte state for Client " +
"{clientNum}: {decoder.GetStatusDescription(decoderStatus)}");
}

//-------------------------
// Encode message to send
//-------------------------
string message = $"Hello from client {clientNum} for the {t + 1} time.";
string encodedPayload = encoder.EncodeB64(message);
Console.WriteLine($"Sending message '{message}' to multi client server.");

//-----------------------------------------------------------
// Send encoded message to server, putting clientId in header
//-----------------------------------------------------------
string multiClientResponse =
MakeHttpCall($"{_restAPIName}/api/multiclient",
HttpMethod.Post,
currentConversation,
_textContentType,
encodedPayload).Result;

//----------------------
// deserialize response
//----------------------
ResponseModel<string> serverResponse =
JsonSerializer.Deserialize<ResponseModel<string>>(multiClientResponse, _jsonOptions);
if (!serverResponse.Success)
{
if (serverResponse.ResultCode.Equals(Constants.RC_MTE_STATE_NOT_FOUND,
StringComparison.InvariantCultureIgnoreCase))
{
//-------------------------------------------------------------------------
// the server does not have this client's state - we should "re-handshake"
//-------------------------------------------------------------------------
bool handshakeIsSuccessful = HandshakeWithServer(clientNum, clients, currentConversation);
if (!handshakeIsSuccessful)
{
Console.WriteLine($"Error from server for client " +
"{clientNum}: {serverResponse.Message}");
throw new ApplicationException();
}
//-----------------------------------------------------------------
// break out of this loop so we can contact again after handshake
//-----------------------------------------------------------------
return;
}
}

//---------------------------------------------------
// If this was successful save the new encoder state
//---------------------------------------------------
encoderState = encoder.SaveStateB64();
var encryptedEncState = _enc.Encrypt(encoderState, currentConversation, _encIV);
Constants.MteClientState.Store($"{Constants.EncoderPrefix}{currentConversation}",
encryptedEncState,
TimeSpan.FromMinutes(Constants.ExpireMinutes));

//-----------------------------
// decode the incoming message
//-----------------------------
string decodedMessage = decoder.DecodeStrB64(serverResponse.Data, out decoderStatus);
if (decoderStatus != MteStatus.mte_status_success)
{
Console.WriteLine($"Error restoring the decoder mte state for Client " +
"{clientNum}: {decoder.GetStatusDescription(decoderStatus)}");
throw new ApplicationException($"Error restoring the decoder mte state for Client " +
"{clientNum}: {decoder.GetStatusDescription(decoderStatus)}");
}

//----------------------------------------
// If decode is successful save new state
//----------------------------------------
decoderState = decoder.SaveStateB64();
var encryptedDecState = _enc.Encrypt(decoderState, currentConversation, _encIV);
Constants.MteClientState.Store($"{Constants.DecoderPrefix}{currentConversation}",
encryptedDecState,
TimeSpan.FromMinutes(Constants.ExpireMinutes));

//-------------------------------------
// Output incoming message from server
//-------------------------------------
Console.WriteLine($"Received '{decodedMessage}' from multi-client server.\n\n");
// Sleep between each call a random amount of time
// between 10 and 100 milli-seconds
Thread.Sleep(rnd.Next(0, 100));
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
}