public PeerNameRecordCollection Resolve(PeerName peerName, Cloud cloud, int maxRecords) { //--------------------------------------------------- //Check arguments //--------------------------------------------------- if (peerName == null) { throw new ArgumentNullException(SR.GetString(SR.Pnrp_PeerNameCantBeNull), "peerName"); } if (maxRecords <= 0) { throw new ArgumentOutOfRangeException("maxRecords", SR.GetString(SR.Pnrp_MaxRecordsParameterMustBeGreaterThanZero)); } //--------------------------------------------------- //Assume all clouds if the clould passed is null? //--------------------------------------------------- if (cloud == null) { cloud = Cloud.Available; } //--------------------------------------------------- //Demand CAS permissions //--------------------------------------------------- PnrpPermission.UnrestrictedPnrpPermission.Demand(); //--------------------------------------------------------------- //No perf hit here, real native call happens only one time if it //did not already happen //--------------------------------------------------------------- UnsafeP2PNativeMethods.PnrpStartup(); //--------------------------------------------------------------- //Trace log //--------------------------------------------------------------- Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Sync Resolve called with PeerName: {0}, Cloud: {1}, MaxRecords {2}", peerName, cloud, maxRecords); SafePeerData shEndPointInfoArray; string NativeCloudName = cloud.InternalName; UInt32 ActualCountOfEndPoints = (UInt32)maxRecords; int result = UnsafeP2PNativeMethods.PeerPnrpResolve(peerName.ToString(), NativeCloudName, ref ActualCountOfEndPoints, out shEndPointInfoArray); if (result != 0) { throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotStartNameResolution), result); } //--------------------------------------------------- //If there are no endpoints returned, return //an empty PeerNameRecord Collection //--------------------------------------------------- PeerNameRecordCollection PeerNameRecords = new PeerNameRecordCollection(); if (ActualCountOfEndPoints != 0) { try { unsafe { IntPtr pEndPointInfoArray = shEndPointInfoArray.DangerousGetHandle(); PEER_PNRP_ENDPOINT_INFO *pEndPoints = (PEER_PNRP_ENDPOINT_INFO *)pEndPointInfoArray; for (int i = 0; i < ActualCountOfEndPoints; i++) { PeerNameRecord record = new PeerNameRecord(); PEER_PNRP_ENDPOINT_INFO *pEndPointInfo = &pEndPoints[i]; 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))); } //---------------------------------- //Dump for trace //---------------------------------- record.TracePeerNameRecord(); //---------------------------------- //Add to collection //---------------------------------- PeerNameRecords.Add(record); } } } finally { shEndPointInfoArray.Dispose(); } } Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Sync Resolve returnig with PeerNameRecord count :{0}", PeerNameRecords.Count); return(PeerNameRecords); }
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; }