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
- DependencySource.cs
- MappableObjectManager.cs
- IsolationInterop.cs
- MenuAutomationPeer.cs
- DocumentViewerBaseAutomationPeer.cs
- SoapCodeExporter.cs
- XComponentModel.cs
- BaseValidator.cs
- DebugTraceHelper.cs
- JsonFormatReaderGenerator.cs
- ContextDataSourceContextData.cs
- ChameleonKey.cs
- JournalEntryStack.cs
- WrapPanel.cs
- AtomPub10CategoriesDocumentFormatter.cs
- UntypedNullExpression.cs
- ValidatingReaderNodeData.cs
- CompiledQuery.cs
- Wizard.cs
- DtcInterfaces.cs
- Header.cs
- LinearGradientBrush.cs
- UserInitiatedRoutedEventPermission.cs
- BufferedGraphics.cs
- GridItemPattern.cs
- TransformDescriptor.cs
- AppManager.cs
- OdbcInfoMessageEvent.cs
- CurrentChangedEventManager.cs
- DesignTimeResourceProviderFactoryAttribute.cs
- CompareInfo.cs
- _NetRes.cs
- Soap.cs
- JoinGraph.cs
- PropertyManager.cs
- MimeParameter.cs
- baseaxisquery.cs
- InputScope.cs
- EntityTypeBase.cs
- Base64Stream.cs
- ToggleButtonAutomationPeer.cs
- HttpModuleAction.cs
- FacetValueContainer.cs
- Schema.cs
- TextRunProperties.cs
- WebServiceErrorEvent.cs
- Content.cs
- InputMethod.cs
- MailHeaderInfo.cs
- __TransparentProxy.cs
- SqlDataSourceStatusEventArgs.cs
- ListBoxItemAutomationPeer.cs
- RouteValueExpressionBuilder.cs
- ListContractAdapter.cs
- ObjectFullSpanRewriter.cs
- XPathNavigatorKeyComparer.cs
- ApplicationFileParser.cs
- ValidationEventArgs.cs
- FrugalMap.cs
- ServiceModelEnumValidatorAttribute.cs
- EmptyCollection.cs
- DataGridViewRowPostPaintEventArgs.cs
- DataRowComparer.cs
- NetworkStream.cs
- ValidationSummaryDesigner.cs
- WebHeaderCollection.cs
- ExpressionContext.cs
- __ConsoleStream.cs
- Transform3D.cs
- InstallerTypeAttribute.cs
- DataGridItemAttachedStorage.cs
- CharEnumerator.cs
- Authorization.cs
- DataSourceIDConverter.cs
- ReadOnlyCollectionBase.cs
- UInt32.cs
- SafeBitVector32.cs
- ListView.cs
- ErrorReporting.cs
- MatrixAnimationUsingPath.cs
- Property.cs
- TemplatePartAttribute.cs
- DetailsView.cs
- DoubleStorage.cs
- DayRenderEvent.cs
- listitem.cs
- ToolboxComponentsCreatingEventArgs.cs
- VisualTreeFlattener.cs
- TypeUnloadedException.cs
- XPathScanner.cs
- NativeMethods.cs
- EdmProviderManifest.cs
- OleCmdHelper.cs
- ScrollViewer.cs
- HtmlWindowCollection.cs
- GACMembershipCondition.cs
- TypeTypeConverter.cs
- Win32Native.cs
- RowTypePropertyElement.cs
- TraceData.cs