static internal WsaQuerySet MarshalWsaQuerySetNativeToWsaQuerySet(IntPtr pNativeData, uint scopeId) { if (pNativeData == IntPtr.Zero) return null; WsaQuerySet querySet = new WsaQuerySet(); // build a native structure from the raw memory WsaQuerySetNative nativeQuerySet; nativeQuerySet = (WsaQuerySetNative)Marshal.PtrToStructure(pNativeData, typeof(WsaQuerySetNative)); CsAddrInfoNative nativeCsAddrInfo; int sizeOfCsAddrInfo = Marshal.SizeOf(typeof(CsAddrInfoNative)); // copy over the simple fields querySet.Context = Marshal.PtrToStringUni(nativeQuerySet.lpszContext); querySet.NameSpace = nativeQuerySet.dwNameSpace; querySet.ServiceInstanceName = Marshal.PtrToStringUni(nativeQuerySet.lpszServiceInstanceName); querySet.Comment = Marshal.PtrToStringUni(nativeQuerySet.lpszComment); // copy the addresses querySet.CsAddrInfos = new CsAddrInfo[nativeQuerySet.dwNumberOfCsAddrs]; for (int i = 0; i < nativeQuerySet.dwNumberOfCsAddrs; i++) { IntPtr addressPtr = (IntPtr)(nativeQuerySet.lpcsaBuffer.ToInt64() + (i * sizeOfCsAddrInfo)); nativeCsAddrInfo = (CsAddrInfoNative)Marshal.PtrToStructure(addressPtr, typeof(CsAddrInfoNative)); querySet.CsAddrInfos[i].iProtocol = nativeCsAddrInfo.iProtocol; querySet.CsAddrInfos[i].iSocketType = nativeCsAddrInfo.iSocketType; querySet.CsAddrInfos[i].LocalAddr = IPEndPointFromSocketAddress(nativeCsAddrInfo.LocalAddr, scopeId); querySet.CsAddrInfos[i].RemoteAddr = IPEndPointFromSocketAddress(nativeCsAddrInfo.RemoteAddr, scopeId); } // copy the GUIDs if (nativeQuerySet.lpNSProviderId != IntPtr.Zero) querySet.NSProviderId = (Guid)Marshal.PtrToStructure(nativeQuerySet.lpNSProviderId, typeof(Guid)); if (nativeQuerySet.lpServiceClassId != IntPtr.Zero) querySet.ServiceClassId = (Guid)Marshal.PtrToStructure(nativeQuerySet.lpServiceClassId, typeof(Guid)); // marshal the BLOB according to namespace if (querySet.NameSpace == NspNamespaces.Cloud) { if (nativeQuerySet.lpBlob != IntPtr.Zero) { // give it a default value querySet.Blob = new PnrpCloudInfo(); // marshal the blob in order to get the pointer BlobNative blob = (BlobNative)Marshal.PtrToStructure(nativeQuerySet.lpBlob, typeof(BlobNative)); // marshal the actual PnrpCloudInfo if (blob.pBlobData != IntPtr.Zero) querySet.Blob = (PnrpCloudInfo)Marshal.PtrToStructure(blob.pBlobData, typeof(PnrpCloudInfo)); } } else if (querySet.NameSpace == NspNamespaces.Name) { if (nativeQuerySet.lpBlob != IntPtr.Zero) { // give it a default value querySet.Blob = new PnrpInfo(); // marshal the blob in order to get the pointer BlobSafe blob = (BlobSafe)Marshal.PtrToStructure(nativeQuerySet.lpBlob, typeof(BlobSafe)); // marshal the actual PnrpInfo if (blob.pBlobData != IntPtr.Zero) { PnrpInfo pnrpInfo = (PnrpInfo)Marshal.PtrToStructure(blob.pBlobData, typeof(PnrpInfo)); querySet.Blob = pnrpInfo; } } } return querySet; }
public static extern int WSALookupServiceBegin( WsaQuerySet qsRestrictions, WasLookupControlOptions dwControlControlOptions, ref IntPtr lphLookup);
public PeerNameResolver(string peerName, int numberOfResultsRequested, PnrpResolveCriteria resolveCriteria, uint scopeId, string cloudName, TimeSpan timeout, List<PnrpRegistration> results) : base(null, null) { // pnrp has a hard-coded limit on the timeout value that can be passed to it // maximum value is 10 minutes if (timeout > MaxTimeout) { timeout = MaxTimeout; } timeoutHelper = new TimeoutHelper(timeout); PnrpInfo resolveQueryInfo = new PnrpInfo(); resolveQueryInfo.dwSize = Marshal.SizeOf(typeof(PnrpInfo)); resolveQueryInfo.nMaxResolve = numberOfResultsRequested; resolveQueryInfo.dwTimeout = (int)timeout.TotalSeconds; resolveQueryInfo.dwLifetime = 0; resolveQueryInfo.enNameState = 0; resolveQueryInfo.lpwszIdentity = null; resolveQueryInfo.dwFlags = PNRPINFO_HINT; IPEndPoint hint = PnrpPeerResolver.GetHint(); resolveQueryInfo.enResolveCriteria = resolveCriteria; resolveQueryInfo.saHint = SOCKET_ADDRESS_SAFE.SocketAddressFromIPEndPoint(hint); resolveQuery = new WsaQuerySet(); resolveQuery.ServiceInstanceName = peerName; resolveQuery.ServiceClassId = SvcIdNameV1; resolveQuery.NameSpace = NspNamespaces.Name; resolveQuery.NSProviderId = NsProviderName; resolveQuery.Context = cloudName; resolveQuery.Blob = resolveQueryInfo; this.results = results; this.scopeId = scopeId; ActionItem.Schedule(new Action<object>(SyncEnumeration), null); }
public void SyncEnumeration(object state) { int retval = 0; CriticalLookupHandle hLookup; WsaQuerySetSafe native = WsaQuerySet.ToWsaQuerySetSafe(resolveQuery); using (native) { CriticalAllocHandle handle = CriticalAllocHandleWsaQuerySetSafe.FromWsaQuerySetSafe(native); retval = WSALookupServiceBegin(handle, WsaNspControlFlags.ReturnAll, out hLookup); } if (retval != 0) { lastException = new PnrpException(WSAGetLastError(), resolveQuery.Context); Utility.CloseInvalidOutCriticalHandle(hLookup); Complete(false, lastException); return; } WsaQuerySet querySet = new WsaQuerySet(); // start with a sensible default size int size = Marshal.SizeOf(typeof(WsaQuerySetSafe)) + 400; CriticalAllocHandle nativeQuerySetPtr = CriticalAllocHandle.FromSize(size); try { using (hLookup) { while (true) { if (timeoutHelper.RemainingTime() == TimeSpan.Zero) { break; } retval = WSALookupServiceNext(hLookup, 0, ref size, (IntPtr)nativeQuerySetPtr); if (retval != 0) { int error = WSAGetLastError(); if (error == (int)WsaError.WSAENOMORE || error == (int)WsaError.WSA_E_NO_MORE) { // no more break; } if (error == (int)WsaError.WSAEFAULT) { nativeQuerySetPtr = CriticalAllocHandle.FromSize(size); continue; } // unexpected error PeerExceptionHelper.ThrowPnrpError(error, querySet.Context); } else { if (nativeQuerySetPtr != IntPtr.Zero) { // marshal the results into something useful querySet = MarshalWsaQuerySetNativeToWsaQuerySet(nativeQuerySetPtr, scopeId); // allocate the friendly PnrpRegistration and fill it in PnrpRegistration pnrpRegistration = new PnrpRegistration(); pnrpRegistration.CloudName = querySet.Context; pnrpRegistration.Comment = querySet.Comment; pnrpRegistration.PeerName = querySet.ServiceInstanceName; pnrpRegistration.Addresses = new IPEndPoint[querySet.CsAddrInfos.Length]; for (int i = 0; i < querySet.CsAddrInfos.Length; i++) pnrpRegistration.Addresses[i] = querySet.CsAddrInfos[i].LocalAddr; // add it to the list to return later. // all cloud enumeratos in the same scope will reference the same list and hence the lock. lock (results) { results.Add(pnrpRegistration); } } } } } } catch (Exception e) { if (Fx.IsFatal(e)) throw; DiagnosticUtility.TraceHandledException(e, TraceEventType.Information); if (DiagnosticUtility.ShouldTraceInformation) { PnrpResolveExceptionTraceRecord record = new PnrpResolveExceptionTraceRecord(resolveQuery.ServiceInstanceName, resolveQuery.Context, e); if (DiagnosticUtility.ShouldTraceError) { TraceUtility.TraceEvent(TraceEventType.Error, TraceCode.PnrpResolveException, SR.GetString(SR.TraceCodePnrpResolveException), record, this, null); } } lastException = e; } finally { Complete(false, lastException); } }
void DeleteService(WsaQuerySet registerQuery) { InvokeService(registerQuery, WsaSetServiceOp.Delete, 0); }
static void InvokeService(WsaQuerySet registerQuery, WsaSetServiceOp op, int flags) { WsaQuerySetSafe native = WsaQuerySet.ToWsaQuerySetSafe(registerQuery); using (native) { CriticalAllocHandle handle = CriticalAllocHandleWsaQuerySetSafe.FromWsaQuerySetSafe(native); int retval = WSASetService(handle, op, flags); if (retval != 0) { int error = WSAGetLastError(); PeerExceptionHelper.ThrowPnrpError(error, registerQuery.Context); } } }
public void Unregister(string peerName, string cloudName, TimeSpan timeout) { // fill in the PnrpInfo with defaults PnrpInfo identityInfo = new PnrpInfo(); identityInfo.lpwszIdentity = null; identityInfo.dwSize = Marshal.SizeOf(typeof(PnrpInfo)); // fill in the query set WsaQuerySet registerQuery = new WsaQuerySet(); registerQuery.NameSpace = NspNamespaces.Name; registerQuery.NSProviderId = NsProviderName; registerQuery.ServiceClassId = SvcIdNameV1; registerQuery.ServiceInstanceName = peerName; registerQuery.Context = cloudName; registerQuery.Blob = identityInfo; DeleteService(registerQuery); }
void RegisterService(WsaQuerySet registerQuery) { try { InvokeService(registerQuery, WsaSetServiceOp.Register, 0); } catch (PnrpException) { if (PnrpPeerResolver.MaxAddressEntriesV1 < registerQuery.CsAddrInfos.Length) { List<CsAddrInfo> infos = new List<CsAddrInfo>(registerQuery.CsAddrInfos); infos.RemoveRange(PnrpPeerResolver.MaxAddressEntriesV1, registerQuery.CsAddrInfos.Length - PnrpPeerResolver.MaxAddressEntriesV1); registerQuery.CsAddrInfos = infos.ToArray(); InvokeService(registerQuery, WsaSetServiceOp.Register, 0); } else throw; } }
public void Register(PnrpRegistration registration, TimeSpan timeout) { // fill in the PnrpInfo blob using the defaults PnrpInfo pnrpInfo = new PnrpInfo(); pnrpInfo.dwLifetime = RegistrationLifetime; pnrpInfo.lpwszIdentity = null; pnrpInfo.dwSize = Marshal.SizeOf(pnrpInfo); pnrpInfo.dwFlags = PNRPINFO_HINT; IPEndPoint hint = PnrpPeerResolver.GetHint(); pnrpInfo.saHint = SOCKET_ADDRESS_SAFE.SocketAddressFromIPEndPoint(hint); // fill in the query set WsaQuerySet registerQuery = new WsaQuerySet(); registerQuery.NameSpace = NspNamespaces.Name; registerQuery.NSProviderId = NsProviderName; registerQuery.ServiceClassId = SvcIdNameV1; registerQuery.ServiceInstanceName = registration.PeerName; registerQuery.Comment = registration.Comment; registerQuery.Context = registration.CloudName; // copy over the addresses if (registration.Addresses != null) { Fx.Assert(registration.Addresses.Length <= 4, "Pnrp supports only 4 addresses"); registerQuery.CsAddrInfos = new CsAddrInfo[registration.Addresses.Length]; for (int i = 0; i < registration.Addresses.Length; i++) { // the only interesting part of the CsAddrInfo is the LocalAddress registerQuery.CsAddrInfos[i].LocalAddr = registration.Addresses[i]; registerQuery.CsAddrInfos[i].iProtocol = (int)ProtocolType.Tcp; registerQuery.CsAddrInfos[i].iSocketType = (int)SocketType.Stream; } } // copy the blob registerQuery.Blob = pnrpInfo; RegisterService(registerQuery); }
static public CloudInfo[] GetClouds() { int retval = 0; ArrayList clouds = new ArrayList(); WsaQuerySet querySet = new WsaQuerySet(); CriticalLookupHandle hLookup; PnrpCloudInfo cloudInfo = new PnrpCloudInfo(); cloudInfo.dwSize = Marshal.SizeOf(typeof(PnrpCloudInfo)); cloudInfo.Cloud.Scope = PnrpScope.Any; cloudInfo.dwCloudState = (PnrpCloudState)0; cloudInfo.Flags = PnrpCloudFlags.None; querySet.NameSpace = NspNamespaces.Cloud; querySet.NSProviderId = NsProviderCloud; querySet.ServiceClassId = SvcIdCloud; querySet.Blob = cloudInfo; WsaQuerySetSafe native = WsaQuerySet.ToWsaQuerySetSafe(querySet); using (native) { CriticalAllocHandle handle = CriticalAllocHandleWsaQuerySetSafe.FromWsaQuerySetSafe(native); retval = WSALookupServiceBegin(handle, WsaNspControlFlags.ReturnAll, out hLookup); } if (retval != 0) { // unable to start the enumeration SocketException exception = new SocketException(WSAGetLastError()); Utility.CloseInvalidOutCriticalHandle(hLookup); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception); } // start with a sensible default size int size = Marshal.SizeOf(typeof(WsaQuerySetSafe)) + 200; //wrap in CriticalAllocHandle when PAYLOAD is enabled CriticalAllocHandle nativeQuerySetPtr = CriticalAllocHandle.FromSize(size); using (hLookup) { while (true) { retval = WSALookupServiceNext(hLookup, 0, ref size, (IntPtr)nativeQuerySetPtr); if (retval != 0) { int error = WSAGetLastError(); if (error == (int)WsaError.WSAENOMORE || error == (int)WsaError.WSA_E_NO_MORE) { // no more break; } if (error == (int)WsaError.WSAEFAULT) { // buffer too small, allocate a bigger one of the specified size if (nativeQuerySetPtr != null) { nativeQuerySetPtr.Dispose(); nativeQuerySetPtr = null; } //wrap in CriticalAllocHandle when PAYLOAD is enabled nativeQuerySetPtr = CriticalAllocHandle.FromSize(size); continue; } // unexpected error throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SocketException(error)); } else { if (nativeQuerySetPtr != IntPtr.Zero) { // marshal the results into something usable WsaQuerySet resultQuerySet = PeerNameResolver.MarshalWsaQuerySetNativeToWsaQuerySet(nativeQuerySetPtr, 0); // extract out the friendly cloud attributes CloudInfo resultCloudInfo = new CloudInfo(); PnrpCloudInfo prnpCloudInfo = (PnrpCloudInfo)resultQuerySet.Blob; resultCloudInfo.Name = resultQuerySet.ServiceInstanceName; resultCloudInfo.Scope = prnpCloudInfo.Cloud.Scope; resultCloudInfo.ScopeId = prnpCloudInfo.Cloud.ScopeId; resultCloudInfo.State = prnpCloudInfo.dwCloudState; resultCloudInfo.Flags = prnpCloudInfo.Flags; // add it to the list to return later clouds.Add(resultCloudInfo); } } } } // package up the results into a nice array return (CloudInfo[])clouds.ToArray(typeof(CloudInfo)); }
int InvokeService(WsaQuerySet registerQuery, WsaSetServiceOp op, int flags) { WsaQuerySetSafe native = WsaQuerySet.ToWsaQuerySetSafe(registerQuery); int error = 0; using (native) { CriticalAllocHandle handle = CriticalAllocHandleWsaQuerySetSafe.FromWsaQuerySetSafe(native); using (handle) { int retval = WSASetService(handle, op, flags); if (retval != 0) { error = WSAGetLastError(); } } } return error; }
public bool IsPnrpAvailable(TimeSpan waitForService) { if (!IsPnrpInstalled()) return false; //make sure that the service is running if (!IsPnrpServiceRunning(waitForService)) return false; // If PNRP is installed, ensure that it supports extended payload by attempting to register with // an invalid query set. If extended payload is not available, "WSASERVICE_NOT_FOUND" is returned. // Otherwise, "WSAEINVAL" is returned. //UPDATE: we will work with PNRP 1.0 if it is available. // a separate implementation will work with payload support when available. WsaQuerySet querySet = new WsaQuerySet(); querySet.NSProviderId = NsProviderName; querySet.ServiceClassId = SvcIdNameV1; int res = InvokeService(querySet, WsaSetServiceOp.Register, 0); //on xp 64bit, WSANO_DATA is returned if (res == (int)WsaError.WSAEINVAL || res == (int)WsaError.WSANO_DATA) return true; // if the call didn't fail or returned any other error, PNRP clearly isn't working properly return false; }
static public WsaQuerySetSafe ToWsaQuerySetSafe(WsaQuerySet input) { WsaQuerySetSafe result = new WsaQuerySetSafe(); if (input == null) return result; result.dwSize = Marshal.SizeOf(typeof(WsaQuerySetNative)); result.lpszServiceInstanceName = CriticalAllocHandleString.FromString(input.ServiceInstanceName); result.lpServiceClassId = CriticalAllocHandleGuid.FromGuid(input.ServiceClassId); result.lpszComment = CriticalAllocHandleString.FromString(input.Comment); result.dwNameSpace = input.NameSpace; result.lpNSProviderId = CriticalAllocHandleGuid.FromGuid(input.NSProviderId); result.lpszContext = CriticalAllocHandleString.FromString(input.Context); result.dwNumberOfProtocols = 0; result.lpafpProtocols = IntPtr.Zero; // not used result.lpszQueryString = IntPtr.Zero; if (input.CsAddrInfos != null) { result.dwNumberOfCsAddrs = input.CsAddrInfos.Length; result.addressList = CsAddrInfoSafe.FromAddresses(input.CsAddrInfos); } result.dwOutputFlags = 0; result.lpBlob = CriticalAllocHandlePnrpBlob.FromPnrpBlob(input.Blob); return result; }