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); }
protected void ProcessConfirmedServiceRequest(BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, BacnetMaxSegments max_segments, BacnetMaxAdpu max_adpu, byte invoke_id, byte[] buffer, int offset, int length) { try { Trace.WriteLine("ConfirmedServiceRequest", null); raw_buffer = buffer; raw_length = length; raw_offset = offset; if (OnConfirmedServiceRequest != null) OnConfirmedServiceRequest(this, adr, type, service, max_segments, max_adpu, invoke_id, buffer, offset, length); //don't send segmented messages, if client don't want it if ((type & BacnetPduTypes.SEGMENTED_RESPONSE_ACCEPTED) == 0) max_segments = BacnetMaxSegments.MAX_SEG0; if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROPERTY && OnReadPropertyRequest != null) { BacnetObjectId object_id; BacnetPropertyReference property; if (Services.DecodeReadProperty(buffer, offset, length, out object_id, out property) >= 0) OnReadPropertyRequest(this, adr, invoke_id, object_id, property, max_segments); else Trace.TraceWarning("Couldn't decode DecodeReadProperty"); } else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_WRITE_PROPERTY && OnWritePropertyRequest != null) { BacnetObjectId object_id; BacnetPropertyValue value; if (Services.DecodeWriteProperty(buffer, offset, length, out object_id, out value) >= 0) OnWritePropertyRequest(this, adr, invoke_id, object_id, value, max_segments); else Trace.TraceWarning("Couldn't decode DecodeWriteProperty"); } else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROP_MULTIPLE && OnReadPropertyMultipleRequest != null) { IList<BacnetReadAccessSpecification> properties; if (Services.DecodeReadPropertyMultiple(buffer, offset, length, out properties) >= 0) OnReadPropertyMultipleRequest(this, adr, invoke_id, properties, max_segments); else Trace.TraceWarning("Couldn't decode DecodeReadPropertyMultiple"); } else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE && OnWritePropertyMultipleRequest != null) { BacnetObjectId object_id; ICollection<BacnetPropertyValue> values; if (Services.DecodeWritePropertyMultiple(buffer, offset, length, out object_id, out values) >= 0) OnWritePropertyMultipleRequest(this, adr, invoke_id, object_id, values, max_segments); else Trace.TraceWarning("Couldn't decode DecodeWritePropertyMultiple"); } else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_COV_NOTIFICATION && OnCOVNotification != null) { uint subscriberProcessIdentifier; BacnetObjectId initiatingDeviceIdentifier; BacnetObjectId monitoredObjectIdentifier; uint timeRemaining; ICollection<BacnetPropertyValue> values; if (Services.DecodeCOVNotifyUnconfirmed(buffer, offset, length, out subscriberProcessIdentifier, out initiatingDeviceIdentifier, out monitoredObjectIdentifier, out timeRemaining, out values) >= 0) OnCOVNotification(this, adr, invoke_id, subscriberProcessIdentifier, initiatingDeviceIdentifier, monitoredObjectIdentifier, timeRemaining, true, values, max_segments); else Trace.TraceWarning("Couldn't decode COVNotify"); } else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_ATOMIC_WRITE_FILE && OnAtomicWriteFileRequest != null) { bool is_stream; BacnetObjectId object_id; int position; uint block_count; byte[][] blocks; int[] counts; if (Services.DecodeAtomicWriteFile(buffer, offset, length, out is_stream, out object_id, out position, out block_count, out blocks, out counts) >= 0) OnAtomicWriteFileRequest(this, adr, invoke_id, is_stream, object_id, position, block_count, blocks, counts, max_segments); else Trace.TraceWarning("Couldn't decode AtomicWriteFile"); } else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_ATOMIC_READ_FILE && OnAtomicReadFileRequest != null) { bool is_stream; BacnetObjectId object_id; int position; uint count; if (Services.DecodeAtomicReadFile(buffer, offset, length, out is_stream, out object_id, out position, out count) >= 0) OnAtomicReadFileRequest(this, adr, invoke_id, is_stream, object_id, position, count, max_segments); else Trace.TraceWarning("Couldn't decode AtomicReadFile"); } else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_SUBSCRIBE_COV && OnSubscribeCOV != null) { uint subscriberProcessIdentifier; BacnetObjectId monitoredObjectIdentifier; bool cancellationRequest; bool issueConfirmedNotifications; uint lifetime; if (Services.DecodeSubscribeCOV(buffer, offset, length, out subscriberProcessIdentifier, out monitoredObjectIdentifier, out cancellationRequest, out issueConfirmedNotifications, out lifetime) >= 0) OnSubscribeCOV(this, adr, invoke_id, subscriberProcessIdentifier, monitoredObjectIdentifier, cancellationRequest, issueConfirmedNotifications, lifetime, max_segments); else Trace.TraceWarning("Couldn't decode SubscribeCOV"); } else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_SUBSCRIBE_COV_PROPERTY && OnSubscribeCOVProperty != null) { uint subscriberProcessIdentifier; BacnetObjectId monitoredObjectIdentifier; BacnetPropertyReference monitoredProperty; bool cancellationRequest; bool issueConfirmedNotifications; uint lifetime; float covIncrement; if (Services.DecodeSubscribeProperty(buffer, offset, length, out subscriberProcessIdentifier, out monitoredObjectIdentifier, out monitoredProperty, out cancellationRequest, out issueConfirmedNotifications, out lifetime, out covIncrement) >= 0) OnSubscribeCOVProperty(this, adr, invoke_id, subscriberProcessIdentifier, monitoredObjectIdentifier, monitoredProperty, cancellationRequest, issueConfirmedNotifications, lifetime, covIncrement, max_segments); else Trace.TraceWarning("Couldn't decode SubscribeCOVProperty"); } else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL && OnDeviceCommunicationControl != null) { uint timeDuration; uint enable_disable; string password; if (Services.DecodeDeviceCommunicationControl(buffer, offset, length, out timeDuration, out enable_disable, out password) >= 0) OnDeviceCommunicationControl(this, adr, invoke_id, timeDuration, enable_disable, password, max_segments); else Trace.TraceWarning("Couldn't decode DeviceCommunicationControl"); } else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_REINITIALIZE_DEVICE && OnReinitializedDevice != null) { BacnetReinitializedStates state; string password; if (Services.DecodeReinitializeDevice(buffer, offset, length, out state, out password) >= 0) OnReinitializedDevice(this, adr, invoke_id, state, password, max_segments); else Trace.TraceWarning("Couldn't decode ReinitializeDevice"); } else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_EVENT_NOTIFICATION && OnEventNotify != null) // F. Chaxel { BacnetEventNotificationData EventData; if (Services.DecodeEventNotifyData(buffer, offset, length, out EventData) >= 0) { OnEventNotify(this, adr, EventData); } else Trace.TraceWarning("Couldn't decode Event/Alarm Notification"); } else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_READ_RANGE && OnReadRange != null) { BacnetObjectId objectId; BacnetPropertyReference property; BacnetReadRangeRequestTypes requestType; uint position; DateTime time; int count; if (Services.DecodeReadRange(buffer, offset, length, out objectId, out property, out requestType, out position, out time, out count) >= 0) { OnReadRange(this, adr, invoke_id, objectId, property, requestType, position, time, count, max_segments); } else Trace.TraceWarning("Couldn't decode ReadRange"); } else { Trace.TraceWarning("Confirmed service not handled: " + service.ToString()); } } catch (Exception ex) { Trace.TraceError("Error in ProcessConfirmedServiceRequest: " + ex.Message); } }