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
- QilReplaceVisitor.cs
- ModelUtilities.cs
- SoapTypeAttribute.cs
- InputScopeManager.cs
- HandlerBase.cs
- ProcessModelInfo.cs
- SynthesizerStateChangedEventArgs.cs
- CodeDelegateInvokeExpression.cs
- WebZone.cs
- FontCollection.cs
- SendActivityEventArgs.cs
- SQLRoleProvider.cs
- XmlNamespaceMappingCollection.cs
- DbProviderConfigurationHandler.cs
- ManagedWndProcTracker.cs
- DesignBindingPropertyDescriptor.cs
- GetIsBrowserClientRequest.cs
- DataColumnMappingCollection.cs
- TextTreeDeleteContentUndoUnit.cs
- UdpSocketReceiveManager.cs
- UseManagedPresentationBindingElementImporter.cs
- Enum.cs
- SharedStatics.cs
- ToolbarAUtomationPeer.cs
- KeyGestureValueSerializer.cs
- FileSystemWatcher.cs
- MinimizableAttributeTypeConverter.cs
- TextElementAutomationPeer.cs
- JsonReader.cs
- SystemIPGlobalProperties.cs
- KeyGestureValueSerializer.cs
- DataGridTextBox.cs
- StrokeCollectionDefaultValueFactory.cs
- ContentPresenter.cs
- _HelperAsyncResults.cs
- SoapSchemaMember.cs
- BackgroundWorker.cs
- WizardSideBarListControlItemEventArgs.cs
- FontCacheUtil.cs
- ViewgenGatekeeper.cs
- GuidConverter.cs
- IfJoinedCondition.cs
- PresentationTraceSources.cs
- FrameworkElement.cs
- SafeTimerHandle.cs
- FrameworkElement.cs
- TextBox.cs
- DataPagerCommandEventArgs.cs
- ListBase.cs
- ContextMenu.cs
- TreeViewEvent.cs
- TypeContext.cs
- SelectionWordBreaker.cs
- EdmValidator.cs
- Vector3dCollection.cs
- Scanner.cs
- NetStream.cs
- EventProviderWriter.cs
- CacheOutputQuery.cs
- AttributedMetaModel.cs
- AnimationLayer.cs
- DetailsViewPagerRow.cs
- IChannel.cs
- WebPartMinimizeVerb.cs
- MenuItemCollectionEditorDialog.cs
- Convert.cs
- HelpEvent.cs
- SafeNativeMethods.cs
- ObsoleteAttribute.cs
- ErrorFormatter.cs
- ClaimTypeElementCollection.cs
- ModelTreeEnumerator.cs
- DocumentApplication.cs
- OdbcHandle.cs
- DynamicControlParameter.cs
- XsltQilFactory.cs
- DataAccessor.cs
- Dynamic.cs
- _OverlappedAsyncResult.cs
- ComplexPropertyEntry.cs
- WebPageTraceListener.cs
- CodeTypeReference.cs
- Expander.cs
- ContainerControl.cs
- HostingEnvironment.cs
- ImageAutomationPeer.cs
- CheckBoxRenderer.cs
- BaseTreeIterator.cs
- GroupBox.cs
- fixedPageContentExtractor.cs
- SerTrace.cs
- WrappedIUnknown.cs
- InkSerializer.cs
- FunctionParameter.cs
- XmlDocument.cs
- Int64.cs
- PersistenceTypeAttribute.cs
- CachedTypeface.cs
- MetadataCollection.cs
- TcpChannelListener.cs