1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
|
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_CRYPTAUTH_BLE_BLUETOOTH_LOW_ENERGY_WEAVE_PACKET_RECEIVER_H_
#define COMPONENTS_CRYPTAUTH_BLE_BLUETOOTH_LOW_ENERGY_WEAVE_PACKET_RECEIVER_H_
#include <stdint.h>
#include <memory>
#include <string>
#include <vector>
#include "build/build_config.h"
#include "components/cryptauth/ble/bluetooth_low_energy_weave_defines.h"
namespace cryptauth {
namespace weave {
// Receive the messages sent with uWeave protocol.
// Example Usage:
// State state = ReceivePacket(packet);
// switch (state) {
// case ReceiverState::DATA_READY:
// OnBytesReceived(GetDataMessage());
// break;
// case ReceiverState::CONNECTION_CLOSED:
// Disconnect(GetReasonForClose());
// break;
// case ReceiverState::ERROR:
// HandleError(GetReasonToClose());
// break;
// case ReceiverState::CONNECTING:
// case ReceiverState::WAITING:
// case ReceiverState::RECEIVING_DATA:
// break;
// default:
// FoundABugInReceiver();
// break;
// }
class BluetoothLowEnergyWeavePacketReceiver {
public:
enum ReceiverType { CLIENT, SERVER };
// CONNECTING:
// The connection hasn't been estabalished. Accept a CONNECTION_REQUEST if
// the receiver is a SERVER. Accept a CONNECTION_RESPONSE if the receiver is
// a CLIENT. All other packets cause the receiver to move into ERROR state.
// The state will transition to WAITING after a request/response if they
// do not have extra data. The state will transition to DATA_READY if the
// request/response have extra data since the extra data is treated as a
// complete data message. This state is never reentered.
// WAITING:
// The reciever is ready but doesn't have any data. It's waiting for packet
// to arrive. Will accept all but connection request/response packets. The
// first data packet will move the receiver to the RECEIVING_DATA state. A
// connection close packet will move the receiver to the CONNECTION_CLOSED
// state. This state is also never reentered.
// RECEIVING_DATA:
// The receiver is in middle of receiving a data message consisted of
// multiple packets. Will receive only data packets. The last data packet
// will move the receiver into DATA_READY state. This state can be entered
// once from WAITING and unlimited number of times from DATA_READY.
// DATA_READY:
// The data message is ready to be retrieved. If the data is not retrieved
// before the next packet which will cause a transition, the data will be
// lost. Move to RECEIVING_DATA on receiving first data packet. Move to
// CONNECTION_CLOSED on receiving close. This state can be entered once from
// CONNECTING and unlimited number of times from RECEIVING_DATA.
// CONNECTION_CLOSED:
// The connection is closed. Refuse any further messages. Allow the reason
// for close to be retrieved.
// ERROR:
// Something bad happened along the way. Allow a reason to close be
// retrieved. The reason to close tells the receiver's user what reason to
// close the connection in case the user wants to send a CONNECTION_CLOSE.
enum State {
CONNECTING = 0x00,
WAITING = 0x01,
RECEIVING_DATA = 0x02,
DATA_READY = 0x03,
CONNECTION_CLOSED = 0x04,
ERROR_DETECTED = 0x05
};
// The specific error that caused the receiver to move to ERROR state.
enum ReceiverError {
NO_ERROR_DETECTED,
EMPTY_PACKET,
RECEIVED_PACKET_IN_CONNECTION_CLOSED,
RECEIVED_DATA_IN_CONNECTING,
SERVER_RECEIVED_CONNECTION_RESPONSE,
CLIENT_RECEIVED_CONNECTION_REQUEST,
RECEIVED_CONNECTION_CLOSE_IN_CONNECTING,
UNRECOGNIZED_CONTROL_COMMAND,
INVALID_CONTROL_COMMAND_IN_DATA_TRANSACTION,
INVALID_DATA_PACKET_SIZE,
DATA_HEADER_LOW_BITS_NOT_CLEARED,
INCORRECT_DATA_FIRST_BIT,
INVALID_CONNECTION_REQUEST_SIZE,
INVALID_REQUESTED_MAX_PACKET_SIZE,
NOT_SUPPORTED_REQUESTED_VERSION,
INVALID_CONNECTION_RESPONSE_SIZE,
INVALID_SELECTED_MAX_PACKET_SIZE,
NOT_SUPPORTED_SELECTED_VERSION,
INVALID_CONNECTION_CLOSE_SIZE,
UNRECOGNIZED_REASON_FOR_CLOSE,
PACKET_OUT_OF_SEQUENCE
};
class Factory {
public:
static std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> NewInstance(
ReceiverType receiver_type);
// Exposed for testing.
static void SetInstanceForTesting(std::shared_ptr<Factory> factory);
protected:
// Exposed for testing.
virtual std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver>
BuildInstance(ReceiverType receiver_type);
private:
static std::shared_ptr<Factory> factory_instance_;
};
~BluetoothLowEnergyWeavePacketReceiver();
typedef std::vector<uint8_t> Packet;
// Get the receiver’s state.
virtual State GetState();
// Return the packet size that the receiver parsed out of request/response.
virtual uint16_t GetMaxPacketSize();
// Get the reason that receiver received in a connection close packet.
// It's only defined in CONNECTION_CLOSED state.
// Will crash unless receiver is in State::CONNECTION_CLOSED.
virtual ReasonForClose GetReasonForClose();
// The reason that the receiver decided to enter the ERROR state.
// This would be the reason that the receiver's want to send a connection
// close to the other side of the connection.
// Will crash unless receiver is in State::ERROR.
virtual ReasonForClose GetReasonToClose();
// Get a complete data message that's yet received.
// Will crash unless receiver is in State::DATA_READY.
// NOTE: if this function is not called in DATA_READY state and the receiver
// transitions out of that state, the data will be gone!
virtual std::string GetDataMessage();
// Get the specific error that caused the receiver to jump into ERROR state.
// Can be called from any state. Will return NO_ERROR if no error occurred.
virtual ReceiverError GetReceiverError();
// Add a packet that's just been received over Connection to the receiver.
virtual State ReceivePacket(const Packet& packet);
protected:
explicit BluetoothLowEnergyWeavePacketReceiver(ReceiverType receiver_type);
private:
void ReceiveFirstPacket(const Packet& packet);
void ReceiveNonFirstPacket(const Packet& packet);
void ReceiveConnectionRequest(const Packet& packet);
void ReceiveConnectionResponse(const Packet& packet);
void ReceiveConnectionClose(const Packet& packet);
void AppendData(const Packet& packet, uint32_t byte_offset);
uint16_t GetShortField(const Packet& packet, uint32_t byte_offset);
uint8_t GetPacketType(const Packet& packet);
uint8_t GetControlCommand(const Packet& packet);
void VerifyPacketCounter(const Packet& packet);
bool IsFirstDataPacket(const Packet& packet);
bool IsLastDataPacket(const Packet& packet);
bool AreLowerTwoBitsCleared(const Packet& packet);
void MoveToErrorState(ReasonForClose reason_to_close,
ReceiverError receiver_error);
void SetMaxPacketSize(uint16_t packet_size);
uint16_t GetConceptualMaxPacketSize();
// Identify whether the receiver is for a client or a server.
ReceiverType receiver_type_;
// Max packet size of the connection.
// Default is 0 which means the server will determine the size by observing
// ATT_MTU of the client.
uint16_t max_packet_size_;
// Expected counter of the next packet received, starting at 0.
uint8_t next_packet_counter_;
// Current state of the receiver.
// Certain functions will only return valid value if the receiver is in the
// appropriate state.
State state_;
// The reason why the connection was closed by the sender if any.
ReasonForClose reason_for_close_;
// The reason why the receiver is in an erronous state if any.
ReasonForClose reason_to_close_;
// The data message if there is one.
Packet data_message_;
// The error the receiver encountered while processing packets.
// Used for debugging purproses.
ReceiverError receiver_error_;
};
} // namespace weave
} // namespace cryptauth
#endif // COMPONENTS_CRYPTAUTH_BLE_BLUETOOTH_LOW_ENERGY_WEAVE_PACKET_RECEIVER_H_
|