private void SendComplexAck(BacnetAddress adr, byte invoke_id, Segmentation segmentation, BacnetConfirmedServices service, Action<EncodeBuffer> apdu_content_encode)
{
Trace.WriteLine("Sending " + System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(service.ToString().ToLower()) + " ... ", null);
//encode
EncodeBuffer buffer;
if (EncodeSegment(adr, invoke_id, segmentation, service, out buffer, apdu_content_encode))
{
//client doesn't support segments
if (segmentation == null)
{
Trace.TraceInformation("Segmenation denied");
ErrorResponse(adr, service, invoke_id, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_APDU_TOO_LONG);
buffer.result = EncodeResult.Good; //don't continue the segmentation
return;
}
//first segment? validate max segments
if (segmentation.sequence_number == 0) //only validate first segment
{
if (segmentation.max_segments != 0xFF && segmentation.buffer.offset > (segmentation.max_segments * (GetMaxApdu() - 5))) //5 is adpu header
{
Trace.TraceInformation("Too much segmenation");
ErrorResponse(adr, service, invoke_id, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_APDU_TOO_LONG);
buffer.result = EncodeResult.Good; //don't continue the segmentation
return;
}
else
Trace.WriteLine("Segmentation required", null);
}
//increment before ack can do so (race condition)
unchecked { segmentation.sequence_number++; };
}
//send
m_client.Send(buffer.buffer, m_client.HeaderLength, buffer.GetLength() - m_client.HeaderLength, adr, false, 0);
}