public static void GetPdu(GXDLMSSettings settings,
GXReplyData data)
{
short ch;
Command cmd = data.Command;
// If header is not read yet or GBT message.
if (data.Command == Command.None || data.Gbt)
{
//If PDU is missing.
if (data.Data.Size - data.Data.Position == 0)
{
throw new InvalidOperationException("Invalid PDU.");
}
int index = data.Data.Position;
// Get command.
ch = data.Data.GetUInt8();
cmd = (Command)ch;
data.Command = cmd;
switch (cmd)
{
case Command.ReadResponse:
if (!HandleReadResponse(settings, data, index))
{
return;
}
break;
case Command.GetResponse:
if (!HandleGetResponse(settings, data, index))
{
return;
}
break;
case Command.SetResponse:
HandleSetResponse(settings, data);
break;
case Command.WriteResponse:
HandleWriteResponse(data);
break;
case Command.MethodResponse:
HandleMethodResponse(settings, data);
break;
case Command.AccessResponse:
HandleAccessResponse(settings, data);
break;
case Command.GeneralBlockTransfer:
HandleGbt(settings, data);
break;
case Command.Aarq:
case Command.Aare:
// This is parsed later.
--data.Data.Position;
break;
case Command.ReleaseResponse:
break;
case Command.ConfirmedServiceError:
HandleConfirmedServiceError(data);
break;
case Command.ExceptionResponse:
throw new GXDLMSException((ExceptionStateError)data.Data.GetUInt8(),
(ExceptionServiceError)data.Data.GetUInt8());
case Command.GetRequest:
case Command.ReadRequest:
case Command.WriteRequest:
case Command.SetRequest:
case Command.MethodRequest:
case Command.ReleaseRequest:
// Server handles this.
if ((data.MoreData & RequestTypes.Frame) != 0)
{
break;
}
break;
case Command.GloReadRequest:
case Command.GloWriteRequest:
case Command.GloGetRequest:
case Command.GloSetRequest:
case Command.GloMethodRequest:
if (settings.Cipher == null)
{
throw new Exception(
"Secure connection is not supported.");
}
//If all frames are read.
if ((data.MoreData & RequestTypes.Frame) == 0)
{
--data.Data.Position;
settings.Cipher.Decrypt(settings.SourceSystemTitle, data.Data);
// Get command.
ch = data.Data.GetUInt8();
cmd = (Command)ch;
data.Command = cmd;
}
else
{
--data.Data.Position;
}
// Server handles this.
break;
case Command.GloReadResponse:
case Command.GloWriteResponse:
case Command.GloGetResponse:
case Command.GloSetResponse:
case Command.GloMethodResponse:
if (settings.Cipher == null)
{
throw new Exception(
"Secure connection is not supported.");
}
//If all frames are read.
if ((data.MoreData & RequestTypes.Frame) == 0)
{
--data.Data.Position;
GXByteBuffer bb = new GXByteBuffer(data.Data);
data.Data.Position = data.Data.Size = index;
settings.Cipher.Decrypt(settings.SourceSystemTitle, bb);
data.Data.Set(bb);
data.Command = Command.None;
GetPdu(settings, data);
data.CipherIndex = data.Data.Size;
}
break;
case Command.DataNotification:
HandleDataNotification(settings, data);
//Client handles this.
break;
default:
throw new ArgumentException("Invalid Command.");
}
}
else if ((data.MoreData & RequestTypes.Frame) == 0)
{
// Is whole block is read and if last packet and data is not try to
// peek.
if (!data.Peek && data.MoreData == RequestTypes.None)
{
if (data.Command == Command.Aare || data.Command == Command.Aarq)
{
data.Data.Position = 0;
}
else
{
data.Data.Position = 1;
}
}
// Get command if operating as a server.
if (settings.IsServer)
{
//Ciphered messages are handled after whole PDU is received.
switch (cmd)
{
case Command.GloReadRequest:
case Command.GloWriteRequest:
case Command.GloGetRequest:
case Command.GloSetRequest:
case Command.GloMethodRequest:
data.Command = Command.None;
data.Data.Position = data.CipherIndex;
GetPdu(settings, data);
break;
default:
break;
}
}
else
{
//If we are receiving last read block in frames.
if (data.Command == Command.ReadResponse && !data.IsMoreData && data.CommandType == (byte)SingleReadResponse.DataBlockResult)
{
data.Data.Position = 0;
if (!HandleReadResponse(settings, data, -1))
{
return;
}
}
// Client do not need a command any more.
data.Command = Command.None;
//Ciphered messages are handled after whole PDU is received.
switch (cmd)
{
case Command.GloReadResponse:
case Command.GloWriteResponse:
case Command.GloGetResponse:
case Command.GloSetResponse:
case Command.GloMethodResponse:
data.Data.Position = data.CipherIndex;
GetPdu(settings, data);
break;
default:
break;
}
}
}
// Get data if all data is read or we want to peek data.
if (data.Xml == null && data.Data.Position != data.Data.Size &&
(cmd == Command.ReadResponse || cmd == Command.GetResponse)
&& (data.MoreData == RequestTypes.None || data.Peek))
{
GetValueFromData(settings, data);
}
}