internal static CpDataType CreateDataType(XPathNavigator dataTypeElementNav, IXmlNamespaceResolver nsmgr, DataTypeResolverDlgt dataTypeResolver) { string standardDataType = ParserHelper.SelectText(dataTypeElementNav, "text()", nsmgr); string extendedDataType = dataTypeElementNav.GetAttribute("type", string.Empty); if (string.IsNullOrEmpty(extendedDataType)) { // Standard data type UPnPStandardDataType type = UPnPStandardDataType.ParseStandardType(standardDataType); if (type == null) { throw new ArgumentException(string.Format("Invalid UPnP standard data type name '{0}'", standardDataType)); } return(new CpStandardDataType(type)); } else { // Extended data type if (standardDataType != "string") { throw new ArgumentException("UPnP extended data types need to yield a standard data type of 'string'"); } string schemaURI; string dataTypeName; if (!ParserHelper.TryParseDataTypeReference(extendedDataType, dataTypeElementNav, out schemaURI, out dataTypeName)) { throw new ArgumentException(string.Format("Unable to parse namespace URI of extended data type '{0}'", extendedDataType)); } UPnPExtendedDataType result; if (dataTypeResolver != null && dataTypeResolver(schemaURI + ":" + dataTypeName, out result)) { return(new CpExtendedDataType(result)); } return(new CpExtendedDataType(new ExtendedDataTypeDummy(schemaURI, dataTypeName))); } }
/// <summary> /// Creates a new <see cref="DeviceConnection"/> to the UPnP device contained in the given /// <paramref name="rootDescriptor"/> with the given <paramref name="deviceUuid"/>. /// </summary> /// <param name="controlPoint">Control point hosting the new device connection instance.</param> /// <param name="rootDescriptor">Root descriptor containing the description of the UPnP device to connect.</param> /// <param name="deviceUuid">UUID of the UPnP device to connect.</param> /// <param name="cpData">Shared control point data structure.</param> /// <param name="dataTypeResolver">Delegate method to resolve extended datatypes.</param> public DeviceConnection(UPnPControlPoint controlPoint, RootDescriptor rootDescriptor, string deviceUuid, CPData cpData, DataTypeResolverDlgt dataTypeResolver) { _controlPoint = controlPoint; _cpData = cpData; _rootDescriptor = rootDescriptor; _deviceUUID = deviceUuid; _genaClientController = new GENAClientController(_cpData, this, rootDescriptor.SSDPRootEntry.PreferredLink.Endpoint, rootDescriptor.SSDPRootEntry.UPnPVersion); BuildDeviceProxy(rootDescriptor, deviceUuid, dataTypeResolver); _genaClientController.Start(); }
internal static CpStateVariable ConnectStateVariable(DeviceConnection connection, CpService parentService, XPathNavigator svIt, IXmlNamespaceResolver nsmgr, DataTypeResolverDlgt dataTypeResolver) { string name = ParserHelper.SelectText(svIt, "s:name/text()", nsmgr); XPathNodeIterator dtIt = svIt.Select("s:dataType", nsmgr); if (!dtIt.MoveNext()) { throw new ArgumentException("Error evaluating data type element"); } CpDataType dataType = CpDataType.CreateDataType(dtIt.Current, nsmgr, dataTypeResolver); CpStateVariable result = new CpStateVariable(connection, parentService, name, dataType); XPathNodeIterator dvIt = svIt.Select("s:defaultValue", nsmgr); if (dvIt.MoveNext()) { XmlReader reader = dvIt.Current.ReadSubtree(); reader.MoveToContent(); result.DefaultValue = dataType.SoapDeserializeValue(reader, true); // Default value is always simple value (see DevArch) } XPathNodeIterator avlIt = svIt.Select("s:allowedValueList/s:allowedValue", nsmgr); if (avlIt.Count > 0) { IList <string> allowedValueList = new List <string>(); while (avlIt.MoveNext()) { allowedValueList.Add(ParserHelper.SelectText(avlIt.Current, "text()", null)); } result.AllowedValueList = allowedValueList; } XPathNodeIterator avrIt = svIt.Select("s:allowedValueRange", nsmgr); if (avrIt.MoveNext()) { result.AllowedValueRange = CpAllowedValueRange.CreateAllowedValueRange(avrIt.Current, nsmgr); } return(result); }
internal static CpService ConnectService(DeviceConnection connection, CpDevice parentDevice, ServiceDescriptor serviceDescriptor, DataTypeResolverDlgt dataTypeResolver) { lock (connection.CPData.SyncObj) { CpService result = new CpService(connection, parentDevice, serviceDescriptor.ServiceType, serviceDescriptor.ServiceTypeVersion, serviceDescriptor.ServiceId); XPathNavigator serviceNav = serviceDescriptor.ServiceDescription.CreateNavigator(); serviceNav.MoveToChild(XPathNodeType.Element); XmlNamespaceManager nsmgr = new XmlNamespaceManager(serviceNav.NameTable); nsmgr.AddNamespace("s", UPnPConsts.NS_SERVICE_DESCRIPTION); XPathNodeIterator svIt = serviceNav.Select("s:serviceStateTable/s:stateVariable", nsmgr); // State variables must be connected first because they are needed from the action's arguments while (svIt.MoveNext()) { result.AddStateVariable(CpStateVariable.ConnectStateVariable(connection, result, svIt.Current, nsmgr, dataTypeResolver)); } XPathNodeIterator acIt = serviceNav.Select("s:actionList/s:action", nsmgr); while (acIt.MoveNext()) { result.AddAction(CpAction.ConnectAction(connection, result, acIt.Current, nsmgr)); } return(result); } }
/// <summary> /// Establishes the actual device connection by building the control point's proxy device tree corresponding to the /// device contained in the given <paramref name="rootDescriptor"/> specified by its <paramref name="deviceUUID"/>. /// </summary> /// <param name="rootDescriptor">Root descriptor which contains the device to build.</param> /// <param name="deviceUUID">UUID of the device to connect.</param> /// <param name="dataTypeResolver">Delegate method to resolve extended datatypes.</param> private void BuildDeviceProxy(RootDescriptor rootDescriptor, string deviceUUID, DataTypeResolverDlgt dataTypeResolver) { if (rootDescriptor.State != RootDescriptorState.Ready) { throw new ArgumentException("Root descriptor is not ready - cannot connect"); } DeviceDescriptor rootDeviceDescriptor = DeviceDescriptor.CreateRootDeviceDescriptor(rootDescriptor); DeviceDescriptor deviceDescriptor = rootDeviceDescriptor.FindDevice(deviceUUID); _device = CpDevice.ConnectDevice(this, deviceDescriptor, dataTypeResolver); }
internal static CpDevice ConnectDevice(DeviceConnection connection, DeviceDescriptor deviceDescriptor, DataTypeResolverDlgt dataTypeResolver) { lock (connection.CPData.SyncObj) { string type; int version; if (!deviceDescriptor.GetTypeAndVersion(out type, out version)) throw new ArgumentException(string.Format("Invalid device type/version URN '{0}'", deviceDescriptor.TypeVersion_URN)); CpDevice result = new CpDevice(connection, type, version, deviceDescriptor.DeviceUUID); foreach (DeviceDescriptor childDevice in deviceDescriptor.ChildDevices) result.AddEmbeddedDevice(ConnectDevice(connection, childDevice, dataTypeResolver)); IDictionary<string, ServiceDescriptor> serviceDescriptors; if (deviceDescriptor.RootDescriptor.ServiceDescriptors.TryGetValue(deviceDescriptor.DeviceUUID, out serviceDescriptors)) foreach (ServiceDescriptor serviceDescriptor in serviceDescriptors.Values) if (serviceDescriptor.State == ServiceDescriptorState.Ready) result.AddService(CpService.ConnectService(connection, result, serviceDescriptor, dataTypeResolver)); else UPnPConfiguration.LOGGER.Warn("CpDevice.ConnectDevice: Unable to connect to service '{0}' (type '{1}', version '{2}') - the service descriptor was not initialized properly", serviceDescriptor.ServiceId, serviceDescriptor.ServiceType, serviceDescriptor.ServiceTypeVersion); return result; } }
/// <summary> /// Establishes the actual device connection by building the control point's proxy device tree corresponding to the /// device contained in the given <paramref name="rootDescriptor"/> specified by its <paramref name="deviceUUID"/>. /// </summary> /// <param name="rootDescriptor">Root descriptor which contains the device to build.</param> /// <param name="deviceUUID">UUID of the device to connect.</param> /// <param name="dataTypeResolver">Delegate method to resolve extended datatypes.</param> private void BuildDeviceProxy(RootDescriptor rootDescriptor, string deviceUUID, DataTypeResolverDlgt dataTypeResolver) { if (rootDescriptor.State != RootDescriptorState.Ready) throw new ArgumentException("Root descriptor is not ready - cannot connect"); DeviceDescriptor rootDeviceDescriptor = DeviceDescriptor.CreateRootDeviceDescriptor(rootDescriptor); DeviceDescriptor deviceDescriptor = rootDeviceDescriptor.FindDevice(deviceUUID); _device = CpDevice.ConnectDevice(this, deviceDescriptor, dataTypeResolver); }
internal static CpStateVariable ConnectStateVariable(DeviceConnection connection, CpService parentService, XPathNavigator svIt, IXmlNamespaceResolver nsmgr, DataTypeResolverDlgt dataTypeResolver) { string name = ParserHelper.SelectText(svIt, "s:name/text()", nsmgr); XPathNodeIterator dtIt = svIt.Select("s:dataType", nsmgr); if (!dtIt.MoveNext()) throw new ArgumentException("Error evaluating data type element"); CpDataType dataType = CpDataType.CreateDataType(dtIt.Current, nsmgr, dataTypeResolver); CpStateVariable result = new CpStateVariable(connection, parentService, name, dataType); XPathNodeIterator dvIt = svIt.Select("s:defaultValue", nsmgr); if (dvIt.MoveNext()) { XmlReader reader = dvIt.Current.ReadSubtree(); reader.MoveToContent(); result.DefaultValue = dataType.SoapDeserializeValue(reader, true); // Default value is always simple value (see DevArch) } XPathNodeIterator avlIt = svIt.Select("s:allowedValueList/s:allowedValue", nsmgr); if (avlIt.Count > 0) { IList<string> allowedValueList = new List<string>(); while (avlIt.MoveNext()) allowedValueList.Add(ParserHelper.SelectText(avlIt.Current, "text()", null)); result.AllowedValueList = allowedValueList; } XPathNodeIterator avrIt = svIt.Select("s:allowedValueRange", nsmgr); if (avrIt.MoveNext()) result.AllowedValueRange = CpAllowedValueRange.CreateAllowedValueRange(avrIt.Current, nsmgr); return result; }
protected DeviceConnection DoConnect(RootDescriptor descriptor, string deviceUuid, DataTypeResolverDlgt dataTypeResolver, bool useHttpKeepAlive = true) { lock (_cpData.SyncObj) { DeviceConnection connection = new DeviceConnection(this, descriptor, deviceUuid, _cpData, dataTypeResolver, useHttpKeepAlive); _connectedDevices.Add(deviceUuid, connection); return connection; } }
/// <summary> /// Connects to the device of the given <paramref name="deviceUuid"/> specified in the <paramref name="rootDescriptor"/>. /// </summary> /// <param name="rootDescriptor">UPnP root descriptor to connect.</param> /// <param name="deviceUuid">UUID of the device in the root descriptor which is the node to connect.</param> /// <param name="dataTypeResolver">Delegate method to resolve extended datatypes.</param> /// <param name="useHttpKeepAlive"><c>True</c> to set the HTTP keep-alive header in action requests sent over the connection, otherwise <c>false</c>.</param> /// <exception cref="ArgumentException"> /// <list type="bullet"> /// <item>If the device with the specified <paramref name="deviceUuid"/> isn't present /// in the given <paramref name="rootDescriptor"/></item> /// <item>If the given <paramref name="rootDescriptor"/> has is in an erroneous state /// (<c><see cref="RootDescriptor.State"/> == <see cref="RootDescriptorState.Erroneous"/></c>)</item> /// <item>If the given <paramref name="rootDescriptor"/> contains erroneous data, e.g. erroneous device or /// service descriptions</item> /// </list> /// </exception> public DeviceConnection Connect(RootDescriptor rootDescriptor, string deviceUuid, DataTypeResolverDlgt dataTypeResolver, bool useHttpKeepAlive = true) { return DoConnect(rootDescriptor, deviceUuid, dataTypeResolver, useHttpKeepAlive); }
protected DeviceConnection DoConnect(RootDescriptor descriptor, string deviceUuid, DataTypeResolverDlgt dataTypeResolver, bool useHttpKeepAlive = true) { lock (_cpData.SyncObj) { DeviceConnection connection = new DeviceConnection(this, descriptor, deviceUuid, _cpData, dataTypeResolver, useHttpKeepAlive); _connectedDevices.Add(deviceUuid, connection); return(connection); } }
/// <summary> /// Connects to the device of the given <paramref name="deviceUuid"/> specified in the <paramref name="rootDescriptor"/>. /// </summary> /// <param name="rootDescriptor">UPnP root descriptor to connect.</param> /// <param name="deviceUuid">UUID of the device in the root descriptor which is the node to connect.</param> /// <param name="dataTypeResolver">Delegate method to resolve extended datatypes.</param> /// <param name="useHttpKeepAlive"><c>True</c> to set the HTTP keep-alive header in action requests sent over the connection, otherwise <c>false</c>.</param> /// <exception cref="ArgumentException"> /// <list type="bullet"> /// <item>If the device with the specified <paramref name="deviceUuid"/> isn't present /// in the given <paramref name="rootDescriptor"/></item> /// <item>If the given <paramref name="rootDescriptor"/> has is in an erroneous state /// (<c><see cref="RootDescriptor.State"/> == <see cref="RootDescriptorState.Erroneous"/></c>)</item> /// <item>If the given <paramref name="rootDescriptor"/> contains erroneous data, e.g. erroneous device or /// service descriptions</item> /// </list> /// </exception> public DeviceConnection Connect(RootDescriptor rootDescriptor, string deviceUuid, DataTypeResolverDlgt dataTypeResolver, bool useHttpKeepAlive = true) { return(DoConnect(rootDescriptor, deviceUuid, dataTypeResolver, useHttpKeepAlive)); }
internal static CpService ConnectService(DeviceConnection connection, CpDevice parentDevice, ServiceDescriptor serviceDescriptor, DataTypeResolverDlgt dataTypeResolver) { lock (connection.CPData.SyncObj) { CpService result = new CpService(connection, parentDevice, serviceDescriptor.ServiceType, serviceDescriptor.ServiceTypeVersion, serviceDescriptor.ServiceId); XPathNavigator serviceNav = serviceDescriptor.ServiceDescription.CreateNavigator(); serviceNav.MoveToChild(XPathNodeType.Element); XmlNamespaceManager nsmgr = new XmlNamespaceManager(serviceNav.NameTable); nsmgr.AddNamespace("s", UPnPConsts.NS_SERVICE_DESCRIPTION); XPathNodeIterator svIt = serviceNav.Select("s:serviceStateTable/s:stateVariable", nsmgr); // State variables must be connected first because they are needed from the action's arguments while (svIt.MoveNext()) result.AddStateVariable(CpStateVariable.ConnectStateVariable(connection, result, svIt.Current, nsmgr, dataTypeResolver)); XPathNodeIterator acIt = serviceNav.Select("s:actionList/s:action", nsmgr); while (acIt.MoveNext()) result.AddAction(CpAction.ConnectAction(connection, result, acIt.Current, nsmgr)); return result; } }
/// <summary> /// Connects to the device of the given <paramref name="deviceUuid"/> specified in the <paramref name="rootDescriptor"/>. /// </summary> /// <param name="rootDescriptor">UPnP root descriptor to connect.</param> /// <param name="deviceUuid">UUID of the device in the root descriptor which is the node to connect.</param> /// <param name="dataTypeResolver">Delegate method to resolve extended datatypes.</param> /// <exception cref="ArgumentException"> /// <list type="bullet"> /// <item>If the device with the specified <paramref name="deviceUuid"/> isn't present /// in the given <paramref name="rootDescriptor"/></item> /// <item>If the given <paramref name="rootDescriptor"/> has is in an erroneous state /// (<c><see cref="RootDescriptor.State"/> == <see cref="RootDescriptorState.Erroneous"/></c>)</item> /// <item>If the given <paramref name="rootDescriptor"/> contains erroneous data, e.g. erroneous device or /// service descriptions</item> /// </list> /// </exception> public DeviceConnection Connect(RootDescriptor rootDescriptor, string deviceUuid, DataTypeResolverDlgt dataTypeResolver) { return(DoConnect(rootDescriptor, deviceUuid, dataTypeResolver)); }
internal static CpDataType CreateDataType(XPathNavigator dataTypeElementNav, IXmlNamespaceResolver nsmgr, DataTypeResolverDlgt dataTypeResolver) { string standardDataType = ParserHelper.SelectText(dataTypeElementNav, "text()", nsmgr); string extendedDataType = dataTypeElementNav.GetAttribute("type", string.Empty); if (string.IsNullOrEmpty(extendedDataType)) { // Standard data type UPnPStandardDataType type = UPnPStandardDataType.ParseStandardType(standardDataType); if (type == null) throw new ArgumentException(string.Format("Invalid UPnP standard data type name '{0}'", standardDataType)); return new CpStandardDataType(type); } else { // Extended data type if (standardDataType != "string") throw new ArgumentException("UPnP extended data types need to yield a standard data type of 'string'"); string schemaURI; string dataTypeName; if (!ParserHelper.TryParseDataTypeReference(extendedDataType, dataTypeElementNav, out schemaURI, out dataTypeName)) throw new ArgumentException(string.Format("Unable to parse namespace URI of extended data type '{0}'", extendedDataType)); UPnPExtendedDataType result; if (dataTypeResolver != null && dataTypeResolver(schemaURI + ":" + dataTypeName, out result)) return new CpExtendedDataType(result); return new CpExtendedDataType(new ExtendedDataTypeDummy(schemaURI, dataTypeName)); } }
/// <summary> /// Creates a new <see cref="DeviceConnection"/> to the UPnP device contained in the given /// <paramref name="rootDescriptor"/> with the given <paramref name="deviceUuid"/>. /// </summary> /// <param name="controlPoint">Control point hosting the new device connection instance.</param> /// <param name="rootDescriptor">Root descriptor containing the description of the UPnP device to connect.</param> /// <param name="deviceUuid">UUID of the UPnP device to connect.</param> /// <param name="cpData">Shared control point data structure.</param> /// <param name="dataTypeResolver">Delegate method to resolve extended datatypes.</param> /// <param name="useHttpKeepAlive"><c>True</c> to set the HTTP keep-alive header in action requests sent over the connection, otherwise <c>false</c>.</param> public DeviceConnection(UPnPControlPoint controlPoint, RootDescriptor rootDescriptor, string deviceUuid, CPData cpData, DataTypeResolverDlgt dataTypeResolver, bool useHttpKeepAlive = true) { _controlPoint = controlPoint; _cpData = cpData; _rootDescriptor = rootDescriptor; _deviceUUID = deviceUuid; _useHttpKeepAlive = useHttpKeepAlive; _genaClientController = new GENAClientController(_cpData, this, rootDescriptor.SSDPRootEntry.PreferredLink.Endpoint, rootDescriptor.SSDPRootEntry.UPnPVersion); BuildDeviceProxy(rootDescriptor, deviceUuid, dataTypeResolver); _genaClientController.Start(); }
internal static CpDevice ConnectDevice(DeviceConnection connection, DeviceDescriptor deviceDescriptor, DataTypeResolverDlgt dataTypeResolver) { lock (connection.CPData.SyncObj) { string type; int version; if (!deviceDescriptor.GetTypeAndVersion(out type, out version)) { throw new ArgumentException(string.Format("Invalid device type/version URN '{0}'", deviceDescriptor.TypeVersion_URN)); } CpDevice result = new CpDevice(connection, type, version, deviceDescriptor.DeviceUUID); foreach (DeviceDescriptor childDevice in deviceDescriptor.ChildDevices) { result.AddEmbeddedDevice(ConnectDevice(connection, childDevice, dataTypeResolver)); } IDictionary <string, ServiceDescriptor> serviceDescriptors; if (deviceDescriptor.RootDescriptor.ServiceDescriptors.TryGetValue(deviceDescriptor.DeviceUUID, out serviceDescriptors)) { foreach (ServiceDescriptor serviceDescriptor in serviceDescriptors.Values) { if (serviceDescriptor.State == ServiceDescriptorState.Ready) { result.AddService(CpService.ConnectService(connection, result, serviceDescriptor, dataTypeResolver)); } else { UPnPConfiguration.LOGGER.Warn("CpDevice.ConnectDevice: Unable to connect to service '{0}' (type '{1}', version '{2}') - the service descriptor was not initialized properly", serviceDescriptor.ServiceId, serviceDescriptor.ServiceType, serviceDescriptor.ServiceTypeVersion); } } } return(result); } }
/// <summary> /// Connects to the device of the given <paramref name="deviceUuid"/> specified in the <paramref name="rootDescriptor"/>. /// </summary> /// <param name="rootDescriptor">UPnP root descriptor to connect.</param> /// <param name="deviceUuid">UUID of the device in the root descriptor which is the node to connect.</param> /// <param name="dataTypeResolver">Delegate method to resolve extended datatypes.</param> /// <exception cref="ArgumentException"> /// <list type="bullet"> /// <item>If the device with the specified <paramref name="deviceUuid"/> isn't present /// in the given <paramref name="rootDescriptor"/></item> /// <item>If the given <paramref name="rootDescriptor"/> has is in an erroneous state /// (<c><see cref="RootDescriptor.State"/> == <see cref="RootDescriptorState.Erroneous"/></c>)</item> /// <item>If the given <paramref name="rootDescriptor"/> contains erroneous data, e.g. erroneous device or /// service descriptions</item> /// </list> /// </exception> public DeviceConnection Connect(RootDescriptor rootDescriptor, string deviceUuid, DataTypeResolverDlgt dataTypeResolver) { return DoConnect(rootDescriptor, deviceUuid, dataTypeResolver); }