OSDP.Net 5.2.1
A .NET library for implementing the Open Supervised Device Protocol (OSDP)
Loading...
Searching...
No Matches
OutgoingMessage.cs
1using System;
4
5namespace OSDP.Net.Messages;
6
7internal class OutgoingMessage : Message
8{
9 private const int StartOfMessageLength = 5;
10
11 internal OutgoingMessage(byte address, Control controlBlock, PayloadData data)
12 {
13 Address = address;
14 ControlBlock = controlBlock;
15 PayloadData = data;
16 }
17
18 internal Control ControlBlock { get; }
19
20 internal byte Code => PayloadData.Code;
21
22 internal PayloadData PayloadData { get; }
23
24 internal byte[] BuildMessage(IMessageSecureChannel secureChannel)
25 {
26 var payload = PayloadData.BuildData();
27
28 var securityEstablished = secureChannel is { IsSecurityEstablished: true };
29
30 if (securityEstablished && payload.Length > 0)
31 {
32 payload = secureChannel.PadTheData(payload).ToArray();
33 }
34
35 bool isSecurityBlockPresent = securityEstablished || PayloadData.IsSecurityInitialization;
36 var securityBlock = isSecurityBlockPresent ? PayloadData.SecurityControlBlock() : Array.Empty<byte>();
37
38 int headerLength = StartOfMessageLength + securityBlock.Length + sizeof(ReplyType);
39 int totalLength = headerLength + payload.Length +
40 (ControlBlock.UseCrc ? 2 : 1) +
41 (securityEstablished ? MacSize : 0);
42 var buffer = new byte[totalLength];
43 int currentLength = 0;
44
45 buffer[currentLength++] = StartOfMessage;
46 buffer[currentLength++] = Address;
47 buffer[currentLength++] = (byte)(totalLength & 0xff);
48 buffer[currentLength++] = (byte)((totalLength >> 8) & 0xff);
49 buffer[currentLength++] = (byte)((ControlBlock.ControlByte & 0x07) | (isSecurityBlockPresent ? 0x08 : 0x00));
50
51 if (isSecurityBlockPresent)
52 {
53 securityBlock.CopyTo(buffer.AsSpan(currentLength));
54 currentLength += securityBlock.Length;
55 }
56
57 buffer[currentLength++] = PayloadData.Code;
58
59 if (securityEstablished)
60 {
61 secureChannel.EncodePayload(payload, buffer.AsSpan(currentLength));
62 currentLength += payload.Length;
63 secureChannel.GenerateMac(buffer.AsSpan(0, currentLength), false)
64 .Slice(0, MacSize)
65 .CopyTo(buffer.AsSpan(currentLength));
66 currentLength += MacSize;
67 }
68 else
69 {
70 payload.CopyTo(buffer, currentLength);
71 currentLength += payload.Length;
72 }
73
74 if (ControlBlock.UseCrc)
75 {
76 AddCrc(buffer);
77 currentLength += 2;
78 }
79 else
80 {
81 AddChecksum(buffer);
82 currentLength++;
83 }
84
85 if (currentLength != buffer.Length)
86 {
87 throw new Exception(
88 $"Invalid processing of reply data, expected length {currentLength}, actual length {buffer.Length}");
89 }
90
91 PayloadData.CustomMessageUpdate(buffer);
92
93 // Section 5.7 states that transmitting device shall guarantee an idle time between packets. This is
94 // accomplished by sending a character with all bits set to 1. The driver byte is required by
95 // converters and multiplexers to sense when line is idle.
96 var messageBuffer = new byte[buffer.Length + 1];
97 messageBuffer[0] = Bus.DriverByte;
98 Buffer.BlockCopy(buffer, 0, messageBuffer, 1, buffer.Length);
99
100 return messageBuffer;
101 }
102
103 protected override ReadOnlySpan<byte> Data()
104 {
105 return PayloadData.BuildData();
106 }
107}
108
109
110internal class OutgoingReply : OutgoingMessage
111{
112 internal OutgoingReply(IncomingMessage command, PayloadData replyPayload) :
113 base((byte)(command.Address | 0x80), command.ControlBlock, replyPayload)
114 {
115 Command = command;
116 }
117 internal IncomingMessage Command { get; }
118}
A base message class for sending or replying.
Definition Message.cs:12
const ushort MacSize
Size in bytes of MAC signature in message suffix when the secure channel has been established.
Definition Message.cs:32
static void AddChecksum(IList< byte > packet)
Adds the checksum to the packet.
Definition Message.cs:160
byte Address
Address assigned to the device.
Definition Message.cs:68
const byte StartOfMessage
OSDP message SOM (start of the message) byte.
Definition Message.cs:21
ReadOnlySpan< byte > Data()
The data.
byte Code
Gets the command or reply code byte value that represent the type of data.
ReadOnlySpan< byte > GenerateMac(ReadOnlySpan< byte > message, bool isIncoming)
Generates a new Message Authentication Code.
void EncodePayload(byte[] payload, Span< byte > destination)
Encrypts the payload using the secure channel context.
ReadOnlySpan< byte > PadTheData(ReadOnlySpan< byte > payload)
Pads the given data with padding bytes to make it a multiple of a specified length.
ReplyType
Identifies the type of OSDP protocol reply (PD -> ACU) message.
Definition ReplyType.cs:7