/// <summary> /// Callback called after a <see cref="BluetoothUnlockResponsePacket"/> is received and the /// corresponding Packet Received event has been fired. /// </summary> /// <param name="sender">The object that sent the event.</param> /// <param name="e">The Packet Received event.</param> /// <seealso cref="PacketReceivedEventArgs"/> private void ReceiveBLEPacket(object sender, PacketReceivedEventArgs e) { if (!(e.ReceivedPacket is XBeeAPIPacket) || ((XBeeAPIPacket)e.ReceivedPacket).FrameType != APIFrameType.BLE_UNLOCK_RESPONSE) { return; } BluetoothUnlockResponsePacket response = (BluetoothUnlockResponsePacket)e.ReceivedPacket; // Check if the packet contains the expected phase or an error. if (response.SrpPhase != SrpPhase.UNKNOWN && response.SrpPhase != expectedPhase) { return; } unlockResponse = response; // Continue execution by notifying the lock object. lock (unlockLock) { Monitor.Pulse(unlockLock); } }
/// <summary> /// Starts the bluetooth authentication with the XBee device. /// </summary> /// <exception cref="BluetoothAuthenticationException">If there is any error performing the /// bluetooth authentication.</exception> /// <exception cref="InterfaceNotOpenException">If the connection interface is not open.</exception> /// <exception cref="XBeeException">If there is any error in the communication process.</exception> public void Authenticate() { // Check connection. if (!device.IsOpen) { throw new InterfaceNotOpenException(); } device.PacketReceived += ReceiveBLEPacket; try { User user = new User(API_USERNAME, password); // Phase 1. byte[] clientEphemeral = user.StartAuthentication(); expectedPhase = SrpPhase.PHASE_2; unlockResponse = null; device.SendPacketAsync(new BluetoothUnlockPacket(SrpPhase.PHASE_1, clientEphemeral)); lock (unlockLock) { Monitor.Wait(unlockLock, TIMEOUT_AUTH); } CheckResponsePacket(); // Phase 2. int index = 0; byte[] salt = new byte[LENGTH_SALT]; Array.Copy(unlockResponse.Data, index, salt, 0, salt.Length); index += LENGTH_SALT; byte[] serverEphemeral = new byte[LENGTH_EPHEMERAL]; Array.Copy(unlockResponse.Data, index, serverEphemeral, 0, serverEphemeral.Length); // Phase 3. byte[] clientSessionProof = user.ProcessChallenge(salt, serverEphemeral); expectedPhase = SrpPhase.PHASE_4; unlockResponse = null; device.SendPacketAsync(new BluetoothUnlockPacket(SrpPhase.PHASE_3, clientSessionProof)); lock (unlockLock) { Monitor.Wait(unlockLock, TIMEOUT_AUTH); } CheckResponsePacket(); // Phase 4. index = 0; byte[] serverSessionProof = new byte[LENGTH_SESSION_PROOF]; Array.Copy(unlockResponse.Data, index, serverSessionProof, 0, serverSessionProof.Length); index += LENGTH_SESSION_PROOF; TxNonce = new byte[LENGTH_NONCE]; Array.Copy(unlockResponse.Data, index, TxNonce, 0, TxNonce.Length); index += LENGTH_NONCE; RxNonce = new byte[LENGTH_NONCE]; Array.Copy(unlockResponse.Data, index, RxNonce, 0, RxNonce.Length); user.VerifySession(serverSessionProof); if (!user.authenticated) { throw new BluetoothAuthenticationException(string.Format(ERROR_AUTH_EXTENDED, ERROR_BAD_PROOF)); } // Save the sesion key. Key = user.SessionKey; } catch (IOException e) { throw new XBeeException(ERROR_WRITING, e); } finally { device.PacketReceived -= ReceiveBLEPacket; } }
/// <summary> /// Parses the given API payload to get the right API packet, depending on its API /// type (<c><paramref name="payload"/>[0]</c>). /// </summary> /// <param name="payload">The payload of the API frame.</param> /// <returns>The corresponding API packet or <see cref="UnknownXBeePacket"/> if the frame API /// type is unknown.</returns> /// <exception cref="InvalidPacketException">If the payload is invalid for the specified /// frame type.</exception> /// <seealso cref="APIFrameType"/> /// <seealso cref="XBeePacket"/> private XBeePacket ParsePayload(byte[] payload) { // Get the API frame type. APIFrameType apiType = APIFrameType.UNKNOWN.Get(payload[0]); // Parse API payload depending on API ID. XBeePacket packet = null; switch (apiType) { case APIFrameType.TX_64: packet = TX64Packet.CreatePacket(payload); break; case APIFrameType.TX_16: packet = TX16Packet.CreatePacket(payload); break; case APIFrameType.BLE_UNLOCK: packet = BluetoothUnlockPacket.CreatePacket(payload); break; case APIFrameType.USER_DATA_RELAY: packet = UserDataRelayPacket.CreatePacket(payload); break; case APIFrameType.AT_COMMAND: packet = ATCommandPacket.CreatePacket(payload); break; case APIFrameType.AT_COMMAND_QUEUE: packet = ATCommandQueuePacket.CreatePacket(payload); break; case APIFrameType.TRANSMIT_REQUEST: packet = TransmitPacket.CreatePacket(payload); break; case APIFrameType.EXPLICIT_ADDRESSING_COMMAND_FRAME: packet = ExplicitAddressingPacket.CreatePacket(payload); break; case APIFrameType.REMOTE_AT_COMMAND_REQUEST: packet = RemoteATCommandPacket.CreatePacket(payload); break; case APIFrameType.TX_SMS: packet = TXSMSPacket.CreatePacket(payload); break; case APIFrameType.TX_IPV4: packet = TXIPv4Packet.CreatePacket(payload); break; case APIFrameType.TX_REQUEST_TLS_PROFILE: packet = TXTLSProfilePacket.CreatePacket(payload); break; case APIFrameType.RX_64: packet = RX64Packet.CreatePacket(payload); break; case APIFrameType.RX_16: packet = RX16Packet.CreatePacket(payload); break; case APIFrameType.RX_IO_64: packet = RX64IOPacket.CreatePacket(payload); break; case APIFrameType.RX_IO_16: packet = RX16IOPacket.CreatePacket(payload); break; case APIFrameType.AT_COMMAND_RESPONSE: packet = ATCommandResponsePacket.CreatePacket(payload); break; case APIFrameType.TX_STATUS: packet = TXStatusPacket.CreatePacket(payload); break; case APIFrameType.MODEM_STATUS: packet = ModemStatusPacket.CreatePacket(payload); break; case APIFrameType.TRANSMIT_STATUS: packet = TransmitStatusPacket.CreatePacket(payload); break; case APIFrameType.RECEIVE_PACKET: packet = ReceivePacket.CreatePacket(payload); break; case APIFrameType.EXPLICIT_RX_INDICATOR: packet = ExplicitRxIndicatorPacket.CreatePacket(payload); break; case APIFrameType.IO_DATA_SAMPLE_RX_INDICATOR: packet = IODataSampleRxIndicatorPacket.CreatePacket(payload); break; case APIFrameType.REMOTE_AT_COMMAND_RESPONSE: packet = RemoteATCommandResponsePacket.CreatePacket(payload); break; case APIFrameType.RX_SMS: packet = RXSMSPacket.CreatePacket(payload); break; case APIFrameType.BLE_UNLOCK_RESPONSE: packet = BluetoothUnlockResponsePacket.CreatePacket(payload); break; case APIFrameType.USER_DATA_RELAY_OUTPUT: packet = UserDataRelayOutputPacket.CreatePacket(payload); break; case APIFrameType.RX_IPV4: packet = RXIPv4Packet.CreatePacket(payload); break; case APIFrameType.UNKNOWN: default: packet = UnknownXBeePacket.CreatePacket(payload); break; } return(packet); }