Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / SystemNet / Net / PeerToPeer / PeerNameResolver.cs / 1305376 / PeerNameResolver.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Net.PeerToPeer { using System; using System.Collections.Generic; using System.Text; using System.ComponentModel; using System.Threading; using System.Security.Permissions; using System.Runtime.InteropServices; using System.Net; using System.Net.Sockets; using System.Diagnostics; ////// This is the event args class we give back each time when /// we have incremental resolution results /// public class ResolveProgressChangedEventArgs : ProgressChangedEventArgs { private PeerNameRecord m_PeerNameRecord; ////// We use progress percentage of **0** all times sice /// we will not no upfront how many records we are going to get /// /// /// public ResolveProgressChangedEventArgs(PeerNameRecord peerNameRecord, object userToken) : base(0, userToken) { m_PeerNameRecord = peerNameRecord; } public PeerNameRecord PeerNameRecord { get { return m_PeerNameRecord; } } } ////// When the resolution completes, we invoke the callback with this event args instance /// public class ResolveCompletedEventArgs : AsyncCompletedEventArgs { private PeerNameRecordCollection m_PeerNameRecordCollection; public ResolveCompletedEventArgs( PeerNameRecordCollection peerNameRecordCollection, Exception error, bool canceled, object userToken) : base(error, canceled, userToken) { m_PeerNameRecordCollection = peerNameRecordCollection; } public PeerNameRecordCollection PeerNameRecordCollection { get { return m_PeerNameRecordCollection; } } } internal class PeerNameResolverHelper : IDisposable { private const UInt32 FACILITY_P2P = 99; private const UInt32 NO_MORE_RECORDS = 0x4003; private const int PEER_E_NO_MORE = (int)(((int)1 << 31) | ((int)FACILITY_P2P << 16) | NO_MORE_RECORDS); //------------------------------------------ //userState the user has supplied //------------------------------------------ internal object m_userState; //------------------------------------------ //Handle to the resolution process //------------------------------------------ internal SafePeerNameEndResolve m_SafePeerNameEndResolve; //------------------------------------------ //Event that the native API sets to indicate that //information is available and that we should call //the PeerPnrpGetEndPoint() to get the end point //------------------------------------------ internal AutoResetEvent m_EndPointInfoAvailableEvent = new AutoResetEvent(false); //------------------------------------------ //The WaitHandle that hooks up a callback to the //event //------------------------------------------ internal RegisteredWaitHandle m_RegisteredWaitHandle; //------------------------------------------ //PeerName that is being resolved //------------------------------------------ internal PeerName m_PeerName; //------------------------------------------ //Cloud in which the resolution must occur //------------------------------------------ internal Cloud m_Cloud; //------------------------------------------ //Max number of records to resolve //------------------------------------------ internal int m_MaxRecords; //------------------------------------------ //Disposed or not //------------------------------------------ internal bool m_Disposed; //----------------------------------------- //Flag to indicate completed or an exception //happened. If you set this flag you own //calling the callback //----------------------------------------- internal bool m_CompletedOrException; //----------------------------------------- //Flag to indicate that the call is canceled //If you set this flag you own calling the callback //----------------------------------------- internal bool m_Cancelled; //------------------------------------------ //A place to save the incremental results //so that we can invoke the completed //handler with all the results at once //------------------------------------------ PeerNameRecordCollection m_PeerNameRecordCollection = new PeerNameRecordCollection(); //------------------------------------------ //Async operation to ensure synchornization //context //------------------------------------------ AsyncOperation m_AsyncOp; //------------------------------------------ //A link to the resolver to avoid //circular dependencies and enable GC //------------------------------------------ WeakReference m_PeerNameResolverWeakReference; //------------------------------------------ //Lock to make sure things don't mess up stuff //------------------------------------------ object m_Lock = new Object(); //------------------------------------------ //EventID or Just a trackig id //------------------------------------------ int m_TraceEventId; internal PeerNameResolverHelper(PeerName peerName, Cloud cloud, int MaxRecords, object userState, PeerNameResolver parent, int NewTraceEventId) { m_userState = userState; m_PeerName = peerName; m_Cloud = cloud; m_MaxRecords = MaxRecords; m_PeerNameResolverWeakReference = new WeakReference(parent); m_TraceEventId = NewTraceEventId; Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "New PeerNameResolverHelper created with TraceEventID {0}", m_TraceEventId); Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "\tPeerName: {0}, Cloud: {1}, MaxRecords: {2}, userState {3}, ParentReference {4}", m_PeerName, m_Cloud, m_MaxRecords, userState.GetHashCode(), m_PeerNameResolverWeakReference.Target.GetHashCode() ); } //// [System.Security.SecurityCritical] internal void StartAsyncResolve() { //------------------------------------------ //Check for disposal //------------------------------------------ if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); //------------------------------------------ //First wire up a callback //------------------------------------------ m_RegisteredWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_EndPointInfoAvailableEvent, //Event that triggers the callback new WaitOrTimerCallback(EndPointInfoAvailableCallback), //callback to be called null, //state to be passed -1, //Timeout - aplicable only for timers not for events false //call us everytime the event is set not just one time ); //------------------------------------------ //Now call the native API to start the resolution //process save the handle for later //------------------------------------------ Int32 result = UnsafeP2PNativeMethods.PeerPnrpStartResolve(m_PeerName.ToString(), m_Cloud.InternalName, (UInt32)m_MaxRecords, m_EndPointInfoAvailableEvent.SafeWaitHandle, out m_SafePeerNameEndResolve); if (result != 0) { if (!m_SafePeerNameEndResolve.IsInvalid && !m_SafePeerNameEndResolve.IsClosed) { m_SafePeerNameEndResolve.Dispose(); } m_RegisteredWaitHandle.Unregister(null); m_RegisteredWaitHandle = null; PeerToPeerException ex = PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotStartNameResolution), result); Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, m_TraceEventId, "Exception occurred while starting async resolve"); throw ex; } //------------------------------------------ //Create an async operation with the given //user state //------------------------------------------ m_AsyncOp = AsyncOperationManager.CreateOperation(m_userState); Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Successfully started the async resolve. The native handle is {0}", m_SafePeerNameEndResolve.DangerousGetHandle()); } //// // // // // // // // // // [System.Security.SecurityCritical] public void EndPointInfoAvailableCallback(object state, bool timedOut) { //------------------------------------------ //This callback is called whenever there is an endpoint info //available or the resultion is completed //------------------------------------------ Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "EndPointInfoAvailableCallback called"); PeerNameRecord record = null; SafePeerData shEndPointInfo; Int32 result = 0; PeerNameResolver parent = null; if (m_Cancelled) { Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Detected that the async operation is already canceled - before entering the lock"); return; } lock (m_Lock) { if (m_Cancelled) { Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Detected that the async operation is already canceled - after entering the lock"); return; } result = UnsafeP2PNativeMethods.PeerPnrpGetEndpoint(m_SafePeerNameEndResolve.DangerousGetHandle(), out shEndPointInfo); if (result != 0) { if (result == PEER_E_NO_MORE) { Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Native API returned that there are no more records - resolve completed successfully"); } m_CompletedOrException = true; m_SafePeerNameEndResolve.Dispose(); } else { Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Proceeding to retrieve the endpoint information from incremental resolve"); try { unsafe { PEER_PNRP_ENDPOINT_INFO* pEndPointInfo = (PEER_PNRP_ENDPOINT_INFO*)shEndPointInfo.DangerousGetHandle(); record = new PeerNameRecord(); record.PeerName = new PeerName(Marshal.PtrToStringUni(pEndPointInfo->pwszPeerName)); string comment = Marshal.PtrToStringUni(pEndPointInfo->pwszComment); if (comment != null && comment.Length > 0) { record.Comment = comment; } if (pEndPointInfo->payLoad.cbPayload != 0) { record.Data = new byte[pEndPointInfo->payLoad.cbPayload]; Marshal.Copy(pEndPointInfo->payLoad.pbPayload, record.Data, 0, (int)pEndPointInfo->payLoad.cbPayload); } //record.EndPointList = new IPEndPoint[pEndPointInfo->cAddresses]; IntPtr ppSOCKADDRs = pEndPointInfo->ArrayOfSOCKADDRIN6Pointers; for (UInt32 j = 0; j < pEndPointInfo->cAddresses; j++) { IntPtr pSOCKADDR = Marshal.ReadIntPtr(ppSOCKADDRs); byte[] AddressFamilyBuffer = new byte[2]; Marshal.Copy(pSOCKADDR, AddressFamilyBuffer, 0, 2); int addressFamily = 0; #if BIGENDIAN addressFamily = AddressFamilyBuffer[1] + ((int)AddressFamilyBuffer[0] << 8); #else addressFamily = AddressFamilyBuffer[0] + ((int)AddressFamilyBuffer[1] << 8); #endif byte[] buffer = new byte[((AddressFamily)addressFamily == AddressFamily.InterNetwork) ? SystemNetHelpers.IPv4AddressSize : SystemNetHelpers.IPv6AddressSize]; Marshal.Copy(pSOCKADDR, buffer, 0, buffer.Length); IPEndPoint ipe = SystemNetHelpers.IPEndPointFromSOCKADDRBuffer(buffer); record.EndPointCollection.Add(ipe); ppSOCKADDRs = (IntPtr)((long)ppSOCKADDRs + Marshal.SizeOf(typeof(IntPtr))); } } } finally { shEndPointInfo.Dispose(); } record.TracePeerNameRecord(); m_PeerNameRecordCollection.Add(record); ResolveProgressChangedEventArgs resolveProgressChangedEventArgs = new ResolveProgressChangedEventArgs( record, m_AsyncOp.UserSuppliedState); Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Proceeding to call progress changed event callback"); parent = m_PeerNameResolverWeakReference.Target as PeerNameResolver; if (parent != null) { parent.PrepareToRaiseProgressChangedEvent(m_AsyncOp, resolveProgressChangedEventArgs); } return; } } ResolveCompletedEventArgs resolveCompletedEventArgs; if (result == PEER_E_NO_MORE) { resolveCompletedEventArgs = new ResolveCompletedEventArgs(m_PeerNameRecordCollection, null, false, m_AsyncOp.UserSuppliedState); } else { PeerToPeerException ex = PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_ExceptionWhileResolvingAPeerName), result); Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Exception occurred when the native API is called to harvest an incremental resolve notification"); resolveCompletedEventArgs = new ResolveCompletedEventArgs(null, ex, false, m_AsyncOp.UserSuppliedState); } parent = m_PeerNameResolverWeakReference.Target as PeerNameResolver; if (parent != null) { Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Proceeding to call the ResolveCompleted callback"); parent.PrepareToRaiseCompletedEvent(m_AsyncOp, resolveCompletedEventArgs); } return; } //// // // // // // // // // // // // // [System.Security.SecurityCritical] public void ContineCancelCallback(object state) { Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "ContineCancelCallback called"); try { if (m_CompletedOrException) { Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "ContinueCancelCallback detected (before acquiring lock) that another thread has already called completed event - so returning without calling cancel"); return; } lock (m_Lock) { if (m_Cancelled) { Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "ContinueCancelCallback detected (after acquiring lock) that cancel has already been called"); return; } if (m_CompletedOrException) { Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "ContinueCancelCallback detected (after acquiring lock) that another thread has already called completed event - so returning without calling cancel"); return; } else { Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "ContinueCancelCallback is proceeding to close the handle and call the Completed callback with Cancelled = true"); } m_Cancelled = true; m_SafePeerNameEndResolve.Dispose(); } PeerNameResolver parent = m_PeerNameResolverWeakReference.Target as PeerNameResolver; if (parent != null) { ResolveCompletedEventArgs e = new ResolveCompletedEventArgs(null, null, true, m_AsyncOp.UserSuppliedState); parent.PrepareToRaiseCompletedEvent(m_AsyncOp, e); } } catch { Logging.P2PTraceSource.TraceEvent(TraceEventType.Critical, m_TraceEventId, "Exception while cancelling the call "); throw; } } //// // // [System.Security.SecurityCritical] public void CancelAsync() { //Defer the work to a callback ThreadPool.QueueUserWorkItem(new WaitCallback(ContineCancelCallback)); } //// // [System.Security.SecurityCritical] public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } //// // [System.Security.SecurityCritical] public void Dispose(bool disposing) { if (!m_Disposed) { if (!m_SafePeerNameEndResolve.IsInvalid) { m_SafePeerNameEndResolve.Dispose(); } if (m_RegisteredWaitHandle != null) m_RegisteredWaitHandle.Unregister(null); m_RegisteredWaitHandle = null; m_EndPointInfoAvailableEvent.Close(); } m_Disposed = true; } internal int TraceEventId { get { return m_TraceEventId; } } } ///// // // /// PeerNameResolver does [....] and async resolves. /// PeerNameResolver supports multiple outstanding async calls /// public class PeerNameResolver { static PeerNameResolver() { //------------------------------------------------- //Check for the availability of the simpler PNRP APIs //------------------------------------------------- if (!PeerToPeerOSHelper.SupportsP2P) { throw new PlatformNotSupportedException(SR.GetString(SR.P2P_NotAvailable)); } } private event EventHandlerm_ResolveProgressChanged; /// /// When an event handler is hooked up or removed, we demand the permissions. /// In partial trust cases, this will avoid the security risk of just hooking up an existing instance /// of the PeerNameResolver and then receiving all notification of /// in resolution that is happening /// public event EventHandlerResolveProgressChanged { add { PnrpPermission.UnrestrictedPnrpPermission.Demand(); m_ResolveProgressChanged += value; } remove { PnrpPermission.UnrestrictedPnrpPermission.Demand(); m_ResolveProgressChanged -= value; } } private event EventHandler m_ResolveCompleted; /// /// When an event handler is hooked up or removed, we demand the permissions. /// In partial trust cases, this will avoid the security risk of just hooking up an existing instance /// of the PeerNameResolver and then receiving all notification of /// in resolution that is happening /// public event EventHandlerResolveCompleted { add { PnrpPermission.UnrestrictedPnrpPermission.Demand(); m_ResolveCompleted += value; } remove { PnrpPermission.UnrestrictedPnrpPermission.Demand(); m_ResolveCompleted -= value; } } SendOrPostCallback OnResolveProgressChangedDelegate; SendOrPostCallback OnResolveCompletedDelegate; /// /// The following lock and the Sorted Dictionary served /// the purpose of keeping an account of the multiple outstanding async /// resolutions. Each outstanding async operation is /// keyed based on the userState parameter passed in /// private object m_PeerNameResolverHelperListLock = new object(); private Dictionary
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- InkCanvasFeedbackAdorner.cs
- CommunicationObjectManager.cs
- MemoryPressure.cs
- IntranetCredentialPolicy.cs
- ReflectionServiceProvider.cs
- LambdaCompiler.Binary.cs
- SourceFileInfo.cs
- TextCompositionEventArgs.cs
- UriTemplateTrieLocation.cs
- Utils.cs
- FaultCode.cs
- ImportCatalogPart.cs
- HttpRequestWrapper.cs
- StickyNoteContentControl.cs
- LayoutDump.cs
- SqlMethodCallConverter.cs
- RowUpdatedEventArgs.cs
- FastEncoderWindow.cs
- WindowsToolbarItemAsMenuItem.cs
- HandlerFactoryCache.cs
- CodeSnippetStatement.cs
- DoubleAnimationBase.cs
- EntityTypeBase.cs
- ResourceExpressionBuilder.cs
- ConfigXmlSignificantWhitespace.cs
- CodePageEncoding.cs
- EventMappingSettingsCollection.cs
- AvTraceDetails.cs
- PathFigureCollectionValueSerializer.cs
- RoleServiceManager.cs
- LicenseProviderAttribute.cs
- PartitionResolver.cs
- Enum.cs
- ProvideValueServiceProvider.cs
- SystemInformation.cs
- XPathSelectionIterator.cs
- RemotingConfiguration.cs
- ComponentCollection.cs
- CodePropertyReferenceExpression.cs
- WebPartChrome.cs
- RoutingChannelExtension.cs
- SByteStorage.cs
- LifetimeServices.cs
- COM2IPerPropertyBrowsingHandler.cs
- SymLanguageType.cs
- SmtpAuthenticationManager.cs
- BitmapCodecInfo.cs
- InvokeMethodActivityDesigner.cs
- odbcmetadatacolumnnames.cs
- Facet.cs
- GetKeyedHashRequest.cs
- UserPreferenceChangingEventArgs.cs
- MethodBuilderInstantiation.cs
- CallSiteBinder.cs
- SimpleParser.cs
- AdapterUtil.cs
- PropertyPath.cs
- QueryBranchOp.cs
- MultiByteCodec.cs
- DropTarget.cs
- TargetPerspective.cs
- PasswordRecovery.cs
- FileStream.cs
- COAUTHIDENTITY.cs
- BufferedWebEventProvider.cs
- SqlBuffer.cs
- Zone.cs
- WebResponse.cs
- AsymmetricKeyExchangeFormatter.cs
- CachingHintValidation.cs
- ComponentEvent.cs
- XmlSignatureManifest.cs
- ServiceModelSectionGroup.cs
- WindowsScrollBarBits.cs
- WindowsFormsLinkLabel.cs
- DeploymentExceptionMapper.cs
- CngProvider.cs
- MetadataUtil.cs
- SymDocumentType.cs
- RepeatButtonAutomationPeer.cs
- EventSetter.cs
- ModelEditingScope.cs
- DataBindEngine.cs
- SharedDp.cs
- QilInvokeEarlyBound.cs
- Point.cs
- TreeBuilder.cs
- XmlAttributeOverrides.cs
- GlobalizationSection.cs
- odbcmetadatacolumnnames.cs
- FileDialog_Vista_Interop.cs
- LassoHelper.cs
- DrawingCollection.cs
- SqlMethodCallConverter.cs
- ResizeGrip.cs
- DynamicPropertyHolder.cs
- InputBindingCollection.cs
- ColorTransform.cs
- SmtpNtlmAuthenticationModule.cs
- OlePropertyStructs.cs