public virtual IEnumerator<ITask> ReserveDevicePortHandler(ReserveDevicePort reservation) { //Debugger.Break(); AttachResponse response; // If the device will be detached. if (reservation.Body.Connection.Port == LegoNxtPort.NotConnected) { response = new AttachResponse(reservation.Body.Connection, reservation.Body.DeviceModel); reservation.ResponsePort.Post(response); yield break; } switch (reservation.Body.Connection.Port) { case LegoNxtPort.A: case LegoNxtPort.EncoderA: reservation.Body.Connection.Port = LegoNxtPort.MotorA; break; case LegoNxtPort.B: case LegoNxtPort.EncoderB: reservation.Body.Connection.Port = LegoNxtPort.MotorB; break; case LegoNxtPort.C: case LegoNxtPort.EncoderC: reservation.Body.Connection.Port = LegoNxtPort.MotorC; break; case LegoNxtPort.AnyMotorPort: case LegoNxtPort.AnySensorPort: lock(_state.Runtime.Devices) { // See if the device is already attached. foreach (AttachRequest device in _state.Runtime.Devices.Values) { if (device.Registration != null && device.Registration.ServiceUri != null && device.Registration.ServiceUri.Equals(reservation.Body.ServiceUri, StringComparison.InvariantCultureIgnoreCase)) { response = new AttachResponse(device.Registration.Connection, reservation.Body.DeviceModel); reservation.ResponsePort.Post(response); yield break; } } } if (reservation.Body.Connection.Port == LegoNxtPort.AnyMotorPort) { // Use the next available Motor Port if (!_state.Runtime.Devices.ContainsKey(LegoNxtPort.MotorA.ToString()) || string.IsNullOrEmpty(_state.Runtime.Devices[LegoNxtPort.MotorA.ToString()].Registration.ServiceUri)) reservation.Body.Connection.Port = LegoNxtPort.MotorA; else if (!_state.Runtime.Devices.ContainsKey(LegoNxtPort.MotorB.ToString()) || string.IsNullOrEmpty(_state.Runtime.Devices[LegoNxtPort.MotorB.ToString()].Registration.ServiceUri)) reservation.Body.Connection.Port = LegoNxtPort.MotorB; else if (!_state.Runtime.Devices.ContainsKey(LegoNxtPort.MotorC.ToString()) || string.IsNullOrEmpty(_state.Runtime.Devices[LegoNxtPort.MotorC.ToString()].Registration.ServiceUri)) reservation.Body.Connection.Port = LegoNxtPort.MotorC; else reservation.Body.Connection.Port = LegoNxtPort.NotConnected; } else if (reservation.Body.Connection.Port == LegoNxtPort.AnySensorPort) { if (reservation.Body.DeviceType == LegoDeviceType.DigitalSensor) { bool done = !_state.Runtime.Connected; yield return Arbiter.Receive(false, TestPortForI2CSensor(LegoNxtPort.Sensor1, reservation.Body.DeviceModel), delegate(bool success) { if (success) reservation.Body.Connection.Port = LegoNxtPort.Sensor1; done = success; }); //if (!done) // yield return Arbiter.Receive(false, TestPortForI2CSensor(LegoNxtPort.Sensor2, reservation.Body.DeviceModel), // delegate(bool success) // { // if (success) // reservation.Body.Connection.Port = LegoNxtPort.Sensor2; // done = success; // }); //if (!done) // yield return Arbiter.Receive(false, TestPortForI2CSensor(LegoNxtPort.Sensor3, reservation.Body.DeviceModel), // delegate(bool success) // { // if (success) // reservation.Body.Connection.Port = LegoNxtPort.Sensor3; // done = success; // }); //if (!done) //{ // LogInfo(LogGroups.Console, "Checking for I2C Sensor on Port 4"); // yield return Arbiter.Receive(false, TestPortForI2CSensor(LegoNxtPort.Sensor4, reservation.Body.DeviceModel), // delegate(bool success) // { // LogInfo(LogGroups.Console, "Found I2C Sensor on Port 4: " + success.ToString()); // if (success) // reservation.Body.Connection.Port = LegoNxtPort.Sensor4; // done = success; // }); //} } } break; } // If we weren't able to assign the Port, exit if ( reservation.Body.Connection.Port == LegoNxtPort.NotConnected || reservation.Body.Connection.Port == LegoNxtPort.AnyMotorPort || reservation.Body.Connection.Port == LegoNxtPort.AnySensorPort || reservation.Body.Connection.Port == LegoNxtPort.A || reservation.Body.Connection.Port == LegoNxtPort.B || reservation.Body.Connection.Port == LegoNxtPort.C || reservation.Body.Connection.Port == LegoNxtPort.EncoderA || reservation.Body.Connection.Port == LegoNxtPort.EncoderB || reservation.Body.Connection.Port == LegoNxtPort.EncoderC) { reservation.Body.Connection.Port = LegoNxtPort.NotConnected; } else // Reserve the connection { _state.Runtime.Devices[reservation.Body.Connection.ToString()] = new AttachRequest(reservation.Body); } response = new AttachResponse(reservation.Body.Connection, reservation.Body.DeviceModel); reservation.ResponsePort.Post(response); yield break; }
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); }
public virtual IEnumerator<ITask> AttachAndSubscribeHandler(AttachAndSubscribe attach) { AttachResponse response; // Disconnect request if (attach.Body.Registration.Connection.Port == LegoNxtPort.NotConnected) { // Check if the sensor was already registered. UnregisterDevice(attach.Body.Registration.ServiceUri); response = new AttachResponse(attach.Body.Registration.Connection, attach.Body.Registration.DeviceModel); attach.ResponsePort.Post(response); yield break; } // Invalid Ports, return a fault if (attach.Body.Registration.Connection.Port == LegoNxtPort.AnyMotorPort || attach.Body.Registration.Connection.Port == LegoNxtPort.AnySensorPort || attach.Body.Registration.Connection.Port == LegoNxtPort.A || attach.Body.Registration.Connection.Port == LegoNxtPort.B || attach.Body.Registration.Connection.Port == LegoNxtPort.C || attach.Body.Registration.Connection.Port == LegoNxtPort.EncoderA || attach.Body.Registration.Connection.Port == LegoNxtPort.EncoderB || attach.Body.Registration.Connection.Port == LegoNxtPort.EncoderC) { attach.ResponsePort.Post( Fault.FromException( new ArgumentOutOfRangeException( string.Format("Invalid {0} Port: {1}", attach.Body.Registration.DeviceModel, attach.Body.Registration.Connection)))); yield break; } // Convert all inherited LegoCommand types to LegoCommands. NormalizeAttachRequest(attach.Body); string priorUri = null; string connectionKey = attach.Body.Registration.Connection.ToString(); if (_state.Runtime.Devices.ContainsKey(connectionKey)) { priorUri = _state.Runtime.Devices[connectionKey].Registration.ServiceUri; if (priorUri != attach.Body.Registration.ServiceUri) UnregisterDevice(priorUri); } _state.Runtime.Devices[connectionKey] = attach.Body; if (!string.IsNullOrEmpty(priorUri) && !priorUri.Equals(attach.Body.Registration.ServiceUri, StringComparison.InvariantCultureIgnoreCase)) { // Send Notification to prior service that it has been disconnected PortSet<DsspDefaultLookup, DsspDefaultDrop> priorServicePort = ServiceForwarder<PortSet<DsspDefaultLookup, DsspDefaultDrop>>(priorUri); priorServicePort.Post(DsspDefaultDrop.Instance); } if (_state.Runtime.Connected) { if (attach.Body.InitializationCommands != null) { foreach (LegoCommand cmd in attach.Body.InitializationCommands.Commands) { // Send Initialization Sequence. yield return Arbiter.Choice(_brickPort.SendCommand(cmd), delegate(LegoResponse ok) { }, delegate(Fault fault) { LogError(fault); }); } } } attach.Body.Registration.SubscriberUri = attach.Body.Subscriber; attach.Body.Timestamp = DateTime.Now; // Register for periodic Polling. if (attach.Body.PollingCommands != null && attach.Body.PollingCommands.Commands != null && attach.Body.PollingCommands.Commands.Count > 0) { _pollingPort.Post(new PollingEntry(attach.Body)); } response = new AttachResponse(attach.Body.Registration.Connection, attach.Body.Registration.DeviceModel); yield return Arbiter.Choice(SelectiveSubscribe(attach), delegate(SubscribeResponseType ok) { attach.ResponsePort.Post(response); }, attach.ResponsePort.Post ); yield break; }