private static async void OnSubscriptionNotify(string server, ServiceEventMessage message) { #if DEBUG Console.WriteLine("Consumed OnSubscriptionNotify message"); Console.WriteLine("Server: " + server); Console.WriteLine("Message: " + message.ToString()); #endif string url = (string)message.Parameters["Url"]; string clientID = (string)message.Parameters["ClientID"]; Model.WebhookNotification notification = new Model.WebhookNotification(); MemoryStream stream = new MemoryStream(16384); new ServiceModels.WebhookNotification(notification, message).Serialise(stream); string payload = new StreamReader(stream).ReadToEnd(); bool retry = message.Parameters.ContainsKey("RequeueCount"); long requeueCount = retry ? (long)message.Parameters["RequeueCount"] : 0; bool dropMessage = false; #if DEBUG Console.WriteLine($"Sending payload to {url}: \n" + payload); #endif try { RESTClient.RESTResponse response = await RESTClient.PostAsync(url, ACCEPT_TYPE, null, notification.AcceptContentType, payload); switch ((HttpStatusCode)response.StatusCode) { case HttpStatusCode.OK: case HttpStatusCode.Created: ApplicationEventLog.Write(LogLevel.Information, $"Webhook post notification from client {clientID} to {url} successful."); break; case HttpStatusCode.BadRequest: case HttpStatusCode.Unauthorized: case HttpStatusCode.NotFound: case HttpStatusCode.MethodNotAllowed: // No retry for these failures ApplicationEventLog.Write(LogLevel.Warning, $"Non-recoverable HTTP Status code from{url}:{response.StatusCode}, discarding message."); dropMessage = true; break; default: ApplicationEventLog.Write(LogLevel.Warning, $"Unexpected HTTP Status code from{url}:{response.StatusCode}"); break; } } catch (Exception ex) { ApplicationEventLog.Write(LogLevel.Error, "Failed to post webhook", ex); } if ((MAX_POST_ATTEMPTS <= 0 || requeueCount < MAX_POST_ATTEMPTS) && !dropMessage) { BusinessLogicFactory.ServiceMessages.NackMessage(message); } }
private void ProcessUpdateRequest(Exchange exchange) { Request request = exchange.Request; Guid clientID; Response response; if (StringUtils.GuidTryDecode(request.UriPath.Substring(4), out clientID)) { LWM2MClient client = BusinessLogicFactory.Clients.GetClient(clientID); if (client == null) { response = Response.CreateResponse(request, StatusCode.NotFound); } else { client.Parse(request.UriQueries); BusinessLogicFactory.Clients.UpdateClientActivity(client); client.Address = request.Source; client.EndPoint = exchange.EndPoint; bool updatedLifeTime = false; if ((request.ContentType == (int)MediaType.ApplicationLinkFormat) || (request.ContentType == -1)) { if (request.PayloadSize > 0) { ObjectTypes objectTypes = new ObjectTypes(); objectTypes.Parse(request.PayloadString); if (ObjectTypes.Compare(client.SupportedTypes, objectTypes) != 0) { client.SupportedTypes = objectTypes; if (client.ClientID != Guid.Empty) { DataAccessFactory.Clients.SaveClient(client, TObjectState.Add); updatedLifeTime = true; } BusinessLogicFactory.Clients.ClientChangedSupportedTypes(client); } } } if (!updatedLifeTime) { BusinessLogicFactory.Clients.UpdateClientLifetime(client.ClientID, client.Lifetime); } response = Response.CreateResponse(request, StatusCode.Changed); ApplicationEventLog.Write(LogLevel.Information, string.Concat("Client update ", client.Name, " address ", client.Address.ToString())); } } else { ApplicationEventLog.WriteEntry(string.Concat("Invalid update location", request.UriPath)); response = Response.CreateResponse(request, StatusCode.BadRequest); } exchange.SendResponse(response); }
private static void Observe(Subscription subscription) { Client client = DataAccessFactory.Clients.GetClient(subscription.ClientID); if (client != null) { if (subscription.PropertyDefinitionID != Guid.Empty) { if (subscription.NotificationParameters != null) { if (DataAccessFactory.Servers.SetNotificationParameters(client, subscription.ObjectDefinitionID, subscription.ObjectID, subscription.PropertyDefinitionID, subscription.NotificationParameters)) { ApplicationEventLog.Write(LogLevel.Information, $"Updated notification parameters for resource /{subscription.ObjectDefinitionID}/{subscription.ObjectID}/{subscription.PropertyDefinitionID}"); } else { ApplicationEventLog.Write(LogLevel.Warning, $"Failed to update notification parameters for resource /{subscription.ObjectDefinitionID}/{subscription.ObjectID}/{subscription.PropertyDefinitionID}"); } } DataAccessFactory.Servers.ObserveResource(client, subscription.ObjectDefinitionID, subscription.ObjectID, subscription.PropertyDefinitionID); #if DEBUG ApplicationEventLog.Write(LogLevel.Information, $"Observing resource /{subscription.ObjectDefinitionID}/{subscription.ObjectID}/{subscription.PropertyDefinitionID}"); #endif } else if (subscription.ObjectID != null) { DataAccessFactory.Servers.ObserveObject(client, subscription.ObjectDefinitionID, subscription.ObjectID); #if DEBUG ApplicationEventLog.Write(LogLevel.Information, $"Observing object /{subscription.ObjectDefinitionID}/{subscription.ObjectID}"); #endif } else if (subscription.ObjectDefinitionID != Guid.Empty) { DataAccessFactory.Servers.ObserveObjects(client, subscription.ObjectDefinitionID); #if DEBUG ApplicationEventLog.Write(LogLevel.Information, $"Observing objects /{subscription.ObjectDefinitionID}"); #endif } else { ApplicationEventLog.Write(LogLevel.Warning, $"Subscription {subscription.SubscriptionID} has no definition ID"); } } else { ApplicationEventLog.Write(LogLevel.Warning, $"No client exists for {subscription.ClientID} in subscription {subscription.SubscriptionID}"); } }
public WebhookNotification(Model.WebhookNotification webhookNotification, ServiceEventMessage message) { _WebhookNotification = webhookNotification; _WebhookNotification.AcceptContentType = (string)message.Parameters["AcceptContentType"]; _WebhookNotification.SubscriptionID = (string)message.Parameters["SubscriptionID"]; _WebhookNotification.ClientID = (string)message.Parameters["ClientID"]; _WebhookNotification.SubscriptionType = (string)message.Parameters["SubscriptionType"]; _WebhookNotification.TimeTriggered = (DateTime)message.Parameters["TimeTriggered"]; if (message.Parameters.ContainsKey("Object")) { _WebhookNotification.ChangedObject = (Model.Object)message.Parameters["Object"]; _WebhookNotification.ObjectDefinition = DataAccessFactory.ObjectDefinitions.GetLookups().GetObjectDefinition(_WebhookNotification.ChangedObject.ObjectDefinitionID); if (_WebhookNotification.ObjectDefinition == null) { ApplicationEventLog.Write(LogLevel.Warning, $"Could not lookup object definition {_WebhookNotification.ChangedObject.ObjectDefinitionID}"); } } }
private static void OnDeleteSubscription(string server, ServiceEventMessage message) { #if DEBUG Console.WriteLine("Consumed delete subscription message"); Console.WriteLine("Server: " + server); Console.WriteLine("Message: " + message.ToString()); #endif Subscription subscription = GetSubscriptionFromMessage(message); if (subscription != null) { if (subscription.SubscriptionType == TSubscriptionType.Observation) { CancelObservation(subscription); } DataAccessFactory.Subscriptions.SaveSubscription(subscription, TObjectState.Delete); } else { ApplicationEventLog.Write(LogLevel.Warning, $"Failed to lookup subscription: {message.Parameters["SubscriptionID"]}"); } }
private static void OnUpdateSubscription(string server, ServiceEventMessage message) { #if DEBUG Console.WriteLine("Consumed update subscription message"); Console.WriteLine("Server: " + server); Console.WriteLine("Message: " + message.ToString()); #endif Subscription subscription = GetSubscriptionFromMessage(message); if (subscription != null) { if (subscription.SubscriptionType == TSubscriptionType.Observation) { if (subscription.NotificationParameters != null && subscription.PropertyDefinitionID != Guid.Empty) { Client client = DataAccessFactory.Clients.GetClient(subscription.ClientID); if (client != null) { if (DataAccessFactory.Servers.SetNotificationParameters(client, subscription.ObjectDefinitionID, subscription.ObjectID, subscription.PropertyDefinitionID, subscription.NotificationParameters)) { ApplicationEventLog.Write(LogLevel.Information, $"Updated notification parameters for resource /{subscription.ObjectDefinitionID}/{subscription.ObjectID}/{subscription.PropertyDefinitionID}"); } else { ApplicationEventLog.Write(LogLevel.Warning, $"Failed to update notification parameters for resource /{subscription.ObjectDefinitionID}/{subscription.ObjectID}/{subscription.PropertyDefinitionID}"); } } else { ApplicationEventLog.Write(LogLevel.Warning, $"No client exists for {subscription.ClientID} in subscription {subscription.SubscriptionID}"); } } } DataAccessFactory.Subscriptions.SaveSubscription(subscription, TObjectState.Update); } else { ApplicationEventLog.Write(LogLevel.Warning, $"Failed to lookup subscription: {message.Parameters["SubscriptionID"]}"); } }
private void _CheckDeadClientsTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { List <LWM2MClient> clientsToRemove = new List <LWM2MClient>(); try { ICollection <LWM2MClient> clients = _Clients.Values; foreach (LWM2MClient client in clients) { if (client.Lifetime < DateTime.UtcNow) { clientsToRemove.Add(client); } } } catch { } try { foreach (LWM2MClient item in clientsToRemove) { ApplicationEventLog.Write(LogLevel.Information, string.Concat("Client connection expired: ", item.Name, " address ", item.Address.ToString())); BusinessLogicFactory.Events.ClientConnectionExpired(item); LWM2MClient client; item.Cancel(); _Clients.TryRemove(item.ClientID, out client); if (item.ClientID != Guid.Empty) { _ClientByDeviceID.TryRemove(item.ClientID, out client); } } } catch { } }
private void ProcessDeregisterRequest(Exchange exchange) { Request request = exchange.Request; Guid clientID = StringUtils.GuidDecode(request.UriPath.Substring(4)); LWM2MClient client = BusinessLogicFactory.Clients.GetClient(clientID); Response response; if (client == null) { response = Response.CreateResponse(request, StatusCode.NotFound); } else { client.Lifetime = DateTime.UtcNow; BusinessLogicFactory.Clients.UpdateClientLifetime(client.ClientID, DateTime.UtcNow); BusinessLogicFactory.Clients.UpdateClientActivity(client.ClientID, DateTime.UtcNow); BusinessLogicFactory.Clients.DeleteClient(clientID); response = Response.CreateResponse(request, StatusCode.Deleted); ApplicationEventLog.Write(LogLevel.Information, string.Concat("Client deregister ", client.Name, " address ", client.Address.ToString())); } exchange.SendResponse(response); }
private static void CancelObservation(Subscription subscription) { Client client = DataAccessFactory.Clients.GetClient(subscription.ClientID); if (client != null) { if (subscription.PropertyDefinitionID != Guid.Empty) { DataAccessFactory.Servers.CancelObserveResource(client, subscription.ObjectDefinitionID, subscription.ObjectID, subscription.PropertyDefinitionID, false); #if DEBUG ApplicationEventLog.Write(LogLevel.Information, $"Cancelled observing resource /{subscription.ObjectDefinitionID}/{subscription.ObjectID}/{subscription.PropertyDefinitionID}"); #endif } else if (subscription.ObjectID != null) { DataAccessFactory.Servers.CancelObserveObject(client, subscription.ObjectDefinitionID, subscription.ObjectID, false); #if DEBUG ApplicationEventLog.Write(LogLevel.Information, $"Cancelled observing object /{subscription.ObjectDefinitionID}/{subscription.ObjectID}"); #endif } else if (subscription.ObjectDefinitionID != Guid.Empty) { DataAccessFactory.Servers.CancelObserveObjects(client, subscription.ObjectDefinitionID, false); #if DEBUG ApplicationEventLog.Write(LogLevel.Information, $"Cancelled observing objects /{subscription.ObjectDefinitionID}"); #endif } else { ApplicationEventLog.Write(LogLevel.Warning, $"Subscription {subscription.SubscriptionID} has no definition ID"); } } else { ApplicationEventLog.Write(LogLevel.Warning, $"No client exists for {subscription.ClientID} in subscription {subscription.SubscriptionID}"); } }
private static void OnCreateSubscription(string server, ServiceEventMessage message) { #if DEBUG Console.WriteLine("Consumed create subscription message"); Console.WriteLine("Server: " + server); Console.WriteLine("Message: " + message.ToString()); #endif Subscription subscription = GetSubscriptionFromMessage(message); if (subscription != null) { if (subscription.SubscriptionType == TSubscriptionType.Observation) { Observe(subscription); } else { // for server event types, we are already subscribed to RabbitMQ service messages. } } else { ApplicationEventLog.Write(LogLevel.Warning, $"Failed to lookup subscription: {message.Parameters["SubscriptionID"]}"); } }
private void ProcessRegisterRequest(Exchange exchange) { Request request = exchange.Request; LWM2MClient client = new LWM2MClient(); client.Server = _ServerEndPoint; client.Address = request.Source; client.Parse(request.UriQueries); ObjectTypes objectTypes = new ObjectTypes(); objectTypes.Parse(request.PayloadString); client.SupportedTypes = objectTypes; client.EndPoint = exchange.EndPoint; if (_SecureChannel != null) { CertificateInfo certificateInfo = _SecureChannel.GetClientCertificateInfo(client.Address); if (certificateInfo == null) { string pskIdentity = _SecureChannel.GetClientPSKIdentity(client.Address); if (!string.IsNullOrEmpty(pskIdentity)) { Guid clientID; PSKIdentity identity = DataAccessFactory.Identities.GetPSKIdentity(pskIdentity); if (identity != null) { if (StringUtils.GuidTryDecode(pskIdentity, out clientID)) { client.ClientID = clientID; } client.OrganisationID = identity.OrganisationID; } } } else { Console.WriteLine(certificateInfo.Subject.CommonName); Console.WriteLine(certificateInfo.Subject.Organistion); Guid clientID; if (Guid.TryParse(certificateInfo.Subject.CommonName, out clientID)) { client.ClientID = clientID; } int organisationID; if (int.TryParse(certificateInfo.Subject.Organistion, out organisationID)) { client.OrganisationID = organisationID; } } } if (client.ClientID != Guid.Empty && (client.OrganisationID > 0 || !SecureOnly) && !DataAccessFactory.Clients.IsBlacklisted(client.ClientID)) { BusinessLogicFactory.Clients.AddClient(client); } Response response = Response.CreateResponse(request, StatusCode.Created); //response.AddOption(Option.Create(OptionType.LocationPath, string.Concat("rd/",StringUtils.GuidEncode(client.ClientID)))); response.AddOption(Option.Create(OptionType.LocationPath, "rd")); response.AddOption(Option.Create(OptionType.LocationPath, StringUtils.GuidEncode(client.ClientID))); exchange.SendResponse(response); ApplicationEventLog.Write(LogLevel.Information, string.Concat("Client registered ", client.Name, " address ", client.Address.ToString())); }
public void SaveObjectProperty(Guid clientID, Guid objectDefinitionID, string instanceID, Property property, TObjectState state) { LWM2MClient client = BusinessLogicFactory.Clients.GetClient(clientID); if (client == null) { ApplicationEventLog.Write(LogLevel.Warning, string.Concat("SaveObject - Client not found ", clientID.ToString())); throw new NoLongerAvailableException("Device not connected"); } else { ObjectDefinitionLookups lookups = BusinessLogicFactory.Clients.GetLookups(); ObjectDefinition objectDefinition = lookups.GetObjectDefinition(objectDefinitionID); if (objectDefinition != null) { int objectID; if (int.TryParse(objectDefinition.ObjectID, out objectID)) { Model.ObjectType objectType = client.SupportedTypes.GetObjectType(objectID); if (objectType != null) { PropertyDefinition propertyDefinition = objectDefinition.GetProperty(property.PropertyDefinitionID); if (propertyDefinition != null) { byte[] payload = null; int contentType = TlvConstant.CONTENT_TYPE_TLV; if (state != TObjectState.Delete) { if ((property.Value != null) || (property.Values != null)) { if ((property.Value != null) && (LWM2MClient.DataFormat == MediaType.TextPlain)) { contentType = LWM2MClient.DataFormat; //contentType = TlvConstant.CONTENT_TYPE_PLAIN; string text = SerialiseProperty(propertyDefinition, property); if (text != null) { payload = Encoding.UTF8.GetBytes(text); } } else { Model.Object lwm2mObject = new Model.Object(); lwm2mObject.Properties.Add(property); payload = SerialiseObject(objectDefinition, lwm2mObject); } } } Request request = null; switch (state) { case TObjectState.NotChanged: break; case TObjectState.Add: request = client.NewPostRequest(objectType, instanceID, propertyDefinition.PropertyID, contentType, payload); break; case TObjectState.Update: request = client.NewPutRequest(objectType, instanceID, propertyDefinition.PropertyID, contentType, payload); break; case TObjectState.Delete: request = client.NewDeleteRequest(objectType, instanceID, propertyDefinition.PropertyID); break; default: break; } Response response = client.SendRequest(request).WaitForResponse(LWM2MClient.REQUEST_TIMEOUT); if (response == null) { throw new TimeoutException(); } else { BusinessLogicFactory.Clients.UpdateClientActivity(client); if (response.StatusCode != StatusCode.Changed) { throw new BadRequestException(); } } } } } } } }
public string SaveObject(Guid clientID, Model.Object item, TObjectState state) { string result = null; LWM2MClient client = BusinessLogicFactory.Clients.GetClient(clientID); if (client == null) { ApplicationEventLog.Write(LogLevel.Warning, string.Concat("SaveObject - Client not found ", clientID.ToString())); throw new NoLongerAvailableException("Device not connected"); } else { ObjectDefinitionLookups lookups = BusinessLogicFactory.Clients.GetLookups(); ObjectDefinition objectDefinition = lookups.GetObjectDefinition(item.ObjectDefinitionID); if (objectDefinition == null) { ApplicationEventLog.Write(LogLevel.Warning, string.Concat("SaveObject - Metadata not found ", item.ObjectDefinitionID.ToString(), " client ", client.Address.ToString())); } else { int objectID; if (int.TryParse(objectDefinition.ObjectID, out objectID)) { Model.ObjectType objectType = client.SupportedTypes.GetObjectType(objectID); if (objectType != null) { Request request = null; switch (state) { case TObjectState.NotChanged: break; case TObjectState.Add: ushort instanceID; if (ushort.TryParse(item.InstanceID, out instanceID)) { request = client.NewPostRequest(objectType, null, null, TlvConstant.CONTENT_TYPE_TLV, SerialiseObject(objectDefinition, item, instanceID)); } else { request = client.NewPostRequest(objectType, null, null, TlvConstant.CONTENT_TYPE_TLV, SerialiseObject(objectDefinition, item)); } break; case TObjectState.Update: request = client.NewPostRequest(objectType, item.InstanceID, null, TlvConstant.CONTENT_TYPE_TLV, SerialiseObject(objectDefinition, item)); break; case TObjectState.Delete: request = client.NewDeleteRequest(objectType, item.InstanceID, null); break; default: break; } ApplicationEventLog.Write(LogLevel.Information, string.Concat("SaveObject - Send request ", string.Concat(objectType.Path, "/", item.InstanceID), " client ", client.Address.ToString())); Response response = client.SendRequest(request).WaitForResponse(LWM2MClient.REQUEST_TIMEOUT); if (response == null) { throw new TimeoutException(); } else { BusinessLogicFactory.Clients.UpdateClientActivity(client); if (response.StatusCode == StatusCode.Created) { if (!string.IsNullOrEmpty(response.LocationPath) && (response.LocationPath.StartsWith(request.UriPath))) { int startIndex = request.UriPath.Length + 1; if (startIndex < response.LocationPath.Length) { result = response.LocationPath.Substring(startIndex); } } } else if (response.StatusCode == StatusCode.Changed) { } else if ((response.StatusCode == StatusCode.NotFound) && (state == TObjectState.Delete)) { } else { throw new BadRequestException(); } } } } } } return(result); }