Skip to content

Commit

Permalink
Callout from @BeipDev on an incorrect reading of the CHARSET RFC. Adj…
Browse files Browse the repository at this point in the history
…usted Unit Test and Code.
  • Loading branch information
HarryCordewener committed Jan 2, 2024
1 parent 5bbecc6 commit 12da8b5
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 13 deletions.
16 changes: 4 additions & 12 deletions TelnetNegotiationCore/Interpretors/TelnetCharsetInterpretor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,20 +238,12 @@ private async Task CompleteAcceptedCharsetAsync(StateMachine<State, Trigger>.Tra
{
try
{
CurrentEncoding = Encoding.GetEncoding(ascii.GetString(_acceptedCharsetByteState, 1, _acceptedCharsetByteIndex - 1).Trim());
CurrentEncoding = Encoding.GetEncoding(ascii.GetString(_acceptedCharsetByteState, 0, _acceptedCharsetByteIndex).Trim());
}
catch (Exception ex1)
catch (Exception ex)
{
_Logger.Warning(ex1, "Potentially expected error during Accepting Charset Negotiation. Seperator not passed back. Trying without seperator.");
try
{
CurrentEncoding = Encoding.GetEncoding(ascii.GetString(_acceptedCharsetByteState, 0, _acceptedCharsetByteIndex).Trim());
}
catch (Exception ex2)
{
_Logger.Warning(ex2, "Unexpected error during Accepting Charset Negotiation. Could not find charset: {charset}", ascii.GetString(_acceptedCharsetByteState, 0, _acceptedCharsetByteIndex));
await CallbackNegotiation(new byte[] { (byte)Trigger.IAC, (byte)Trigger.SB, (byte)Trigger.CHARSET, (byte)Trigger.REJECTED, (byte)Trigger.IAC, (byte)Trigger.SE });
}
_Logger.Error(ex, "Unexpected error during Accepting Charset Negotiation. Could not find charset: {charset}", ascii.GetString(_acceptedCharsetByteState, 0, _acceptedCharsetByteIndex));
await CallbackNegotiation(new byte[] { (byte)Trigger.IAC, (byte)Trigger.SB, (byte)Trigger.CHARSET, (byte)Trigger.REJECTED, (byte)Trigger.IAC, (byte)Trigger.SE });
}
_Logger.Information("Connection: Accepted Charset Negotiation for: {charset}", CurrentEncoding.WebName);
charsetoffered = false;
Expand Down
65 changes: 64 additions & 1 deletion TelnetNegotiationCore/Interpretors/TelnetMSSPInterpretor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ public partial class TelnetInterpretor
{
private MSSPConfig _msspConfig;

private List<byte> _currentVariable;
private List<byte> _currentValue;

/// <summary>
/// Mud Server Status Protocol will provide information to the requestee about the server's contents.
/// </summary>
Expand Down Expand Up @@ -55,12 +58,72 @@ private StateMachine<State, Trigger> SetupMSSPNegotiation(StateMachine<State, Tr
.SubstateOf(State.Accepting)
.OnEntry(() => _Logger.Debug("Connection: {connectionStatus}", "Server won't do MSSP - do nothing"));

/// TODO: Accept MSSP and interpret it into a structure.
tsm.Configure(State.SubNegotiation)
.Permit(Trigger.MSSP, State.AlmostNegotiatingMSSP)
.OnEntry(() => {
_currentValue = new List<byte>();
_currentVariable = new List<byte>();
});

tsm.Configure(State.AlmostNegotiatingMSSP)
.Permit(Trigger.MSSP_VAR, State.EvaluatingMSSPVar);

tsm.Configure(State.EvaluatingMSSPVar)
.Permit(Trigger.MSSP_VAL, State.EvaluatingMSSPVal)
.Permit(Trigger.IAC, State.EscapingMSSPVar);

tsm.Configure(State.EscapingMSSPVar)
.Permit(Trigger.IAC, State.EvaluatingMSSPVar);

tsm.Configure(State.EvaluatingMSSPVal)
.Permit(Trigger.MSSP_VAR, State.EvaluatingMSSPVar)
.Permit(Trigger.IAC, State.EscapingMSSPVal);

tsm.Configure(State.EscapingMSSPVal)
.Permit(Trigger.IAC, State.EvaluatingMSSPVal)
.Permit(Trigger.SE, State.CompletingMSSP);

tsm.Configure(State.CompletingMSSP)
.SubstateOf(State.Accepting)
.OnEntryAsync(ReadMSSPValues);

TriggerHelper.ForAllTriggers(t => tsm.Configure(State.EvaluatingMSSPVal).OnEntryFrom(ParametarizedTrigger(t), CaptureValue));
TriggerHelper.ForAllTriggers(t => tsm.Configure(State.EvaluatingMSSPVar).OnEntryFrom(ParametarizedTrigger(t), CaptureVariable));
}

return tsm;
}

private async Task ReadMSSPValues()
{
var variableList = _currentVariable.Split((byte)Trigger.MSSP_VAR);
var valueList = _currentVariable.Split((byte)Trigger.MSSP_VAL);

var vv = variableList.Zip(valueList);

await Task.CompletedTask;
}

/*
* For ease of parsing, variables and values cannot contain the MSSP_VAL, MSSP_VAR, IAC, or NUL byte.
* The value can be an empty string unless a numeric value is expected in which case the default value should be 0.
* If your Mud can't calculate one of the numeric values for the World variables you can use "-1" to indicate that the data is not available.
* If a list of responses is provided try to pick from the list, unless "Etc" is specified, which means it's open ended.
*/
private void CaptureVariable(OneOf<byte, Trigger> b)
{
// We could increment here based on having switched... Somehow?
// We need a better state tracking for this, to indicate the transition.
_currentVariable.Add(b.AsT0);
}

private void CaptureValue(OneOf<byte, Trigger> b)
{
// We could increment here based on having switched... Somehow?
// We need a better state tracking for this, to indicate the transition.
_currentVariable.Add(b.AsT0);
}

/// <summary>
/// Announce we do MSSP negotiation to the client.
/// </summary>
Expand Down
6 changes: 6 additions & 0 deletions TelnetNegotiationCore/Models/State.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ public enum State : sbyte
DontMSSP,
WontMSSP,
WillMSSP,
AlmostNegotiatingMSSP,
EvaluatingMSSPVar,
EvaluatingMSSPVal,
EscapingMSSPVar,
EscapingMSSPVal,
CompletingMSSP,
#endregion MSSP Negotiation
#region Window Size Negotiation
WillDoNAWS,
Expand Down

0 comments on commit 12da8b5

Please sign in to comment.