private async void ReceivePump() { // Read length. var lengthBuffer = new byte[4]; int receiveLength; try { receiveLength = await Task.Factory.FromAsync( (callback, state) => socket.BeginReceive(lengthBuffer, 0, lengthBuffer.Length, SocketFlags.None, callback, state), asyncResult => socket.EndReceive(asyncResult), null); } catch (SocketException) { System.Diagnostics.Debug.WriteLine("Socket read error; detaching"); Detach(); return; } if (receiveLength == 0 || receiveLength != 4) { // Failed? ReceivePump(); return; } var length = BitConverter.ToInt32(lengthBuffer, 0); // Read body. var bodyBuffer = new byte[length]; int bodyOffset = 0; while (bodyOffset != bodyBuffer.Length) { receiveLength = await Task.Factory.FromAsync( (callback, state) => socket.BeginReceive( bodyBuffer, bodyOffset, bodyBuffer.Length - bodyOffset, SocketFlags.None, callback, state), asyncResult => socket.EndReceive(asyncResult), null); if (receiveLength == 0) { // Failed? ReceivePump(); return; } bodyOffset += receiveLength; } // Emit message. OnMessageReceived(bodyBuffer); // Continue pumping. Dispatch.Issue(() => ReceivePump()); }
public async Task Attach(CancellationToken cancellationToken) { System.Diagnostics.Debug.Assert(CurrentState == State.Idle); SocketPermission permission = new SocketPermission( NetworkAccess.Connect, TransportType.Tcp, kServerHostname, kServerPort); permission.Demand(); IPAddress ipAddress = new IPAddress(new byte[] { 127, 0, 0, 1 }); IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, kServerPort); socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Blocking = false; socket.NoDelay = true; socket.ReceiveBufferSize = 1024 * 1024; socket.SendBufferSize = 1024 * 1024; socket.ReceiveTimeout = 0; socket.SendTimeout = 0; OnStateChanged(State.Attaching); while (true) { Task task = Task.Factory.FromAsync(socket.BeginConnect, socket.EndConnect, ipEndPoint, null); try { await task.WithCancellation(cancellationToken); } catch (OperationCanceledException) { socket.Close(); socket = null; OnStateChanged(State.Idle); return; } catch (SocketException e) { if (e.SocketErrorCode == SocketError.ConnectionRefused) { // Not found - emulator may still be starting. System.Diagnostics.Debug.WriteLine("Connection refused; trying again..."); continue; } OnStateChanged(State.Idle); return; } break; } // Start recv pump. Dispatch.Issue(() => ReceivePump()); var fbb = BeginRequest(); AttachRequest.StartAttachRequest(fbb); int requestDataOffset = AttachRequest.EndAttachRequest(fbb); var response = await CommitRequest(fbb, RequestData.AttachRequest, requestDataOffset); System.Diagnostics.Debug.Assert(response.ResponseDataType == ResponseData.AttachResponse); var attachResponse = new AttachResponse(); response.GetResponseData(attachResponse); // Open mmap to share memory. memoryHandle = FileMapping.OpenFileMapping( FileMapAccess.FILE_MAP_ALL_ACCESS, false, attachResponse.MemoryFile); if (memoryHandle.IsInvalid) { System.Diagnostics.Debug.Fail("Unable to open target memory"); Detach(); return; } // Open mmap to code cache. codeCacheHandle = FileMapping.OpenFileMapping(FileMapAccess.FILE_MAP_ALL_ACCESS, false, attachResponse.CodeCacheFile); if (codeCacheHandle.IsInvalid) { System.Diagnostics.Debug.Fail("Unable to open target code cache"); Detach(); return; } codeCachePtr = FileMapping.MapViewOfFileEx( codeCacheHandle, FileMapAccess.FILE_MAP_ALL_ACCESS, 0, 0, attachResponse.CodeCacheSize, attachResponse.CodeCacheBase); // Setup the memory system. This maps the emulator memory into our address // space. if (!Memory.InitializeMapping(memoryHandle)) { Detach(); return; } OnStateChanged(State.Attached); }