Etherios Cloud Connector very first porting for mbed. Tested in an LPC1768

Etherios Cloud Connector for Embedded v2.1.0.3 library for mbed. Early porting.

This port is centered mainly in the platform code. So it should work properly with the provided examples of send_data, device_request, data_points, RCI and firmware_update (stub implementation, not a real one... yet ;-)). Filesystem is not implemented yet, and some examples might need changes.

To run, it needs the following libraries: - mbed - mbed-rtos - EthernetInterface

Find more information (and the source code!) about Etherios Cloud Connector for Embedded here: http://www.etherios.com/products/devicecloud/support/connector and in: http://www.etherios.com

Committer:
spastor
Date:
Tue Dec 03 13:34:02 2013 +0000
Revision:
0:1c358ea10753
First commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
spastor 0:1c358ea10753 1 /*
spastor 0:1c358ea10753 2 * Copyright (c) 2013 Digi International Inc.,
spastor 0:1c358ea10753 3 * All rights not expressly granted are reserved.
spastor 0:1c358ea10753 4 *
spastor 0:1c358ea10753 5 * This Source Code Form is subject to the terms of the Mozilla Public
spastor 0:1c358ea10753 6 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
spastor 0:1c358ea10753 7 * You can obtain one at http://mozilla.org/MPL/2.0/.
spastor 0:1c358ea10753 8 *
spastor 0:1c358ea10753 9 * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
spastor 0:1c358ea10753 10 * =======================================================================
spastor 0:1c358ea10753 11 */
spastor 0:1c358ea10753 12
spastor 0:1c358ea10753 13 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 14 #include "zlib.h"
spastor 0:1c358ea10753 15 #endif
spastor 0:1c358ea10753 16
spastor 0:1c358ea10753 17 #define MSG_FACILITY_VERSION 0x01
spastor 0:1c358ea10753 18 #define MSG_COMPRESSION_NONE 0x00
spastor 0:1c358ea10753 19 #define MSG_COMPRESSION_LIBZ 0xFF
spastor 0:1c358ea10753 20
spastor 0:1c358ea10753 21 #define MSG_INVALID_CLIENT_SESSION 0xFFFF
spastor 0:1c358ea10753 22
spastor 0:1c358ea10753 23 #define MSG_FLAG_REQUEST UINT32_C(0x01)
spastor 0:1c358ea10753 24 #define MSG_FLAG_LAST_DATA UINT32_C(0x02)
spastor 0:1c358ea10753 25 #define MSG_FLAG_SENDER UINT32_C(0x04)
spastor 0:1c358ea10753 26
spastor 0:1c358ea10753 27 #define MSG_FLAG_CLIENT_OWNED UINT32_C(0x20)
spastor 0:1c358ea10753 28 #define MSG_FLAG_RECEIVING UINT32_C(0x40)
spastor 0:1c358ea10753 29 #define MSG_FLAG_START UINT32_C(0x80)
spastor 0:1c358ea10753 30 #define MSG_FLAG_ACK_PENDING UINT32_C(0x100)
spastor 0:1c358ea10753 31 #define MSG_FLAG_COMPRESSED UINT32_C(0x200)
spastor 0:1c358ea10753 32 #define MSG_FLAG_INFLATED UINT32_C(0x400)
spastor 0:1c358ea10753 33 #define MSG_FLAG_DEFLATED UINT32_C(0x800)
spastor 0:1c358ea10753 34 #define MSG_FLAG_SEND_NOW UINT32_C(0x1000)
spastor 0:1c358ea10753 35 #define MSG_FLAG_DOUBLE_BUF UINT32_C(0x2000)
spastor 0:1c358ea10753 36
spastor 0:1c358ea10753 37 #define MsgIsBitSet(flag, bit) (connector_bool(((flag) & (bit)) == (bit)))
spastor 0:1c358ea10753 38 #define MsgIsBitClear(flag, bit) (connector_bool(((flag) & (bit)) == 0))
spastor 0:1c358ea10753 39 #define MsgBitSet(flag, bit) ((flag) |= (bit))
spastor 0:1c358ea10753 40 #define MsgBitClear(flag, bit) ((flag) &= ~(bit))
spastor 0:1c358ea10753 41
spastor 0:1c358ea10753 42 #define MsgIsRequest(flag) MsgIsBitSet((flag), MSG_FLAG_REQUEST)
spastor 0:1c358ea10753 43 #define MsgIsLastData(flag) MsgIsBitSet((flag), MSG_FLAG_LAST_DATA)
spastor 0:1c358ea10753 44 #define MsgIsSender(flag) MsgIsBitSet((flag), MSG_FLAG_SENDER)
spastor 0:1c358ea10753 45 #define MsgIsReceiving(flag) MsgIsBitSet((flag), MSG_FLAG_RECEIVING)
spastor 0:1c358ea10753 46 #define MsgIsCompressed(flag) MsgIsBitSet((flag), MSG_FLAG_COMPRESSED)
spastor 0:1c358ea10753 47 #define MsgIsStart(flag) MsgIsBitSet((flag), MSG_FLAG_START)
spastor 0:1c358ea10753 48 #define MsgIsAckPending(flag) MsgIsBitSet((flag), MSG_FLAG_ACK_PENDING)
spastor 0:1c358ea10753 49 #define MsgIsClientOwned(flag) MsgIsBitSet((flag), MSG_FLAG_CLIENT_OWNED)
spastor 0:1c358ea10753 50 #define MsgIsInflated(flag) MsgIsBitSet((flag), MSG_FLAG_INFLATED)
spastor 0:1c358ea10753 51 #define MsgIsDeflated(flag) MsgIsBitSet((flag), MSG_FLAG_DEFLATED)
spastor 0:1c358ea10753 52 #define MsgIsSendNow(flag) MsgIsBitSet((flag), MSG_FLAG_SEND_NOW)
spastor 0:1c358ea10753 53 #define MsgIsDoubleBuf(flag) MsgIsBitSet((flag), MSG_FLAG_DOUBLE_BUF)
spastor 0:1c358ea10753 54
spastor 0:1c358ea10753 55 #define MsgIsNotRequest(flag) MsgIsBitClear((flag), MSG_FLAG_REQUEST)
spastor 0:1c358ea10753 56 #define MsgIsNotLastData(flag) MsgIsBitClear((flag), MSG_FLAG_LAST_DATA)
spastor 0:1c358ea10753 57 #define MsgIsNotSender(flag) MsgIsBitClear((flag), MSG_FLAG_SENDER)
spastor 0:1c358ea10753 58 #define MsgIsNotReceiving(flag) MsgIsBitClear((flag), MSG_FLAG_RECEIVING)
spastor 0:1c358ea10753 59 #define MsgIsNotClientOwned(flag) MsgIsBitClear((flag), MSG_FLAG_CLIENT_OWNED)
spastor 0:1c358ea10753 60 #define MsgIsNotInflated(flag) MsgIsBitClear((flag), MSG_FLAG_INFLATED)
spastor 0:1c358ea10753 61 #define MsgIsNotDeflated(flag) MsgIsBitClear((flag), MSG_FLAG_DEFLATED)
spastor 0:1c358ea10753 62
spastor 0:1c358ea10753 63 #define MsgSetRequest(flag) MsgBitSet((flag), MSG_FLAG_REQUEST)
spastor 0:1c358ea10753 64 #define MsgSetLastData(flag) MsgBitSet((flag), MSG_FLAG_LAST_DATA)
spastor 0:1c358ea10753 65 #define MsgSetSender(flag) MsgBitSet((flag), MSG_FLAG_SENDER)
spastor 0:1c358ea10753 66 #define MsgSetReceiving(flag) MsgBitSet((flag), MSG_FLAG_RECEIVING)
spastor 0:1c358ea10753 67 #define MsgSetCompression(flag) MsgBitSet((flag), MSG_FLAG_COMPRESSED)
spastor 0:1c358ea10753 68 #define MsgSetStart(flag) MsgBitSet((flag), MSG_FLAG_START)
spastor 0:1c358ea10753 69 #define MsgSetAckPending(flag) MsgBitSet((flag), MSG_FLAG_ACK_PENDING)
spastor 0:1c358ea10753 70 #define MsgSetClientOwned(flag) MsgBitSet((flag), MSG_FLAG_CLIENT_OWNED)
spastor 0:1c358ea10753 71 #define MsgSetInflated(flag) MsgBitSet((flag), MSG_FLAG_INFLATED)
spastor 0:1c358ea10753 72 #define MsgSetDeflated(flag) MsgBitSet((flag), MSG_FLAG_DEFLATED)
spastor 0:1c358ea10753 73 #define MsgSetSendNow(flag) MsgBitSet((flag), MSG_FLAG_SEND_NOW)
spastor 0:1c358ea10753 74 #define MsgSetDoubleBuf(flag) MsgBitSet((flag), MSG_FLAG_DOUBLE_BUF)
spastor 0:1c358ea10753 75
spastor 0:1c358ea10753 76 #define MsgClearRequest(flag) MsgBitClear((flag), MSG_FLAG_REQUEST)
spastor 0:1c358ea10753 77 #define MsgClearLastData(flag) MsgBitClear((flag), MSG_FLAG_LAST_DATA)
spastor 0:1c358ea10753 78 #define MsgClearReceiving(flag) MsgBitClear((flag), MSG_FLAG_RECEIVING)
spastor 0:1c358ea10753 79 #define MsgClearStart(flag) MsgBitClear((flag), MSG_FLAG_START)
spastor 0:1c358ea10753 80 #define MsgClearAckPending(flag) MsgBitClear((flag), MSG_FLAG_ACK_PENDING)
spastor 0:1c358ea10753 81 #define MsgClearCompression(flag) MsgBitClear((flag), MSG_FLAG_COMPRESSED)
spastor 0:1c358ea10753 82 #define MsgClearInflated(flag) MsgBitClear((flag), MSG_FLAG_INFLATED)
spastor 0:1c358ea10753 83 #define MsgClearDeflated(flag) MsgBitClear((flag), MSG_FLAG_DEFLATED)
spastor 0:1c358ea10753 84 #define MsgClearSendNow(flag) MsgBitClear((flag), MSG_FLAG_SEND_NOW)
spastor 0:1c358ea10753 85
spastor 0:1c358ea10753 86 typedef enum
spastor 0:1c358ea10753 87 {
spastor 0:1c358ea10753 88 msg_service_id_none,
spastor 0:1c358ea10753 89 msg_service_id_data,
spastor 0:1c358ea10753 90 msg_service_id_file,
spastor 0:1c358ea10753 91 msg_service_id_rci,
spastor 0:1c358ea10753 92 msg_service_id_brci,
spastor 0:1c358ea10753 93 msg_service_id_count
spastor 0:1c358ea10753 94 } msg_service_id_t;
spastor 0:1c358ea10753 95
spastor 0:1c358ea10753 96 typedef enum
spastor 0:1c358ea10753 97 {
spastor 0:1c358ea10753 98 msg_opcode_capability,
spastor 0:1c358ea10753 99 msg_opcode_start,
spastor 0:1c358ea10753 100 msg_opcode_data,
spastor 0:1c358ea10753 101 msg_opcode_ack,
spastor 0:1c358ea10753 102 msg_opcode_error
spastor 0:1c358ea10753 103 } msg_opcode_t;
spastor 0:1c358ea10753 104
spastor 0:1c358ea10753 105 typedef enum
spastor 0:1c358ea10753 106 {
spastor 0:1c358ea10753 107 msg_block_state_send_request,
spastor 0:1c358ea10753 108 msg_block_state_recv_request,
spastor 0:1c358ea10753 109 msg_block_state_send_response,
spastor 0:1c358ea10753 110 msg_block_state_recv_response
spastor 0:1c358ea10753 111 } msg_block_state_t;
spastor 0:1c358ea10753 112
spastor 0:1c358ea10753 113 typedef enum
spastor 0:1c358ea10753 114 {
spastor 0:1c358ea10753 115 msg_state_init,
spastor 0:1c358ea10753 116 msg_state_get_data,
spastor 0:1c358ea10753 117 msg_state_compress,
spastor 0:1c358ea10753 118 msg_state_send_data,
spastor 0:1c358ea10753 119 msg_state_wait_send_complete,
spastor 0:1c358ea10753 120 msg_state_wait_ack,
spastor 0:1c358ea10753 121 msg_state_receive,
spastor 0:1c358ea10753 122 msg_state_decompress,
spastor 0:1c358ea10753 123 msg_state_process_decompressed,
spastor 0:1c358ea10753 124 msg_state_send_ack,
spastor 0:1c358ea10753 125 msg_state_send_error,
spastor 0:1c358ea10753 126 msg_state_delete
spastor 0:1c358ea10753 127 } msg_state_t;
spastor 0:1c358ea10753 128
spastor 0:1c358ea10753 129 typedef enum
spastor 0:1c358ea10753 130 {
spastor 0:1c358ea10753 131 msg_service_type_need_data,
spastor 0:1c358ea10753 132 msg_service_type_have_data,
spastor 0:1c358ea10753 133 msg_service_type_error,
spastor 0:1c358ea10753 134 msg_service_type_free,
spastor 0:1c358ea10753 135 msg_service_type_pending_request
spastor 0:1c358ea10753 136 } msg_service_type_t;
spastor 0:1c358ea10753 137
spastor 0:1c358ea10753 138 typedef enum
spastor 0:1c358ea10753 139 {
spastor 0:1c358ea10753 140 msg_capability_cloud,
spastor 0:1c358ea10753 141 msg_capability_client,
spastor 0:1c358ea10753 142 msg_capability_count
spastor 0:1c358ea10753 143 } msg_capability_type_t;
spastor 0:1c358ea10753 144
spastor 0:1c358ea10753 145 enum msg_capability_packet_t
spastor 0:1c358ea10753 146 {
spastor 0:1c358ea10753 147 field_define(capability_packet, opcode, uint8_t),
spastor 0:1c358ea10753 148 field_define(capability_packet, flags, uint8_t),
spastor 0:1c358ea10753 149 field_define(capability_packet, version, uint8_t),
spastor 0:1c358ea10753 150 field_define(capability_packet, max_transactions, uint8_t),
spastor 0:1c358ea10753 151 field_define(capability_packet, window_size, uint32_t),
spastor 0:1c358ea10753 152 field_define(capability_packet, compression_count, uint8_t),
spastor 0:1c358ea10753 153 record_end(capability_packet)
spastor 0:1c358ea10753 154 };
spastor 0:1c358ea10753 155
spastor 0:1c358ea10753 156 enum msg_start_packet_t
spastor 0:1c358ea10753 157 {
spastor 0:1c358ea10753 158 field_define(start_packet, opcode, uint8_t),
spastor 0:1c358ea10753 159 field_define(start_packet, flags, uint8_t),
spastor 0:1c358ea10753 160 field_define(start_packet, transaction_id, uint16_t),
spastor 0:1c358ea10753 161 field_define(start_packet, service_id, uint16_t),
spastor 0:1c358ea10753 162 field_define(start_packet, compression_id, uint8_t),
spastor 0:1c358ea10753 163 record_end(start_packet)
spastor 0:1c358ea10753 164 };
spastor 0:1c358ea10753 165
spastor 0:1c358ea10753 166 enum msg_data_packet_t
spastor 0:1c358ea10753 167 {
spastor 0:1c358ea10753 168 field_define(data_packet, opcode, uint8_t),
spastor 0:1c358ea10753 169 field_define(data_packet, flags, uint8_t),
spastor 0:1c358ea10753 170 field_define(data_packet, transaction_id, uint16_t),
spastor 0:1c358ea10753 171 record_end(data_packet)
spastor 0:1c358ea10753 172 };
spastor 0:1c358ea10753 173
spastor 0:1c358ea10753 174 enum msg_ack_packet_t
spastor 0:1c358ea10753 175 {
spastor 0:1c358ea10753 176 field_define(ack_packet, opcode, uint8_t),
spastor 0:1c358ea10753 177 field_define(ack_packet, flags, uint8_t),
spastor 0:1c358ea10753 178 field_define(ack_packet, transaction_id, uint16_t),
spastor 0:1c358ea10753 179 field_define(ack_packet, ack_count, uint32_t),
spastor 0:1c358ea10753 180 field_define(ack_packet, window_size, uint32_t),
spastor 0:1c358ea10753 181 record_end(ack_packet)
spastor 0:1c358ea10753 182 };
spastor 0:1c358ea10753 183
spastor 0:1c358ea10753 184 enum msg_error_packet_t
spastor 0:1c358ea10753 185 {
spastor 0:1c358ea10753 186 field_define(error_packet, opcode, uint8_t),
spastor 0:1c358ea10753 187 field_define(error_packet, flags, uint8_t),
spastor 0:1c358ea10753 188 field_define(error_packet, transaction_id, uint16_t),
spastor 0:1c358ea10753 189 field_define(error_packet, error_code, uint8_t),
spastor 0:1c358ea10753 190 record_end(error_packet)
spastor 0:1c358ea10753 191 };
spastor 0:1c358ea10753 192
spastor 0:1c358ea10753 193 typedef struct msg_data_block_t
spastor 0:1c358ea10753 194 {
spastor 0:1c358ea10753 195 size_t total_bytes;
spastor 0:1c358ea10753 196 size_t available_window;
spastor 0:1c358ea10753 197 size_t ack_count;
spastor 0:1c358ea10753 198 unsigned int status_flag;
spastor 0:1c358ea10753 199 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 200 uint8_t buffer_in[MSG_MAX_RECV_PACKET_SIZE];
spastor 0:1c358ea10753 201 uint8_t buffer_out[MSG_MAX_RECV_PACKET_SIZE];
spastor 0:1c358ea10753 202 size_t bytes_out;
spastor 0:1c358ea10753 203 int z_flag;
spastor 0:1c358ea10753 204 z_stream zlib;
spastor 0:1c358ea10753 205 #endif
spastor 0:1c358ea10753 206 } msg_data_block_t;
spastor 0:1c358ea10753 207
spastor 0:1c358ea10753 208 typedef struct
spastor 0:1c358ea10753 209 {
spastor 0:1c358ea10753 210 void * data_ptr;
spastor 0:1c358ea10753 211 size_t length_in_bytes;
spastor 0:1c358ea10753 212 unsigned int flags;
spastor 0:1c358ea10753 213 } msg_service_data_t;
spastor 0:1c358ea10753 214
spastor 0:1c358ea10753 215 typedef struct
spastor 0:1c358ea10753 216 {
spastor 0:1c358ea10753 217 void * session;
spastor 0:1c358ea10753 218 msg_service_type_t service_type;
spastor 0:1c358ea10753 219 msg_service_data_t * need_data;
spastor 0:1c358ea10753 220 msg_service_data_t * have_data;
spastor 0:1c358ea10753 221 connector_session_error_t error_value;
spastor 0:1c358ea10753 222 } msg_service_request_t;
spastor 0:1c358ea10753 223
spastor 0:1c358ea10753 224 typedef struct msg_session_t
spastor 0:1c358ea10753 225 {
spastor 0:1c358ea10753 226 unsigned int session_id;
spastor 0:1c358ea10753 227 unsigned int service_id;
spastor 0:1c358ea10753 228 void * service_context;
spastor 0:1c358ea10753 229 msg_state_t current_state;
spastor 0:1c358ea10753 230 msg_state_t saved_state;
spastor 0:1c358ea10753 231 uint8_t * send_data_ptr;
spastor 0:1c358ea10753 232 size_t send_data_bytes;
spastor 0:1c358ea10753 233 msg_data_block_t * in_dblock;
spastor 0:1c358ea10753 234 msg_data_block_t * out_dblock;
spastor 0:1c358ea10753 235 connector_session_error_t error;
spastor 0:1c358ea10753 236 unsigned int error_flag;
spastor 0:1c358ea10753 237 msg_service_request_t service_layer_data;
spastor 0:1c358ea10753 238 struct msg_session_t * next;
spastor 0:1c358ea10753 239 struct msg_session_t * prev;
spastor 0:1c358ea10753 240 } msg_session_t;
spastor 0:1c358ea10753 241
spastor 0:1c358ea10753 242 typedef connector_status_t connector_msg_callback_t(connector_data_t * const connector_ptr, msg_service_request_t * const service_request);
spastor 0:1c358ea10753 243
spastor 0:1c358ea10753 244 typedef struct
spastor 0:1c358ea10753 245 {
spastor 0:1c358ea10753 246 uint32_t window_size;
spastor 0:1c358ea10753 247 connector_bool_t compression_supported;
spastor 0:1c358ea10753 248 uint8_t active_transactions;
spastor 0:1c358ea10753 249 uint8_t max_transactions;
spastor 0:1c358ea10753 250 } msg_capabilities_t;
spastor 0:1c358ea10753 251
spastor 0:1c358ea10753 252 typedef struct
spastor 0:1c358ea10753 253 {
spastor 0:1c358ea10753 254 msg_capabilities_t capabilities[msg_capability_count];
spastor 0:1c358ea10753 255 connector_msg_callback_t * service_cb[msg_service_id_count];
spastor 0:1c358ea10753 256 connector_bool_t session_locked;
spastor 0:1c358ea10753 257 struct
spastor 0:1c358ea10753 258 {
spastor 0:1c358ea10753 259 msg_session_t * head;
spastor 0:1c358ea10753 260 msg_session_t * tail;
spastor 0:1c358ea10753 261 msg_session_t * current;
spastor 0:1c358ea10753 262 } session;
spastor 0:1c358ea10753 263 unsigned int last_assigned_id;
spastor 0:1c358ea10753 264 void const * pending_service_request;
spastor 0:1c358ea10753 265 } connector_msg_data_t;
spastor 0:1c358ea10753 266
spastor 0:1c358ea10753 267 static msg_session_t * msg_find_session(connector_msg_data_t const * const msg_ptr, unsigned int const id, connector_bool_t const client_owned)
spastor 0:1c358ea10753 268 {
spastor 0:1c358ea10753 269 msg_session_t * session = msg_ptr->session.head;
spastor 0:1c358ea10753 270
spastor 0:1c358ea10753 271 while (session != NULL)
spastor 0:1c358ea10753 272 {
spastor 0:1c358ea10753 273 if (session->session_id == id)
spastor 0:1c358ea10753 274 {
spastor 0:1c358ea10753 275 unsigned int const status = (session->in_dblock != NULL) ? session->in_dblock->status_flag : session->out_dblock->status_flag;
spastor 0:1c358ea10753 276
spastor 0:1c358ea10753 277 if (MsgIsClientOwned(status) == client_owned)
spastor 0:1c358ea10753 278 break;
spastor 0:1c358ea10753 279 }
spastor 0:1c358ea10753 280
spastor 0:1c358ea10753 281 session = session->next;
spastor 0:1c358ea10753 282 }
spastor 0:1c358ea10753 283
spastor 0:1c358ea10753 284 return session;
spastor 0:1c358ea10753 285 }
spastor 0:1c358ea10753 286
spastor 0:1c358ea10753 287 static unsigned int msg_find_next_available_id(connector_msg_data_t * const msg_ptr)
spastor 0:1c358ea10753 288 {
spastor 0:1c358ea10753 289 unsigned int new_id = MSG_INVALID_CLIENT_SESSION;
spastor 0:1c358ea10753 290 unsigned int const last_id = msg_ptr->last_assigned_id;
spastor 0:1c358ea10753 291
spastor 0:1c358ea10753 292 do
spastor 0:1c358ea10753 293 {
spastor 0:1c358ea10753 294 connector_bool_t const client_owned = connector_true;
spastor 0:1c358ea10753 295
spastor 0:1c358ea10753 296 msg_ptr->last_assigned_id++;
spastor 0:1c358ea10753 297 if (msg_ptr->last_assigned_id >= MSG_INVALID_CLIENT_SESSION)
spastor 0:1c358ea10753 298 {
spastor 0:1c358ea10753 299 msg_ptr->last_assigned_id = 0;
spastor 0:1c358ea10753 300 continue;
spastor 0:1c358ea10753 301 }
spastor 0:1c358ea10753 302
spastor 0:1c358ea10753 303 if (msg_find_session(msg_ptr, msg_ptr->last_assigned_id, client_owned) == NULL)
spastor 0:1c358ea10753 304 {
spastor 0:1c358ea10753 305 new_id = msg_ptr->last_assigned_id;
spastor 0:1c358ea10753 306 break;
spastor 0:1c358ea10753 307 }
spastor 0:1c358ea10753 308
spastor 0:1c358ea10753 309 } while (msg_ptr->last_assigned_id != last_id);
spastor 0:1c358ea10753 310
spastor 0:1c358ea10753 311 return new_id;
spastor 0:1c358ea10753 312 }
spastor 0:1c358ea10753 313
spastor 0:1c358ea10753 314 static void msg_set_error(msg_session_t * const session, connector_session_error_t const error_code)
spastor 0:1c358ea10753 315 {
spastor 0:1c358ea10753 316 msg_data_block_t * const dblock = (session->in_dblock != NULL) ? session->in_dblock : session->out_dblock;
spastor 0:1c358ea10753 317 connector_bool_t const client_request_error = connector_bool(MsgIsClientOwned(dblock->status_flag) && MsgIsNotReceiving(dblock->status_flag));
spastor 0:1c358ea10753 318 connector_bool_t const client_response_error = connector_bool(MsgIsNotClientOwned(dblock->status_flag) && MsgIsNotReceiving(dblock->status_flag));
spastor 0:1c358ea10753 319 connector_bool_t const cloud_request_error = connector_bool(MsgIsNotClientOwned(dblock->status_flag) && MsgIsReceiving(dblock->status_flag));
spastor 0:1c358ea10753 320
spastor 0:1c358ea10753 321 if (client_request_error && MsgIsStart(dblock->status_flag))
spastor 0:1c358ea10753 322 {
spastor 0:1c358ea10753 323 /* no need to send an error. just delete since nothing has been sent to Device Cloud */
spastor 0:1c358ea10753 324 session->current_state = msg_state_delete;
spastor 0:1c358ea10753 325 goto done;
spastor 0:1c358ea10753 326 }
spastor 0:1c358ea10753 327
spastor 0:1c358ea10753 328 session->error = error_code;
spastor 0:1c358ea10753 329 session->current_state = msg_state_send_error;
spastor 0:1c358ea10753 330
spastor 0:1c358ea10753 331 if (client_response_error && MsgIsStart(dblock->status_flag))
spastor 0:1c358ea10753 332 {
spastor 0:1c358ea10753 333 /* canceling Device Cloud request since no response data has been sent yet */
spastor 0:1c358ea10753 334 MsgSetRequest(session->error_flag);
spastor 0:1c358ea10753 335 goto done;
spastor 0:1c358ea10753 336 }
spastor 0:1c358ea10753 337
spastor 0:1c358ea10753 338 if (client_request_error || cloud_request_error)
spastor 0:1c358ea10753 339 MsgSetRequest(session->error_flag);
spastor 0:1c358ea10753 340
spastor 0:1c358ea10753 341 if (client_request_error || client_response_error)
spastor 0:1c358ea10753 342 MsgSetSender(session->error_flag);
spastor 0:1c358ea10753 343
spastor 0:1c358ea10753 344 done:
spastor 0:1c358ea10753 345 return;
spastor 0:1c358ea10753 346 }
spastor 0:1c358ea10753 347
spastor 0:1c358ea10753 348 static connector_status_t msg_call_service_layer(connector_data_t * const connector_ptr, msg_session_t * const session, msg_service_type_t const type)
spastor 0:1c358ea10753 349 {
spastor 0:1c358ea10753 350 connector_status_t status = connector_init_error;
spastor 0:1c358ea10753 351 msg_service_request_t * const service_ptr = &session->service_layer_data;
spastor 0:1c358ea10753 352 connector_msg_data_t * const msg_ptr = get_facility_data(connector_ptr, E_MSG_FAC_MSG_NUM);
spastor 0:1c358ea10753 353 connector_msg_callback_t * cb_fn;
spastor 0:1c358ea10753 354
spastor 0:1c358ea10753 355 ASSERT_GOTO(msg_ptr != NULL, error);
spastor 0:1c358ea10753 356 cb_fn = msg_ptr->service_cb[session->service_id];
spastor 0:1c358ea10753 357 ASSERT_GOTO(cb_fn != NULL, error);
spastor 0:1c358ea10753 358
spastor 0:1c358ea10753 359 service_ptr->service_type = type;
spastor 0:1c358ea10753 360 service_ptr->session = session;
spastor 0:1c358ea10753 361
spastor 0:1c358ea10753 362 status = cb_fn(connector_ptr, service_ptr);
spastor 0:1c358ea10753 363 if ((status == connector_working) && (service_ptr->service_type == msg_service_type_error))
spastor 0:1c358ea10753 364 {
spastor 0:1c358ea10753 365 msg_set_error(session, service_ptr->error_value);
spastor 0:1c358ea10753 366 status = connector_unavailable;
spastor 0:1c358ea10753 367 }
spastor 0:1c358ea10753 368
spastor 0:1c358ea10753 369 error:
spastor 0:1c358ea10753 370 return status;
spastor 0:1c358ea10753 371 }
spastor 0:1c358ea10753 372
spastor 0:1c358ea10753 373 static connector_status_t msg_inform_error(connector_data_t * const connector_ptr, msg_session_t * const session, connector_session_error_t error_code)
spastor 0:1c358ea10753 374 {
spastor 0:1c358ea10753 375 session->service_layer_data.error_value = error_code;
spastor 0:1c358ea10753 376
spastor 0:1c358ea10753 377 return msg_call_service_layer(connector_ptr, session, msg_service_type_error);
spastor 0:1c358ea10753 378 }
spastor 0:1c358ea10753 379
spastor 0:1c358ea10753 380 static msg_session_t * msg_create_session(connector_data_t * const connector_ptr, connector_msg_data_t * const msg_ptr, unsigned int const service_id,
spastor 0:1c358ea10753 381 connector_bool_t const client_owned, connector_status_t * const status)
spastor 0:1c358ea10753 382 {
spastor 0:1c358ea10753 383 unsigned int session_id = MSG_INVALID_CLIENT_SESSION;
spastor 0:1c358ea10753 384 msg_capability_type_t const capability_id = client_owned == connector_true ? msg_capability_cloud : msg_capability_client;
spastor 0:1c358ea10753 385 msg_session_t * session = NULL;
spastor 0:1c358ea10753 386 unsigned int flags = 0;
spastor 0:1c358ea10753 387
spastor 0:1c358ea10753 388 *status = connector_pending;
spastor 0:1c358ea10753 389 ASSERT_GOTO(msg_ptr != NULL, done);
spastor 0:1c358ea10753 390
spastor 0:1c358ea10753 391 {
spastor 0:1c358ea10753 392 uint8_t const max_transactions = msg_ptr->capabilities[capability_id].max_transactions;
spastor 0:1c358ea10753 393 uint8_t const active_transactions = msg_ptr->capabilities[capability_id].active_transactions;
spastor 0:1c358ea10753 394 uint8_t const unlimited_transactions = 0;
spastor 0:1c358ea10753 395
spastor 0:1c358ea10753 396 if ((max_transactions != unlimited_transactions) && (active_transactions >= max_transactions))
spastor 0:1c358ea10753 397 {
spastor 0:1c358ea10753 398 connector_debug_printf("msg_create_session: active transactions reached the limit [%d], service id [%d]\n", active_transactions, max_transactions, service_id);
spastor 0:1c358ea10753 399 goto done;
spastor 0:1c358ea10753 400 }
spastor 0:1c358ea10753 401 }
spastor 0:1c358ea10753 402
spastor 0:1c358ea10753 403 if (client_owned == connector_true)
spastor 0:1c358ea10753 404 {
spastor 0:1c358ea10753 405 session_id = msg_find_next_available_id(msg_ptr);
spastor 0:1c358ea10753 406 if (session_id == MSG_INVALID_CLIENT_SESSION) goto done;
spastor 0:1c358ea10753 407 MsgSetClientOwned(flags);
spastor 0:1c358ea10753 408 }
spastor 0:1c358ea10753 409
spastor 0:1c358ea10753 410 MsgSetRequest(flags);
spastor 0:1c358ea10753 411 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 412 MsgSetCompression(flags);
spastor 0:1c358ea10753 413 #endif
spastor 0:1c358ea10753 414
spastor 0:1c358ea10753 415 switch (service_id)
spastor 0:1c358ea10753 416 {
spastor 0:1c358ea10753 417 case msg_service_id_rci:
spastor 0:1c358ea10753 418 case msg_service_id_brci:
spastor 0:1c358ea10753 419 MsgSetDoubleBuf(flags);
spastor 0:1c358ea10753 420 break;
spastor 0:1c358ea10753 421
spastor 0:1c358ea10753 422 default:
spastor 0:1c358ea10753 423 break;
spastor 0:1c358ea10753 424 }
spastor 0:1c358ea10753 425
spastor 0:1c358ea10753 426 {
spastor 0:1c358ea10753 427 void * ptr;
spastor 0:1c358ea10753 428 uint8_t * data_ptr;
spastor 0:1c358ea10753 429 size_t const bytes_in_block = sizeof(msg_data_block_t);
spastor 0:1c358ea10753 430 size_t const bytes_in_service_data = sizeof(msg_service_data_t);
spastor 0:1c358ea10753 431 size_t const bytes_in_session = sizeof *session;
spastor 0:1c358ea10753 432 size_t const single_buffer_bytes = bytes_in_block + bytes_in_service_data;
spastor 0:1c358ea10753 433 size_t const double_buffer_bytes = MsgIsCompressed(flags) ? 2 * single_buffer_bytes : (2 * single_buffer_bytes) + MSG_MAX_SEND_PACKET_SIZE;
spastor 0:1c358ea10753 434 size_t const total_bytes = bytes_in_session + (MsgIsDoubleBuf(flags) ? double_buffer_bytes : single_buffer_bytes);
spastor 0:1c358ea10753 435 connector_static_buffer_id_t buffer_id = client_owned == connector_true ? named_buffer_id(msg_session_client) : named_buffer_id(msg_session);
spastor 0:1c358ea10753 436
spastor 0:1c358ea10753 437 *status = malloc_data_buffer(connector_ptr, total_bytes, buffer_id, &ptr);
spastor 0:1c358ea10753 438 if (*status != connector_working) goto done;
spastor 0:1c358ea10753 439
spastor 0:1c358ea10753 440 data_ptr = ptr;
spastor 0:1c358ea10753 441 session = ptr;
spastor 0:1c358ea10753 442 data_ptr += bytes_in_session;
spastor 0:1c358ea10753 443
spastor 0:1c358ea10753 444 if (MsgIsDoubleBuf(flags))
spastor 0:1c358ea10753 445 {
spastor 0:1c358ea10753 446 session->out_dblock = (msg_data_block_t *)(session + 1);
spastor 0:1c358ea10753 447 session->in_dblock = session->out_dblock + 1;
spastor 0:1c358ea10753 448 data_ptr += (2 * bytes_in_block);
spastor 0:1c358ea10753 449 session->service_layer_data.have_data = (msg_service_data_t *)(session->in_dblock + 1);
spastor 0:1c358ea10753 450 session->service_layer_data.need_data = session->service_layer_data.have_data + 1;
spastor 0:1c358ea10753 451 data_ptr += (2 * bytes_in_service_data);
spastor 0:1c358ea10753 452 session->send_data_ptr = MsgIsCompressed(flags) ? NULL : data_ptr;
spastor 0:1c358ea10753 453 }
spastor 0:1c358ea10753 454 else
spastor 0:1c358ea10753 455 {
spastor 0:1c358ea10753 456 msg_data_block_t ** const current_dblock_ptr = client_owned == connector_true ? &session->out_dblock : &session->in_dblock;
spastor 0:1c358ea10753 457 msg_data_block_t ** const other_dblock_ptr = client_owned == connector_true ? &session->in_dblock : &session->out_dblock;
spastor 0:1c358ea10753 458
spastor 0:1c358ea10753 459 *current_dblock_ptr = (msg_data_block_t *)(session + 1);
spastor 0:1c358ea10753 460 *other_dblock_ptr = NULL;
spastor 0:1c358ea10753 461 data_ptr += bytes_in_block;
spastor 0:1c358ea10753 462 session->service_layer_data.need_data = (msg_service_data_t *)(client_owned == connector_true ? (*current_dblock_ptr) + 1 : NULL);
spastor 0:1c358ea10753 463 session->service_layer_data.have_data = (msg_service_data_t *)(client_owned == connector_true ? NULL : (*current_dblock_ptr) + 1);
spastor 0:1c358ea10753 464 session->send_data_ptr = NULL;
spastor 0:1c358ea10753 465 }
spastor 0:1c358ea10753 466 }
spastor 0:1c358ea10753 467
spastor 0:1c358ea10753 468 session->session_id = session_id;
spastor 0:1c358ea10753 469 session->service_id = service_id;
spastor 0:1c358ea10753 470 session->error = connector_session_error_none;
spastor 0:1c358ea10753 471 session->service_layer_data.error_value = connector_session_error_none;
spastor 0:1c358ea10753 472 session->error_flag = 0;
spastor 0:1c358ea10753 473 session->send_data_bytes = 0;
spastor 0:1c358ea10753 474 session->service_context = NULL;
spastor 0:1c358ea10753 475 session->current_state = msg_state_init;
spastor 0:1c358ea10753 476 session->saved_state = msg_state_init;
spastor 0:1c358ea10753 477
spastor 0:1c358ea10753 478 if (session->out_dblock != NULL)
spastor 0:1c358ea10753 479 session->out_dblock->status_flag = flags;
spastor 0:1c358ea10753 480
spastor 0:1c358ea10753 481 if (session->in_dblock != NULL)
spastor 0:1c358ea10753 482 session->in_dblock->status_flag = flags;
spastor 0:1c358ea10753 483
spastor 0:1c358ea10753 484 if (msg_ptr->session_locked) goto error;
spastor 0:1c358ea10753 485 msg_ptr->session_locked = connector_true;
spastor 0:1c358ea10753 486 add_list_node(&msg_ptr->session.head, &msg_ptr->session.tail, session);
spastor 0:1c358ea10753 487 msg_ptr->session_locked = connector_false;
spastor 0:1c358ea10753 488
spastor 0:1c358ea10753 489 msg_ptr->capabilities[capability_id].active_transactions++;
spastor 0:1c358ea10753 490 *status = connector_working;
spastor 0:1c358ea10753 491 goto done;
spastor 0:1c358ea10753 492
spastor 0:1c358ea10753 493 error:
spastor 0:1c358ea10753 494 {
spastor 0:1c358ea10753 495 connector_status_t const result = free_data_buffer(connector_ptr, named_buffer_id(msg_session), session);
spastor 0:1c358ea10753 496
spastor 0:1c358ea10753 497 *status = (result == connector_abort) ? connector_abort : connector_pending;
spastor 0:1c358ea10753 498 session = NULL;
spastor 0:1c358ea10753 499 }
spastor 0:1c358ea10753 500
spastor 0:1c358ea10753 501 done:
spastor 0:1c358ea10753 502 return session;
spastor 0:1c358ea10753 503 }
spastor 0:1c358ea10753 504
spastor 0:1c358ea10753 505 static connector_status_t msg_delete_session(connector_data_t * const connector_ptr, connector_msg_data_t * const msg_ptr, msg_session_t * const session)
spastor 0:1c358ea10753 506 {
spastor 0:1c358ea10753 507 connector_status_t status = connector_working;
spastor 0:1c358ea10753 508
spastor 0:1c358ea10753 509 ASSERT_GOTO(msg_ptr != NULL, error);
spastor 0:1c358ea10753 510 ASSERT_GOTO(session != NULL, error);
spastor 0:1c358ea10753 511 ASSERT_GOTO((session->in_dblock != NULL) || (session->out_dblock != NULL), error);
spastor 0:1c358ea10753 512
spastor 0:1c358ea10753 513 if (msg_ptr->session_locked) goto error;
spastor 0:1c358ea10753 514 msg_ptr->session_locked = connector_true;
spastor 0:1c358ea10753 515 remove_list_node(&msg_ptr->session.head, &msg_ptr->session.tail, session);
spastor 0:1c358ea10753 516 if (msg_ptr->session.current == session)
spastor 0:1c358ea10753 517 msg_ptr->session.current = (session->prev != NULL) ? session->prev : msg_ptr->session.tail;
spastor 0:1c358ea10753 518 msg_ptr->session_locked = connector_false;
spastor 0:1c358ea10753 519
spastor 0:1c358ea10753 520 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 521 {
spastor 0:1c358ea10753 522 if ((session->in_dblock != NULL) && MsgIsInflated(session->in_dblock->status_flag))
spastor 0:1c358ea10753 523 inflateEnd(&session->in_dblock->zlib);
spastor 0:1c358ea10753 524
spastor 0:1c358ea10753 525 if ((session->out_dblock != NULL) && MsgIsDeflated(session->out_dblock->status_flag))
spastor 0:1c358ea10753 526 deflateEnd(&session->out_dblock->zlib);
spastor 0:1c358ea10753 527 }
spastor 0:1c358ea10753 528 #endif
spastor 0:1c358ea10753 529
spastor 0:1c358ea10753 530 {
spastor 0:1c358ea10753 531 unsigned int const flag = (session->in_dblock != NULL) ? session->in_dblock->status_flag : session->out_dblock->status_flag;
spastor 0:1c358ea10753 532 msg_capability_type_t const capability_id = MsgIsClientOwned(flag) == connector_true ? msg_capability_cloud : msg_capability_client;
spastor 0:1c358ea10753 533
spastor 0:1c358ea10753 534 if (msg_ptr->capabilities[capability_id].active_transactions > 0)
spastor 0:1c358ea10753 535 {
spastor 0:1c358ea10753 536 msg_ptr->capabilities[capability_id].active_transactions--;
spastor 0:1c358ea10753 537 }
spastor 0:1c358ea10753 538 else
spastor 0:1c358ea10753 539 {
spastor 0:1c358ea10753 540 ASSERT(connector_false);
spastor 0:1c358ea10753 541 }
spastor 0:1c358ea10753 542 }
spastor 0:1c358ea10753 543
spastor 0:1c358ea10753 544 status = msg_call_service_layer(connector_ptr, session, msg_service_type_free);
spastor 0:1c358ea10753 545
spastor 0:1c358ea10753 546 {
spastor 0:1c358ea10753 547 connector_status_t const free_status = free_data_buffer(connector_ptr, named_buffer_id(msg_session), session);
spastor 0:1c358ea10753 548
spastor 0:1c358ea10753 549 if (status != connector_abort)
spastor 0:1c358ea10753 550 status = free_status;
spastor 0:1c358ea10753 551 }
spastor 0:1c358ea10753 552
spastor 0:1c358ea10753 553 error:
spastor 0:1c358ea10753 554 return status;
spastor 0:1c358ea10753 555 }
spastor 0:1c358ea10753 556
spastor 0:1c358ea10753 557 static void msg_default_data_block(msg_data_block_t * dblock, uint32_t const window_size)
spastor 0:1c358ea10753 558 {
spastor 0:1c358ea10753 559 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 560 dblock->bytes_out = 0;
spastor 0:1c358ea10753 561 dblock->z_flag = Z_NO_FLUSH;
spastor 0:1c358ea10753 562 #endif
spastor 0:1c358ea10753 563
spastor 0:1c358ea10753 564 dblock->available_window = window_size;
spastor 0:1c358ea10753 565 dblock->ack_count = 0;
spastor 0:1c358ea10753 566 dblock->total_bytes = 0;
spastor 0:1c358ea10753 567 MsgSetStart(dblock->status_flag);
spastor 0:1c358ea10753 568 MsgClearLastData(dblock->status_flag);
spastor 0:1c358ea10753 569 }
spastor 0:1c358ea10753 570
spastor 0:1c358ea10753 571 static connector_session_error_t msg_initialize_data_block(msg_session_t * const session, uint32_t const window_size, msg_block_state_t state)
spastor 0:1c358ea10753 572 {
spastor 0:1c358ea10753 573 connector_session_error_t result = connector_session_error_none;
spastor 0:1c358ea10753 574
spastor 0:1c358ea10753 575 ASSERT_GOTO(session != NULL, error);
spastor 0:1c358ea10753 576
spastor 0:1c358ea10753 577 switch(state)
spastor 0:1c358ea10753 578 {
spastor 0:1c358ea10753 579 case msg_block_state_send_response:
spastor 0:1c358ea10753 580 if (session->out_dblock == NULL)
spastor 0:1c358ea10753 581 {
spastor 0:1c358ea10753 582 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 583 ASSERT_GOTO(session->in_dblock != NULL, compression_error);
spastor 0:1c358ea10753 584 inflateEnd(&session->in_dblock->zlib);
spastor 0:1c358ea10753 585 MsgClearInflated(session->in_dblock->status_flag);
spastor 0:1c358ea10753 586 #endif
spastor 0:1c358ea10753 587 session->out_dblock = session->in_dblock;
spastor 0:1c358ea10753 588 ASSERT_GOTO(session->service_layer_data.have_data != NULL, error);
spastor 0:1c358ea10753 589 session->service_layer_data.need_data = session->service_layer_data.have_data;
spastor 0:1c358ea10753 590 session->in_dblock = NULL;
spastor 0:1c358ea10753 591 session->service_layer_data.have_data = NULL;
spastor 0:1c358ea10753 592 }
spastor 0:1c358ea10753 593 MsgClearRequest(session->out_dblock->status_flag);
spastor 0:1c358ea10753 594 /* intentional fall through */
spastor 0:1c358ea10753 595
spastor 0:1c358ea10753 596 case msg_block_state_send_request:
spastor 0:1c358ea10753 597 msg_default_data_block(session->out_dblock, window_size);
spastor 0:1c358ea10753 598 MsgClearReceiving(session->out_dblock->status_flag);
spastor 0:1c358ea10753 599 session->current_state = msg_state_get_data;
spastor 0:1c358ea10753 600 session->service_layer_data.need_data->data_ptr = NULL;
spastor 0:1c358ea10753 601 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 602 if (MsgIsNotDeflated(session->out_dblock->status_flag) == connector_true)
spastor 0:1c358ea10753 603 {
spastor 0:1c358ea10753 604 memset(&session->out_dblock->zlib, 0, sizeof session->out_dblock->zlib);
spastor 0:1c358ea10753 605 ASSERT_GOTO(deflateInit(&session->out_dblock->zlib, Z_DEFAULT_COMPRESSION) == Z_OK, compression_error);
spastor 0:1c358ea10753 606 MsgSetDeflated(session->out_dblock->status_flag);
spastor 0:1c358ea10753 607 }
spastor 0:1c358ea10753 608 #endif
spastor 0:1c358ea10753 609 break;
spastor 0:1c358ea10753 610
spastor 0:1c358ea10753 611 case msg_block_state_recv_response:
spastor 0:1c358ea10753 612 if (session->in_dblock == NULL)
spastor 0:1c358ea10753 613 {
spastor 0:1c358ea10753 614 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 615 ASSERT_GOTO(session->out_dblock != NULL, compression_error);
spastor 0:1c358ea10753 616 deflateEnd(&session->out_dblock->zlib);
spastor 0:1c358ea10753 617 MsgClearDeflated(session->out_dblock->status_flag);
spastor 0:1c358ea10753 618 #endif
spastor 0:1c358ea10753 619 session->in_dblock = session->out_dblock;
spastor 0:1c358ea10753 620 ASSERT_GOTO(session->service_layer_data.need_data != NULL, error);
spastor 0:1c358ea10753 621 session->service_layer_data.have_data = session->service_layer_data.need_data;
spastor 0:1c358ea10753 622 MsgClearRequest(session->in_dblock->status_flag);
spastor 0:1c358ea10753 623 session->out_dblock = NULL;
spastor 0:1c358ea10753 624 session->service_layer_data.need_data = NULL;
spastor 0:1c358ea10753 625 }
spastor 0:1c358ea10753 626 /* intentional fall through */
spastor 0:1c358ea10753 627
spastor 0:1c358ea10753 628 case msg_block_state_recv_request:
spastor 0:1c358ea10753 629 msg_default_data_block(session->in_dblock, window_size);
spastor 0:1c358ea10753 630 MsgSetReceiving(session->in_dblock->status_flag);
spastor 0:1c358ea10753 631 session->current_state = msg_state_receive;
spastor 0:1c358ea10753 632 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 633 if (MsgIsNotInflated(session->in_dblock->status_flag) == connector_true)
spastor 0:1c358ea10753 634 {
spastor 0:1c358ea10753 635 memset(&session->in_dblock->zlib, 0, sizeof session->in_dblock->zlib);
spastor 0:1c358ea10753 636 ASSERT_GOTO(inflateInit(&session->in_dblock->zlib) == Z_OK, compression_error);
spastor 0:1c358ea10753 637 MsgSetInflated(session->in_dblock->status_flag);
spastor 0:1c358ea10753 638 }
spastor 0:1c358ea10753 639 #endif
spastor 0:1c358ea10753 640 break;
spastor 0:1c358ea10753 641
spastor 0:1c358ea10753 642 default:
spastor 0:1c358ea10753 643 ASSERT_GOTO(connector_false, error);
spastor 0:1c358ea10753 644 break;
spastor 0:1c358ea10753 645 }
spastor 0:1c358ea10753 646
spastor 0:1c358ea10753 647 goto done;
spastor 0:1c358ea10753 648
spastor 0:1c358ea10753 649 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 650 compression_error:
spastor 0:1c358ea10753 651 result = connector_session_error_compression_failure;
spastor 0:1c358ea10753 652 #endif
spastor 0:1c358ea10753 653
spastor 0:1c358ea10753 654 error:
spastor 0:1c358ea10753 655 done:
spastor 0:1c358ea10753 656 return result;
spastor 0:1c358ea10753 657 }
spastor 0:1c358ea10753 658
spastor 0:1c358ea10753 659 static connector_status_t msg_send_error(connector_data_t * const connector_ptr, connector_msg_data_t * const msg_ptr, msg_session_t * const session, uint16_t const session_id, connector_session_error_t const error_value, uint8_t const flag)
spastor 0:1c358ea10753 660 {
spastor 0:1c358ea10753 661 connector_status_t status = connector_working;
spastor 0:1c358ea10753 662 uint8_t * error_packet;
spastor 0:1c358ea10753 663 uint8_t * const edp_header = tcp_get_packet_buffer(connector_ptr, E_MSG_FAC_MSG_NUM, &error_packet, NULL);
spastor 0:1c358ea10753 664
spastor 0:1c358ea10753 665 if (edp_header == NULL)
spastor 0:1c358ea10753 666 {
spastor 0:1c358ea10753 667 status = connector_pending;
spastor 0:1c358ea10753 668 goto done;
spastor 0:1c358ea10753 669 }
spastor 0:1c358ea10753 670
spastor 0:1c358ea10753 671 message_store_u8(error_packet, opcode, msg_opcode_error);
spastor 0:1c358ea10753 672 message_store_u8(error_packet, flags, flag);
spastor 0:1c358ea10753 673 message_store_be16(error_packet, transaction_id, session_id);
spastor 0:1c358ea10753 674 message_store_u8(error_packet, error_code, error_value);
spastor 0:1c358ea10753 675
spastor 0:1c358ea10753 676 status = tcp_initiate_send_facility_packet(connector_ptr, edp_header, record_end(error_packet), E_MSG_FAC_MSG_NUM, tcp_release_packet_buffer, NULL);
spastor 0:1c358ea10753 677
spastor 0:1c358ea10753 678
spastor 0:1c358ea10753 679 if ((status != connector_pending) && (session != NULL))
spastor 0:1c358ea10753 680 status = msg_delete_session(connector_ptr, msg_ptr, session);
spastor 0:1c358ea10753 681
spastor 0:1c358ea10753 682 done:
spastor 0:1c358ea10753 683 return status;
spastor 0:1c358ea10753 684 }
spastor 0:1c358ea10753 685
spastor 0:1c358ea10753 686 static connector_status_t msg_send_capabilities(connector_data_t * const connector_ptr, connector_msg_data_t const * const msg_ptr, uint8_t const flag)
spastor 0:1c358ea10753 687 {
spastor 0:1c358ea10753 688 connector_status_t status = connector_pending;
spastor 0:1c358ea10753 689 uint8_t * capability_packet = NULL;
spastor 0:1c358ea10753 690 uint8_t * const edp_header = tcp_get_packet_buffer(connector_ptr, E_MSG_FAC_MSG_NUM, &capability_packet, NULL);
spastor 0:1c358ea10753 691 uint8_t * variable_data_ptr = capability_packet + record_bytes(capability_packet);
spastor 0:1c358ea10753 692
spastor 0:1c358ea10753 693 if ((edp_header == NULL) || (capability_packet == NULL))
spastor 0:1c358ea10753 694 goto error;
spastor 0:1c358ea10753 695
spastor 0:1c358ea10753 696 /*
spastor 0:1c358ea10753 697 * ------------------------------------------------------------------------------------------
spastor 0:1c358ea10753 698 * | 0 | 1 | 2 | 3 | 4-7 | 8 | 9-(8+n) | 9+n | s bytes |
spastor 0:1c358ea10753 699 * -----------------------------------------------------------------------------------------
spastor 0:1c358ea10753 700 * | opcode | flags | version | Max Trx | Window | Count(n) | list | Count (s) | list |
spastor 0:1c358ea10753 701 * | | | | | size | compression algo | Service Info |
spastor 0:1c358ea10753 702 * -----------------------------------------------------------------------------------------
spastor 0:1c358ea10753 703 */
spastor 0:1c358ea10753 704 message_store_u8(capability_packet, opcode, msg_opcode_capability);
spastor 0:1c358ea10753 705 message_store_u8(capability_packet, flags, flag);
spastor 0:1c358ea10753 706 message_store_u8(capability_packet, version, MSG_FACILITY_VERSION);
spastor 0:1c358ea10753 707 message_store_u8(capability_packet, max_transactions, msg_ptr->capabilities[msg_capability_client].max_transactions);
spastor 0:1c358ea10753 708 message_store_be32(capability_packet, window_size, msg_ptr->capabilities[msg_capability_client].window_size);
spastor 0:1c358ea10753 709
spastor 0:1c358ea10753 710 /* append compression algorithms supported */
spastor 0:1c358ea10753 711 {
spastor 0:1c358ea10753 712 uint8_t const compression_length = (msg_ptr->capabilities[msg_capability_client].compression_supported) ? 1 : 0;
spastor 0:1c358ea10753 713
spastor 0:1c358ea10753 714 message_store_u8(capability_packet, compression_count, compression_length);
spastor 0:1c358ea10753 715 if (compression_length > 0)
spastor 0:1c358ea10753 716 *variable_data_ptr++ = MSG_COMPRESSION_LIBZ;
spastor 0:1c358ea10753 717 }
spastor 0:1c358ea10753 718
spastor 0:1c358ea10753 719 /* append service IDs of all listeners */
spastor 0:1c358ea10753 720 {
spastor 0:1c358ea10753 721 uint16_t services = 0;
spastor 0:1c358ea10753 722 uint16_t service_id;
spastor 0:1c358ea10753 723
spastor 0:1c358ea10753 724 for (service_id = 0; service_id < msg_service_id_count; service_id++)
spastor 0:1c358ea10753 725 if (msg_ptr->service_cb[service_id] != NULL) services++;
spastor 0:1c358ea10753 726
spastor 0:1c358ea10753 727 StoreBE16(variable_data_ptr, services);
spastor 0:1c358ea10753 728 variable_data_ptr += sizeof services;
spastor 0:1c358ea10753 729
spastor 0:1c358ea10753 730 for (service_id = 0; service_id < msg_service_id_count; service_id++)
spastor 0:1c358ea10753 731 {
spastor 0:1c358ea10753 732 if (msg_ptr->service_cb[service_id] != NULL)
spastor 0:1c358ea10753 733 {
spastor 0:1c358ea10753 734 StoreBE16(variable_data_ptr, service_id);
spastor 0:1c358ea10753 735 variable_data_ptr += sizeof service_id;
spastor 0:1c358ea10753 736 }
spastor 0:1c358ea10753 737 }
spastor 0:1c358ea10753 738 }
spastor 0:1c358ea10753 739
spastor 0:1c358ea10753 740 {
spastor 0:1c358ea10753 741 size_t const packet_len = (size_t)(variable_data_ptr - capability_packet);
spastor 0:1c358ea10753 742
spastor 0:1c358ea10753 743 status = tcp_initiate_send_facility_packet(connector_ptr, edp_header, packet_len, E_MSG_FAC_MSG_NUM, tcp_release_packet_buffer, NULL);
spastor 0:1c358ea10753 744 }
spastor 0:1c358ea10753 745
spastor 0:1c358ea10753 746 error:
spastor 0:1c358ea10753 747 return status;
spastor 0:1c358ea10753 748 }
spastor 0:1c358ea10753 749
spastor 0:1c358ea10753 750 static void msg_fill_msg_header(msg_session_t * const session, void * ptr)
spastor 0:1c358ea10753 751 {
spastor 0:1c358ea10753 752 uint8_t flag = 0;
spastor 0:1c358ea10753 753
spastor 0:1c358ea10753 754 if MsgIsRequest(session->out_dblock->status_flag)
spastor 0:1c358ea10753 755 MsgSetRequest(flag);
spastor 0:1c358ea10753 756
spastor 0:1c358ea10753 757 if (MsgIsLastData(session->out_dblock->status_flag))
spastor 0:1c358ea10753 758 MsgSetLastData(flag);
spastor 0:1c358ea10753 759
spastor 0:1c358ea10753 760 if (MsgIsStart(session->out_dblock->status_flag))
spastor 0:1c358ea10753 761 {
spastor 0:1c358ea10753 762 uint8_t * const start_packet = ptr;
spastor 0:1c358ea10753 763
spastor 0:1c358ea10753 764 MsgClearStart(session->out_dblock->status_flag);
spastor 0:1c358ea10753 765
spastor 0:1c358ea10753 766 /*
spastor 0:1c358ea10753 767 * -----------------------------------------------------------------
spastor 0:1c358ea10753 768 * | 0 | 1 | 2-3 | 4-5 | 6 | 7 ... n |
spastor 0:1c358ea10753 769 * ----------------------------------------------------------------
spastor 0:1c358ea10753 770 * | opcode | flags | Xid | Service ID | Comp ID | Data |
spastor 0:1c358ea10753 771 * ----------------------------------------------------------------
spastor 0:1c358ea10753 772 */
spastor 0:1c358ea10753 773 message_store_u8(start_packet, opcode, msg_opcode_start);
spastor 0:1c358ea10753 774 message_store_u8(start_packet, flags, flag);
spastor 0:1c358ea10753 775 {
spastor 0:1c358ea10753 776 uint16_t const session_id = (uint16_t)session->session_id;
spastor 0:1c358ea10753 777 uint16_t const service_id = (uint16_t)session->service_id;
spastor 0:1c358ea10753 778
spastor 0:1c358ea10753 779 message_store_be16(start_packet, transaction_id, session_id);
spastor 0:1c358ea10753 780 message_store_be16(start_packet, service_id, service_id);
spastor 0:1c358ea10753 781 }
spastor 0:1c358ea10753 782 message_store_u8(start_packet, compression_id, (MsgIsCompressed(session->out_dblock->status_flag) ? MSG_COMPRESSION_LIBZ : MSG_COMPRESSION_NONE));
spastor 0:1c358ea10753 783 }
spastor 0:1c358ea10753 784 else
spastor 0:1c358ea10753 785 {
spastor 0:1c358ea10753 786 uint8_t * const data_packet = ptr;
spastor 0:1c358ea10753 787
spastor 0:1c358ea10753 788 /*
spastor 0:1c358ea10753 789 * ---------------------------------------
spastor 0:1c358ea10753 790 * | 0 | 1 | 2-3 | 4 ... n |
spastor 0:1c358ea10753 791 * --------------------------------------
spastor 0:1c358ea10753 792 * | opcode | flags | Xid | Data |
spastor 0:1c358ea10753 793 * --------------------------------------
spastor 0:1c358ea10753 794 */
spastor 0:1c358ea10753 795 message_store_u8(data_packet, opcode, msg_opcode_data);
spastor 0:1c358ea10753 796 message_store_u8(data_packet, flags, flag);
spastor 0:1c358ea10753 797 {
spastor 0:1c358ea10753 798 uint16_t const session_id = (uint16_t)session->session_id;
spastor 0:1c358ea10753 799
spastor 0:1c358ea10753 800 message_store_be16(data_packet, transaction_id, session_id);
spastor 0:1c358ea10753 801 }
spastor 0:1c358ea10753 802 }
spastor 0:1c358ea10753 803 }
spastor 0:1c358ea10753 804
spastor 0:1c358ea10753 805 static connector_status_t msg_send_complete(connector_data_t * const connector_ptr, uint8_t const * const packet, connector_status_t const status, void * const user_data)
spastor 0:1c358ea10753 806 {
spastor 0:1c358ea10753 807 connector_status_t return_status = connector_working;
spastor 0:1c358ea10753 808
spastor 0:1c358ea10753 809 msg_session_t * const session = user_data;
spastor 0:1c358ea10753 810 msg_data_block_t * const dblock = session->out_dblock;
spastor 0:1c358ea10753 811
spastor 0:1c358ea10753 812 ASSERT_GOTO(session != NULL, error);
spastor 0:1c358ea10753 813 ASSERT_GOTO(dblock != NULL, error);
spastor 0:1c358ea10753 814
spastor 0:1c358ea10753 815 if ((MsgIsDoubleBuf(dblock->status_flag) == connector_false) && (MsgIsCompressed(dblock->status_flag) == connector_false))
spastor 0:1c358ea10753 816 {
spastor 0:1c358ea10753 817 return_status = tcp_release_packet_buffer(connector_ptr, packet, connector_success, NULL);
spastor 0:1c358ea10753 818 if (return_status != connector_working) goto error;
spastor 0:1c358ea10753 819 }
spastor 0:1c358ea10753 820
spastor 0:1c358ea10753 821 switch (status)
spastor 0:1c358ea10753 822 {
spastor 0:1c358ea10753 823 case connector_service_busy:
spastor 0:1c358ea10753 824 session->current_state = msg_state_send_data;
spastor 0:1c358ea10753 825 break;
spastor 0:1c358ea10753 826
spastor 0:1c358ea10753 827 case connector_success:
spastor 0:1c358ea10753 828 /* update session state */
spastor 0:1c358ea10753 829 if (MsgIsLastData(dblock->status_flag))
spastor 0:1c358ea10753 830 {
spastor 0:1c358ea10753 831 if (MsgIsRequest(dblock->status_flag))
spastor 0:1c358ea10753 832 {
spastor 0:1c358ea10753 833 session->current_state = msg_state_receive;
spastor 0:1c358ea10753 834 }
spastor 0:1c358ea10753 835 else
spastor 0:1c358ea10753 836 {
spastor 0:1c358ea10753 837 connector_msg_data_t * const msg_ptr = get_facility_data(connector_ptr, E_MSG_FAC_MSG_NUM);
spastor 0:1c358ea10753 838
spastor 0:1c358ea10753 839 return_status = msg_delete_session(connector_ptr, msg_ptr, session);
spastor 0:1c358ea10753 840 }
spastor 0:1c358ea10753 841
spastor 0:1c358ea10753 842 goto done;
spastor 0:1c358ea10753 843 }
spastor 0:1c358ea10753 844
spastor 0:1c358ea10753 845 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 846 dblock->bytes_out = 0;
spastor 0:1c358ea10753 847 if (dblock->zlib.avail_out == 0)
spastor 0:1c358ea10753 848 {
spastor 0:1c358ea10753 849 session->current_state = msg_state_compress;
spastor 0:1c358ea10753 850 goto done;
spastor 0:1c358ea10753 851 }
spastor 0:1c358ea10753 852
spastor 0:1c358ea10753 853 dblock->z_flag = Z_NO_FLUSH;
spastor 0:1c358ea10753 854 dblock->zlib.avail_out = 0;
spastor 0:1c358ea10753 855 #else
spastor 0:1c358ea10753 856 session->send_data_bytes = 0;
spastor 0:1c358ea10753 857 #endif
spastor 0:1c358ea10753 858
spastor 0:1c358ea10753 859 session->service_layer_data.need_data->data_ptr = NULL;
spastor 0:1c358ea10753 860 session->current_state = MsgIsAckPending(dblock->status_flag) == connector_true ? msg_state_wait_ack : session->saved_state;
spastor 0:1c358ea10753 861
spastor 0:1c358ea10753 862 break;
spastor 0:1c358ea10753 863
spastor 0:1c358ea10753 864 default:
spastor 0:1c358ea10753 865 msg_inform_error(connector_ptr, session, connector_session_error_send);
spastor 0:1c358ea10753 866 break;
spastor 0:1c358ea10753 867 }
spastor 0:1c358ea10753 868
spastor 0:1c358ea10753 869 error:
spastor 0:1c358ea10753 870 done:
spastor 0:1c358ea10753 871 return return_status;
spastor 0:1c358ea10753 872 }
spastor 0:1c358ea10753 873
spastor 0:1c358ea10753 874 static connector_status_t msg_send_data(connector_data_t * const connector_ptr, msg_session_t * const session)
spastor 0:1c358ea10753 875 {
spastor 0:1c358ea10753 876 connector_status_t status = connector_working;
spastor 0:1c358ea10753 877 uint8_t * buffer;
spastor 0:1c358ea10753 878 size_t bytes;
spastor 0:1c358ea10753 879
spastor 0:1c358ea10753 880 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 881 {
spastor 0:1c358ea10753 882 msg_data_block_t * const dblock = session->out_dblock;
spastor 0:1c358ea10753 883
spastor 0:1c358ea10753 884 bytes = dblock->bytes_out;
spastor 0:1c358ea10753 885 buffer = dblock->buffer_out;
spastor 0:1c358ea10753 886 }
spastor 0:1c358ea10753 887 #else
spastor 0:1c358ea10753 888 bytes = session->send_data_bytes;
spastor 0:1c358ea10753 889 buffer = session->send_data_ptr;
spastor 0:1c358ea10753 890 #endif
spastor 0:1c358ea10753 891
spastor 0:1c358ea10753 892 ASSERT_GOTO(bytes > 0, error);
spastor 0:1c358ea10753 893 status = tcp_initiate_send_facility_packet(connector_ptr, buffer, bytes, E_MSG_FAC_MSG_NUM, msg_send_complete, session);
spastor 0:1c358ea10753 894 if (status != connector_working)
spastor 0:1c358ea10753 895 {
spastor 0:1c358ea10753 896 connector_status_t result = status;
spastor 0:1c358ea10753 897
spastor 0:1c358ea10753 898 if (status == connector_pending) result = connector_service_busy;
spastor 0:1c358ea10753 899
spastor 0:1c358ea10753 900 msg_send_complete(connector_ptr, buffer, result, session);
spastor 0:1c358ea10753 901 }
spastor 0:1c358ea10753 902 else
spastor 0:1c358ea10753 903 session->current_state = msg_state_wait_send_complete;
spastor 0:1c358ea10753 904
spastor 0:1c358ea10753 905 error:
spastor 0:1c358ea10753 906 return status;
spastor 0:1c358ea10753 907 }
spastor 0:1c358ea10753 908
spastor 0:1c358ea10753 909 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 910 static connector_status_t msg_compress_data(connector_data_t * const connector_ptr, msg_session_t * const session)
spastor 0:1c358ea10753 911 {
spastor 0:1c358ea10753 912 connector_status_t status = connector_working;
spastor 0:1c358ea10753 913 msg_data_block_t * const dblock = session->out_dblock;
spastor 0:1c358ea10753 914 uint8_t * const msg_buffer = GET_PACKET_DATA_POINTER(dblock->buffer_out, PACKET_EDP_FACILITY_SIZE);
spastor 0:1c358ea10753 915 size_t const frame_bytes = sizeof dblock->buffer_out - PACKET_EDP_FACILITY_SIZE;
spastor 0:1c358ea10753 916 z_streamp zlib_ptr = &dblock->zlib;
spastor 0:1c358ea10753 917 int zret;
spastor 0:1c358ea10753 918
spastor 0:1c358ea10753 919 if (zlib_ptr->avail_out == 0)
spastor 0:1c358ea10753 920 {
spastor 0:1c358ea10753 921 size_t const header_length = MsgIsStart(dblock->status_flag) ? record_end(start_packet) : record_end(data_packet);
spastor 0:1c358ea10753 922
spastor 0:1c358ea10753 923 zlib_ptr->next_out = msg_buffer + header_length;
spastor 0:1c358ea10753 924 zlib_ptr->avail_out = frame_bytes - header_length;
spastor 0:1c358ea10753 925 }
spastor 0:1c358ea10753 926
spastor 0:1c358ea10753 927 zret = deflate(zlib_ptr, dblock->z_flag);
spastor 0:1c358ea10753 928 switch (zret)
spastor 0:1c358ea10753 929 {
spastor 0:1c358ea10753 930 case Z_OK:
spastor 0:1c358ea10753 931 if ((dblock->z_flag != Z_SYNC_FLUSH) && (zlib_ptr->avail_out > 0))
spastor 0:1c358ea10753 932 goto done;
spastor 0:1c358ea10753 933 break;
spastor 0:1c358ea10753 934
spastor 0:1c358ea10753 935 case Z_STREAM_END:
spastor 0:1c358ea10753 936 MsgSetLastData(dblock->status_flag);
spastor 0:1c358ea10753 937 break;
spastor 0:1c358ea10753 938
spastor 0:1c358ea10753 939 default:
spastor 0:1c358ea10753 940 status = msg_inform_error(connector_ptr, session, connector_session_error_compression_failure);
spastor 0:1c358ea10753 941 goto done;
spastor 0:1c358ea10753 942 }
spastor 0:1c358ea10753 943
spastor 0:1c358ea10753 944 msg_fill_msg_header(session, msg_buffer);
spastor 0:1c358ea10753 945 dblock->bytes_out = frame_bytes - zlib_ptr->avail_out;
spastor 0:1c358ea10753 946 status = msg_send_data(connector_ptr, session);
spastor 0:1c358ea10753 947
spastor 0:1c358ea10753 948 done:
spastor 0:1c358ea10753 949 return status;
spastor 0:1c358ea10753 950 }
spastor 0:1c358ea10753 951
spastor 0:1c358ea10753 952 static connector_status_t msg_prepare_send_data(connector_data_t * const connector_ptr, msg_session_t * const session)
spastor 0:1c358ea10753 953 {
spastor 0:1c358ea10753 954 connector_status_t status = connector_no_resource;
spastor 0:1c358ea10753 955 msg_data_block_t * const dblock = session->out_dblock;
spastor 0:1c358ea10753 956
spastor 0:1c358ea10753 957 UNUSED_PARAMETER(connector_ptr);
spastor 0:1c358ea10753 958 ASSERT_GOTO(dblock != NULL, error);
spastor 0:1c358ea10753 959 ASSERT_GOTO(dblock->zlib.avail_in == 0, error);
spastor 0:1c358ea10753 960
spastor 0:1c358ea10753 961 {
spastor 0:1c358ea10753 962 unsigned int const flag = (dblock->total_bytes == 0) ? MSG_FLAG_START : 0;
spastor 0:1c358ea10753 963 msg_service_data_t * const service_data = session->service_layer_data.need_data;
spastor 0:1c358ea10753 964
spastor 0:1c358ea10753 965 ASSERT_GOTO(service_data != NULL, error);
spastor 0:1c358ea10753 966 service_data->data_ptr = dblock->buffer_in;
spastor 0:1c358ea10753 967 service_data->length_in_bytes = sizeof dblock->buffer_in;
spastor 0:1c358ea10753 968 service_data->flags = flag;
spastor 0:1c358ea10753 969 status = connector_working;
spastor 0:1c358ea10753 970 }
spastor 0:1c358ea10753 971
spastor 0:1c358ea10753 972 error:
spastor 0:1c358ea10753 973 return status;
spastor 0:1c358ea10753 974 }
spastor 0:1c358ea10753 975
spastor 0:1c358ea10753 976 static connector_status_t msg_process_send_data(connector_data_t * const connector_ptr, msg_session_t * const session)
spastor 0:1c358ea10753 977 {
spastor 0:1c358ea10753 978 connector_status_t status = connector_no_resource;
spastor 0:1c358ea10753 979 msg_data_block_t * const dblock = session->out_dblock;
spastor 0:1c358ea10753 980
spastor 0:1c358ea10753 981 ASSERT_GOTO(dblock != NULL, error);
spastor 0:1c358ea10753 982 ASSERT_GOTO(dblock->zlib.avail_in == 0, error);
spastor 0:1c358ea10753 983
spastor 0:1c358ea10753 984 {
spastor 0:1c358ea10753 985 z_streamp const zlib_ptr = &dblock->zlib;
spastor 0:1c358ea10753 986 msg_service_data_t * const service_data = session->service_layer_data.need_data;
spastor 0:1c358ea10753 987
spastor 0:1c358ea10753 988 zlib_ptr->next_in = dblock->buffer_in;
spastor 0:1c358ea10753 989 zlib_ptr->avail_in = service_data->length_in_bytes;
spastor 0:1c358ea10753 990 dblock->total_bytes += service_data->length_in_bytes;
spastor 0:1c358ea10753 991 if (MsgIsLastData(service_data->flags))
spastor 0:1c358ea10753 992 dblock->z_flag = Z_FINISH;
spastor 0:1c358ea10753 993 }
spastor 0:1c358ea10753 994
spastor 0:1c358ea10753 995 if (dblock->z_flag == Z_NO_FLUSH)
spastor 0:1c358ea10753 996 {
spastor 0:1c358ea10753 997 size_t const unacked_bytes = dblock->total_bytes - dblock->ack_count;
spastor 0:1c358ea10753 998 size_t const safe_window_size = dblock->available_window - sizeof dblock->buffer_in;
spastor 0:1c358ea10753 999
spastor 0:1c358ea10753 1000 if (unacked_bytes > safe_window_size)
spastor 0:1c358ea10753 1001 {
spastor 0:1c358ea10753 1002 dblock->z_flag = Z_SYNC_FLUSH;
spastor 0:1c358ea10753 1003 MsgSetAckPending(dblock->status_flag);
spastor 0:1c358ea10753 1004 }
spastor 0:1c358ea10753 1005 }
spastor 0:1c358ea10753 1006
spastor 0:1c358ea10753 1007 status = msg_compress_data(connector_ptr, session);
spastor 0:1c358ea10753 1008
spastor 0:1c358ea10753 1009 error:
spastor 0:1c358ea10753 1010 return status;
spastor 0:1c358ea10753 1011 }
spastor 0:1c358ea10753 1012
spastor 0:1c358ea10753 1013 #else
spastor 0:1c358ea10753 1014
spastor 0:1c358ea10753 1015 static connector_status_t msg_prepare_send_data(connector_data_t * const connector_ptr, msg_session_t * const session)
spastor 0:1c358ea10753 1016 {
spastor 0:1c358ea10753 1017 uint8_t * msg_buffer;
spastor 0:1c358ea10753 1018 connector_status_t status = connector_no_resource;
spastor 0:1c358ea10753 1019 msg_data_block_t * const dblock = session->out_dblock;
spastor 0:1c358ea10753 1020
spastor 0:1c358ea10753 1021 ASSERT_GOTO(dblock != NULL, error);
spastor 0:1c358ea10753 1022 if (MsgIsDoubleBuf(dblock->status_flag))
spastor 0:1c358ea10753 1023 {
spastor 0:1c358ea10753 1024 msg_buffer = GET_PACKET_DATA_POINTER(session->send_data_ptr, PACKET_EDP_FACILITY_SIZE);
spastor 0:1c358ea10753 1025 session->send_data_bytes = MSG_MAX_SEND_PACKET_SIZE - PACKET_EDP_FACILITY_SIZE;
spastor 0:1c358ea10753 1026 }
spastor 0:1c358ea10753 1027 else
spastor 0:1c358ea10753 1028 {
spastor 0:1c358ea10753 1029 session->send_data_ptr = tcp_get_packet_buffer(connector_ptr, E_MSG_FAC_MSG_NUM, &msg_buffer, &session->send_data_bytes);
spastor 0:1c358ea10753 1030 if (session->send_data_ptr == NULL)
spastor 0:1c358ea10753 1031 {
spastor 0:1c358ea10753 1032 status = connector_pending;
spastor 0:1c358ea10753 1033 goto done;
spastor 0:1c358ea10753 1034 }
spastor 0:1c358ea10753 1035 }
spastor 0:1c358ea10753 1036
spastor 0:1c358ea10753 1037 {
spastor 0:1c358ea10753 1038 size_t const header_bytes = MsgIsStart(dblock->status_flag) == connector_true ? record_end(start_packet) : record_end(data_packet);
spastor 0:1c358ea10753 1039 msg_service_data_t * const service_data = session->service_layer_data.need_data;
spastor 0:1c358ea10753 1040 unsigned int const flag = MsgIsStart(dblock->status_flag) ? MSG_FLAG_START : 0;
spastor 0:1c358ea10753 1041
spastor 0:1c358ea10753 1042 ASSERT_GOTO(MsgIsNotLastData(dblock->status_flag), error);
spastor 0:1c358ea10753 1043 ASSERT_GOTO(session->send_data_bytes > header_bytes, error);
spastor 0:1c358ea10753 1044 ASSERT_GOTO(service_data != NULL, error);
spastor 0:1c358ea10753 1045
spastor 0:1c358ea10753 1046 service_data->data_ptr = msg_buffer + header_bytes;
spastor 0:1c358ea10753 1047 service_data->length_in_bytes = session->send_data_bytes - header_bytes;
spastor 0:1c358ea10753 1048 service_data->flags = flag;
spastor 0:1c358ea10753 1049 status = connector_working;
spastor 0:1c358ea10753 1050 }
spastor 0:1c358ea10753 1051
spastor 0:1c358ea10753 1052 error:
spastor 0:1c358ea10753 1053 done:
spastor 0:1c358ea10753 1054 return status;
spastor 0:1c358ea10753 1055 }
spastor 0:1c358ea10753 1056
spastor 0:1c358ea10753 1057 static connector_status_t msg_process_send_data(connector_data_t * const connector_ptr, msg_session_t * const session)
spastor 0:1c358ea10753 1058 {
spastor 0:1c358ea10753 1059 connector_status_t status = connector_no_resource;
spastor 0:1c358ea10753 1060 msg_data_block_t * const dblock = session->out_dblock;
spastor 0:1c358ea10753 1061 msg_service_data_t * const service_data = session->service_layer_data.need_data;
spastor 0:1c358ea10753 1062
spastor 0:1c358ea10753 1063 ASSERT_GOTO(dblock != NULL, error);
spastor 0:1c358ea10753 1064 if (MsgIsLastData(service_data->flags))
spastor 0:1c358ea10753 1065 MsgSetLastData(dblock->status_flag);
spastor 0:1c358ea10753 1066
spastor 0:1c358ea10753 1067 {
spastor 0:1c358ea10753 1068 size_t const header_bytes = MsgIsStart(dblock->status_flag) == connector_true ? record_end(start_packet) : record_end(data_packet);
spastor 0:1c358ea10753 1069 uint8_t * const msg_buffer = GET_PACKET_DATA_POINTER(session->send_data_ptr, PACKET_EDP_FACILITY_SIZE);
spastor 0:1c358ea10753 1070
spastor 0:1c358ea10753 1071 session->send_data_bytes = service_data->length_in_bytes + header_bytes;
spastor 0:1c358ea10753 1072 msg_fill_msg_header(session, msg_buffer);
spastor 0:1c358ea10753 1073 status = msg_send_data(connector_ptr, session);
spastor 0:1c358ea10753 1074 if (status != connector_working)
spastor 0:1c358ea10753 1075 goto error;
spastor 0:1c358ea10753 1076 }
spastor 0:1c358ea10753 1077
spastor 0:1c358ea10753 1078 dblock->total_bytes += service_data->length_in_bytes;
spastor 0:1c358ea10753 1079 if ((dblock->total_bytes - dblock->ack_count) > (dblock->available_window - MSG_MAX_SEND_PACKET_SIZE))
spastor 0:1c358ea10753 1080 MsgSetAckPending(dblock->status_flag);
spastor 0:1c358ea10753 1081
spastor 0:1c358ea10753 1082 error:
spastor 0:1c358ea10753 1083 return status;
spastor 0:1c358ea10753 1084 }
spastor 0:1c358ea10753 1085
spastor 0:1c358ea10753 1086 #endif
spastor 0:1c358ea10753 1087
spastor 0:1c358ea10753 1088 static connector_status_t msg_get_service_data(connector_data_t * const connector_ptr, msg_session_t * const session)
spastor 0:1c358ea10753 1089 {
spastor 0:1c358ea10753 1090 connector_status_t status = connector_no_resource;
spastor 0:1c358ea10753 1091 msg_data_block_t * const dblock = session->out_dblock;
spastor 0:1c358ea10753 1092
spastor 0:1c358ea10753 1093 ASSERT_GOTO(dblock != NULL, error);
spastor 0:1c358ea10753 1094 ASSERT_GOTO(MsgIsNotLastData(dblock->status_flag), done);
spastor 0:1c358ea10753 1095
spastor 0:1c358ea10753 1096 status = msg_prepare_send_data(connector_ptr, session);
spastor 0:1c358ea10753 1097 if (status != connector_working)
spastor 0:1c358ea10753 1098 goto error;
spastor 0:1c358ea10753 1099
spastor 0:1c358ea10753 1100 status = msg_call_service_layer(connector_ptr, session, msg_service_type_need_data);
spastor 0:1c358ea10753 1101 if (status != connector_working)
spastor 0:1c358ea10753 1102 {
spastor 0:1c358ea10753 1103 /* release the buffer */
spastor 0:1c358ea10753 1104 if ((MsgIsDoubleBuf(dblock->status_flag) == connector_false) && (MsgIsCompressed(dblock->status_flag) == connector_false))
spastor 0:1c358ea10753 1105 tcp_release_packet_buffer(connector_ptr, session->send_data_ptr, connector_success, NULL);
spastor 0:1c358ea10753 1106
spastor 0:1c358ea10753 1107 goto done;
spastor 0:1c358ea10753 1108 }
spastor 0:1c358ea10753 1109
spastor 0:1c358ea10753 1110 session->saved_state = session->current_state;
spastor 0:1c358ea10753 1111 status = msg_process_send_data(connector_ptr, session);
spastor 0:1c358ea10753 1112
spastor 0:1c358ea10753 1113 error:
spastor 0:1c358ea10753 1114 done:
spastor 0:1c358ea10753 1115 return status;
spastor 0:1c358ea10753 1116 }
spastor 0:1c358ea10753 1117
spastor 0:1c358ea10753 1118 #if (defined CONNECTOR_DATA_SERVICE)
spastor 0:1c358ea10753 1119 static connector_bool_t msg_initiate_request(connector_data_t * const connector_ptr, void const * const service_context)
spastor 0:1c358ea10753 1120 {
spastor 0:1c358ea10753 1121 connector_bool_t success = connector_false;
spastor 0:1c358ea10753 1122 connector_msg_data_t * const msg_ptr = get_facility_data(connector_ptr, E_MSG_FAC_MSG_NUM);
spastor 0:1c358ea10753 1123
spastor 0:1c358ea10753 1124 ASSERT_GOTO(msg_ptr != NULL, error);
spastor 0:1c358ea10753 1125 if (msg_ptr->pending_service_request == NULL)
spastor 0:1c358ea10753 1126 {
spastor 0:1c358ea10753 1127 msg_ptr->pending_service_request = service_context;
spastor 0:1c358ea10753 1128 success = connector_true;
spastor 0:1c358ea10753 1129 }
spastor 0:1c358ea10753 1130
spastor 0:1c358ea10753 1131 error:
spastor 0:1c358ea10753 1132 return success;
spastor 0:1c358ea10753 1133 }
spastor 0:1c358ea10753 1134
spastor 0:1c358ea10753 1135 static connector_status_t msg_handle_pending_request(connector_data_t * const connector_ptr, connector_msg_data_t * const msg_ptr, msg_session_t * const session, connector_session_error_t const result)
spastor 0:1c358ea10753 1136 {
spastor 0:1c358ea10753 1137 connector_status_t status = connector_working;
spastor 0:1c358ea10753 1138 connector_msg_callback_t * const cb_fn = msg_ptr->service_cb[msg_service_id_data];
spastor 0:1c358ea10753 1139
spastor 0:1c358ea10753 1140 if (cb_fn != NULL)
spastor 0:1c358ea10753 1141 {
spastor 0:1c358ea10753 1142 msg_service_request_t service_data;
spastor 0:1c358ea10753 1143
spastor 0:1c358ea10753 1144 service_data.session = session;
spastor 0:1c358ea10753 1145 service_data.service_type = msg_service_type_pending_request;
spastor 0:1c358ea10753 1146 service_data.have_data = (void *)msg_ptr->pending_service_request;
spastor 0:1c358ea10753 1147 service_data.error_value = result;
spastor 0:1c358ea10753 1148
spastor 0:1c358ea10753 1149 cb_fn(connector_ptr, &service_data);
spastor 0:1c358ea10753 1150 if ((service_data.error_value != connector_session_error_none) && (session != NULL))
spastor 0:1c358ea10753 1151 status = msg_delete_session(connector_ptr, msg_ptr, session);
spastor 0:1c358ea10753 1152 }
spastor 0:1c358ea10753 1153
spastor 0:1c358ea10753 1154 msg_ptr->pending_service_request = NULL;
spastor 0:1c358ea10753 1155 return status;
spastor 0:1c358ea10753 1156 }
spastor 0:1c358ea10753 1157
spastor 0:1c358ea10753 1158 static connector_status_t msg_start_session(connector_data_t * const connector_ptr, connector_msg_data_t * const msg_ptr)
spastor 0:1c358ea10753 1159 {
spastor 0:1c358ea10753 1160 connector_status_t status = connector_working;
spastor 0:1c358ea10753 1161 static connector_bool_t const client_owned = connector_true;
spastor 0:1c358ea10753 1162 msg_session_t * const session = msg_create_session(connector_ptr, msg_ptr, msg_service_id_data, client_owned, &status);
spastor 0:1c358ea10753 1163
spastor 0:1c358ea10753 1164 if (session == NULL) goto error;
spastor 0:1c358ea10753 1165
spastor 0:1c358ea10753 1166 {
spastor 0:1c358ea10753 1167 connector_session_error_t const result = msg_initialize_data_block(session, msg_ptr->capabilities[msg_capability_cloud].window_size, msg_block_state_send_request);
spastor 0:1c358ea10753 1168
spastor 0:1c358ea10753 1169 status = msg_handle_pending_request(connector_ptr, msg_ptr, session, result);
spastor 0:1c358ea10753 1170 }
spastor 0:1c358ea10753 1171
spastor 0:1c358ea10753 1172 error:
spastor 0:1c358ea10753 1173 return status;
spastor 0:1c358ea10753 1174 }
spastor 0:1c358ea10753 1175 #endif
spastor 0:1c358ea10753 1176
spastor 0:1c358ea10753 1177 static connector_status_t msg_send_ack(connector_data_t * const connector_ptr, connector_msg_data_t * const msg_ptr, msg_session_t * const session)
spastor 0:1c358ea10753 1178 {
spastor 0:1c358ea10753 1179 connector_status_t status = connector_pending;
spastor 0:1c358ea10753 1180 uint8_t * ack_packet;
spastor 0:1c358ea10753 1181 uint8_t * const edp_packet = tcp_get_packet_buffer(connector_ptr, E_MSG_FAC_MSG_NUM, &ack_packet, NULL);
spastor 0:1c358ea10753 1182 msg_data_block_t * const dblock = session->in_dblock;
spastor 0:1c358ea10753 1183
spastor 0:1c358ea10753 1184 if (edp_packet == NULL)
spastor 0:1c358ea10753 1185 goto done;
spastor 0:1c358ea10753 1186
spastor 0:1c358ea10753 1187 ASSERT_GOTO(dblock != NULL, error);
spastor 0:1c358ea10753 1188 message_store_u8(ack_packet, opcode, msg_opcode_ack);
spastor 0:1c358ea10753 1189 {
spastor 0:1c358ea10753 1190 uint8_t const flag = MsgIsClientOwned(dblock->status_flag) ? 0 : MSG_FLAG_REQUEST;
spastor 0:1c358ea10753 1191
spastor 0:1c358ea10753 1192 message_store_u8(ack_packet, flags, flag);
spastor 0:1c358ea10753 1193 }
spastor 0:1c358ea10753 1194 {
spastor 0:1c358ea10753 1195 uint16_t const session_id = (uint16_t)session->session_id;
spastor 0:1c358ea10753 1196
spastor 0:1c358ea10753 1197 message_store_be16(ack_packet, transaction_id, session_id);
spastor 0:1c358ea10753 1198 }
spastor 0:1c358ea10753 1199 {
spastor 0:1c358ea10753 1200 uint32_t const val32 = (uint32_t) dblock->total_bytes;
spastor 0:1c358ea10753 1201
spastor 0:1c358ea10753 1202 ASSERT(dblock->total_bytes <= UINT32_MAX);
spastor 0:1c358ea10753 1203 message_store_be32(ack_packet, ack_count, val32);
spastor 0:1c358ea10753 1204 }
spastor 0:1c358ea10753 1205
spastor 0:1c358ea10753 1206 message_store_be32(ack_packet, window_size, msg_ptr->capabilities[msg_capability_client].window_size);
spastor 0:1c358ea10753 1207
spastor 0:1c358ea10753 1208 status = tcp_initiate_send_facility_packet(connector_ptr, edp_packet, record_end(ack_packet),
spastor 0:1c358ea10753 1209 E_MSG_FAC_MSG_NUM, tcp_release_packet_buffer, NULL);
spastor 0:1c358ea10753 1210 if (status != connector_pending)
spastor 0:1c358ea10753 1211 {
spastor 0:1c358ea10753 1212 dblock->ack_count = dblock->total_bytes;
spastor 0:1c358ea10753 1213 MsgClearAckPending(dblock->status_flag);
spastor 0:1c358ea10753 1214 session->current_state = msg_state_receive;
spastor 0:1c358ea10753 1215 }
spastor 0:1c358ea10753 1216
spastor 0:1c358ea10753 1217 error:
spastor 0:1c358ea10753 1218 done:
spastor 0:1c358ea10753 1219 return status;
spastor 0:1c358ea10753 1220 }
spastor 0:1c358ea10753 1221
spastor 0:1c358ea10753 1222 static connector_status_t msg_process_capabilities(connector_data_t * const connector_ptr, connector_msg_data_t * const msg_fac, uint8_t * const ptr)
spastor 0:1c358ea10753 1223 {
spastor 0:1c358ea10753 1224 connector_status_t status = connector_working;
spastor 0:1c358ea10753 1225 uint8_t * capability_packet = ptr;
spastor 0:1c358ea10753 1226 connector_bool_t const request_capabilities = connector_bool((message_load_u8(capability_packet, flags) & MSG_FLAG_REQUEST) == MSG_FLAG_REQUEST);
spastor 0:1c358ea10753 1227 uint8_t const version = message_load_u8(capability_packet, version);
spastor 0:1c358ea10753 1228
spastor 0:1c358ea10753 1229 ASSERT_GOTO(version == MSG_FACILITY_VERSION, error);
spastor 0:1c358ea10753 1230 msg_fac->capabilities[msg_capability_cloud].max_transactions = message_load_u8(capability_packet, max_transactions);
spastor 0:1c358ea10753 1231 msg_fac->capabilities[msg_capability_cloud].window_size = message_load_be32(capability_packet, window_size);
spastor 0:1c358ea10753 1232
spastor 0:1c358ea10753 1233 {
spastor 0:1c358ea10753 1234 uint8_t const comp_count = message_load_u8(capability_packet, compression_count);
spastor 0:1c358ea10753 1235 uint8_t const * compression_list = capability_packet + record_bytes(capability_packet);
spastor 0:1c358ea10753 1236 int i;
spastor 0:1c358ea10753 1237
spastor 0:1c358ea10753 1238 msg_fac->capabilities[msg_capability_cloud].compression_supported = connector_false;
spastor 0:1c358ea10753 1239 for (i = 0; i < comp_count; i++)
spastor 0:1c358ea10753 1240 {
spastor 0:1c358ea10753 1241 uint8_t const compression_id = *compression_list++;
spastor 0:1c358ea10753 1242
spastor 0:1c358ea10753 1243 if (compression_id == MSG_COMPRESSION_LIBZ)
spastor 0:1c358ea10753 1244 {
spastor 0:1c358ea10753 1245 msg_fac->capabilities[msg_capability_cloud].compression_supported = connector_true;
spastor 0:1c358ea10753 1246 break;
spastor 0:1c358ea10753 1247 }
spastor 0:1c358ea10753 1248 }
spastor 0:1c358ea10753 1249 }
spastor 0:1c358ea10753 1250
spastor 0:1c358ea10753 1251 if (request_capabilities)
spastor 0:1c358ea10753 1252 {
spastor 0:1c358ea10753 1253 uint8_t const capability_flag = 0;
spastor 0:1c358ea10753 1254
spastor 0:1c358ea10753 1255 status = msg_send_capabilities(connector_ptr, msg_fac, capability_flag);
spastor 0:1c358ea10753 1256 }
spastor 0:1c358ea10753 1257
spastor 0:1c358ea10753 1258 error:
spastor 0:1c358ea10753 1259 return status;
spastor 0:1c358ea10753 1260 }
spastor 0:1c358ea10753 1261
spastor 0:1c358ea10753 1262 static connector_status_t msg_pass_service_data(connector_data_t * const connector_ptr, msg_session_t * const session, void * data, size_t const bytes)
spastor 0:1c358ea10753 1263 {
spastor 0:1c358ea10753 1264 connector_status_t status = connector_working;
spastor 0:1c358ea10753 1265 msg_data_block_t * const dblock = session->in_dblock;
spastor 0:1c358ea10753 1266
spastor 0:1c358ea10753 1267 ASSERT_GOTO(session != NULL, error);
spastor 0:1c358ea10753 1268 ASSERT_GOTO(dblock != NULL, error);
spastor 0:1c358ea10753 1269
spastor 0:1c358ea10753 1270 {
spastor 0:1c358ea10753 1271 unsigned int service_flag = 0;
spastor 0:1c358ea10753 1272 msg_service_data_t * const service_data = session->service_layer_data.have_data;
spastor 0:1c358ea10753 1273
spastor 0:1c358ea10753 1274 ASSERT_GOTO(service_data != NULL, error);
spastor 0:1c358ea10753 1275 if (MsgIsStart(dblock->status_flag))
spastor 0:1c358ea10753 1276 MsgSetStart(service_flag);
spastor 0:1c358ea10753 1277
spastor 0:1c358ea10753 1278 if (MsgIsLastData(dblock->status_flag))
spastor 0:1c358ea10753 1279 MsgSetLastData(service_flag);
spastor 0:1c358ea10753 1280
spastor 0:1c358ea10753 1281 service_data->data_ptr = data;
spastor 0:1c358ea10753 1282 service_data->length_in_bytes = bytes;
spastor 0:1c358ea10753 1283 service_data->flags = service_flag;
spastor 0:1c358ea10753 1284 if ((MsgIsDoubleBuf(dblock->status_flag)) && (session->service_layer_data.need_data->data_ptr == NULL))
spastor 0:1c358ea10753 1285 {
spastor 0:1c358ea10753 1286 status = msg_prepare_send_data(connector_ptr, session);
spastor 0:1c358ea10753 1287 ASSERT_GOTO(status == connector_working, error);
spastor 0:1c358ea10753 1288 }
spastor 0:1c358ea10753 1289 status = msg_call_service_layer(connector_ptr, session, msg_service_type_have_data);
spastor 0:1c358ea10753 1290 }
spastor 0:1c358ea10753 1291
spastor 0:1c358ea10753 1292 if (status != connector_working && status != connector_idle && status != connector_pending && status != connector_active)
spastor 0:1c358ea10753 1293 goto error;
spastor 0:1c358ea10753 1294
spastor 0:1c358ea10753 1295 if (status == connector_working)
spastor 0:1c358ea10753 1296 {
spastor 0:1c358ea10753 1297 MsgClearStart(dblock->status_flag);
spastor 0:1c358ea10753 1298
spastor 0:1c358ea10753 1299 if (MsgIsLastData(dblock->status_flag))
spastor 0:1c358ea10753 1300 {
spastor 0:1c358ea10753 1301 if (MsgIsRequest(dblock->status_flag))
spastor 0:1c358ea10753 1302 {
spastor 0:1c358ea10753 1303 connector_msg_data_t * const msg_ptr = get_facility_data(connector_ptr, E_MSG_FAC_MSG_NUM);
spastor 0:1c358ea10753 1304 connector_session_error_t result;
spastor 0:1c358ea10753 1305
spastor 0:1c358ea10753 1306 ASSERT_GOTO(msg_ptr != NULL, error);
spastor 0:1c358ea10753 1307 if (MsgIsDoubleBuf(dblock->status_flag) == connector_false)
spastor 0:1c358ea10753 1308 {
spastor 0:1c358ea10753 1309 result = msg_initialize_data_block(session, msg_ptr->capabilities[msg_capability_cloud].window_size, msg_block_state_send_response);
spastor 0:1c358ea10753 1310 if (result != connector_session_error_none)
spastor 0:1c358ea10753 1311 status = msg_inform_error(connector_ptr, session, result);
spastor 0:1c358ea10753 1312 }
spastor 0:1c358ea10753 1313 else
spastor 0:1c358ea10753 1314 {
spastor 0:1c358ea10753 1315 MsgClearRequest(dblock->status_flag);
spastor 0:1c358ea10753 1316 MsgClearRequest(session->out_dblock->status_flag);
spastor 0:1c358ea10753 1317 }
spastor 0:1c358ea10753 1318 }
spastor 0:1c358ea10753 1319 else
spastor 0:1c358ea10753 1320 session->current_state = msg_state_delete;
spastor 0:1c358ea10753 1321 }
spastor 0:1c358ea10753 1322 else
spastor 0:1c358ea10753 1323 {
spastor 0:1c358ea10753 1324 dblock->total_bytes += bytes;
spastor 0:1c358ea10753 1325
spastor 0:1c358ea10753 1326 if ((dblock->total_bytes - dblock->ack_count) > (dblock->available_window/2))
spastor 0:1c358ea10753 1327 {
spastor 0:1c358ea10753 1328 MsgSetAckPending(dblock->status_flag);
spastor 0:1c358ea10753 1329 session->current_state = msg_state_send_ack;
spastor 0:1c358ea10753 1330 }
spastor 0:1c358ea10753 1331 else
spastor 0:1c358ea10753 1332 session->current_state = msg_state_receive;
spastor 0:1c358ea10753 1333 }
spastor 0:1c358ea10753 1334 }
spastor 0:1c358ea10753 1335
spastor 0:1c358ea10753 1336 if (MsgIsDoubleBuf(dblock->status_flag))
spastor 0:1c358ea10753 1337 {
spastor 0:1c358ea10753 1338 ASSERT_GOTO(session->service_layer_data.need_data != NULL, error);
spastor 0:1c358ea10753 1339 session->saved_state = session->current_state;
spastor 0:1c358ea10753 1340
spastor 0:1c358ea10753 1341 if (MsgIsSendNow(session->service_layer_data.need_data->flags))
spastor 0:1c358ea10753 1342 {
spastor 0:1c358ea10753 1343 connector_status_t const send_status = msg_process_send_data(connector_ptr, session);
spastor 0:1c358ea10753 1344
spastor 0:1c358ea10753 1345 ASSERT_GOTO(((send_status == connector_working) || (send_status == connector_pending) || (send_status == connector_active)), error);
spastor 0:1c358ea10753 1346 session->service_layer_data.need_data->data_ptr = NULL;
spastor 0:1c358ea10753 1347 }
spastor 0:1c358ea10753 1348 }
spastor 0:1c358ea10753 1349
spastor 0:1c358ea10753 1350 error:
spastor 0:1c358ea10753 1351 return status;
spastor 0:1c358ea10753 1352 }
spastor 0:1c358ea10753 1353
spastor 0:1c358ea10753 1354 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 1355 static connector_status_t msg_process_decompressed_data(connector_data_t * const connector_ptr, msg_session_t * const session)
spastor 0:1c358ea10753 1356 {
spastor 0:1c358ea10753 1357 connector_status_t status = connector_working;
spastor 0:1c358ea10753 1358 msg_data_block_t * const dblock = session->in_dblock;
spastor 0:1c358ea10753 1359
spastor 0:1c358ea10753 1360 ASSERT_GOTO(dblock != NULL, error);
spastor 0:1c358ea10753 1361 ASSERT_GOTO(dblock->bytes_out > 0, error);
spastor 0:1c358ea10753 1362
spastor 0:1c358ea10753 1363 status = msg_pass_service_data(connector_ptr, session, dblock->buffer_out, dblock->bytes_out);
spastor 0:1c358ea10753 1364 if (status == connector_working)
spastor 0:1c358ea10753 1365 {
spastor 0:1c358ea10753 1366 dblock->bytes_out = 0;
spastor 0:1c358ea10753 1367 if (session->current_state != msg_state_get_data)
spastor 0:1c358ea10753 1368 {
spastor 0:1c358ea10753 1369 if (dblock->zlib.avail_out == 0)
spastor 0:1c358ea10753 1370 session->current_state = msg_state_decompress;
spastor 0:1c358ea10753 1371 else
spastor 0:1c358ea10753 1372 {
spastor 0:1c358ea10753 1373 if (MsgIsAckPending(dblock->status_flag))
spastor 0:1c358ea10753 1374 session->current_state = msg_state_send_ack;
spastor 0:1c358ea10753 1375 }
spastor 0:1c358ea10753 1376 }
spastor 0:1c358ea10753 1377 }
spastor 0:1c358ea10753 1378 else if ((status == connector_active) || (status == connector_pending))
spastor 0:1c358ea10753 1379 {
spastor 0:1c358ea10753 1380 session->current_state = msg_state_process_decompressed;
spastor 0:1c358ea10753 1381 status = connector_working;
spastor 0:1c358ea10753 1382 }
spastor 0:1c358ea10753 1383
spastor 0:1c358ea10753 1384 error:
spastor 0:1c358ea10753 1385 return status;
spastor 0:1c358ea10753 1386 }
spastor 0:1c358ea10753 1387
spastor 0:1c358ea10753 1388 static connector_status_t msg_decompress_data(connector_data_t * const connector_ptr, msg_session_t * const session)
spastor 0:1c358ea10753 1389 {
spastor 0:1c358ea10753 1390 connector_status_t status = connector_working;
spastor 0:1c358ea10753 1391 msg_data_block_t * const dblock = session->in_dblock;
spastor 0:1c358ea10753 1392 z_streamp zlib_ptr;
spastor 0:1c358ea10753 1393
spastor 0:1c358ea10753 1394 ASSERT_GOTO(dblock != NULL, error);
spastor 0:1c358ea10753 1395 zlib_ptr = &dblock->zlib;
spastor 0:1c358ea10753 1396
spastor 0:1c358ea10753 1397 if (zlib_ptr->avail_out == 0)
spastor 0:1c358ea10753 1398 {
spastor 0:1c358ea10753 1399 zlib_ptr->next_out = dblock->buffer_out;
spastor 0:1c358ea10753 1400 zlib_ptr->avail_out = sizeof dblock->buffer_out;
spastor 0:1c358ea10753 1401 }
spastor 0:1c358ea10753 1402
spastor 0:1c358ea10753 1403 {
spastor 0:1c358ea10753 1404 int const zret = inflate(zlib_ptr, Z_NO_FLUSH);
spastor 0:1c358ea10753 1405
spastor 0:1c358ea10753 1406 session->current_state = MsgIsAckPending(dblock->status_flag) ? msg_state_send_ack : msg_state_receive;
spastor 0:1c358ea10753 1407 switch(zret)
spastor 0:1c358ea10753 1408 {
spastor 0:1c358ea10753 1409 case Z_BUF_ERROR:
spastor 0:1c358ea10753 1410 if (zlib_ptr->avail_in > 0)
spastor 0:1c358ea10753 1411 goto error;
spastor 0:1c358ea10753 1412 goto done;
spastor 0:1c358ea10753 1413
spastor 0:1c358ea10753 1414 case Z_OK:
spastor 0:1c358ea10753 1415 if (zlib_ptr->avail_out > 0)
spastor 0:1c358ea10753 1416 goto done;
spastor 0:1c358ea10753 1417 break;
spastor 0:1c358ea10753 1418
spastor 0:1c358ea10753 1419 case Z_STREAM_END:
spastor 0:1c358ea10753 1420 MsgSetLastData(dblock->status_flag);
spastor 0:1c358ea10753 1421 break;
spastor 0:1c358ea10753 1422
spastor 0:1c358ea10753 1423 default:
spastor 0:1c358ea10753 1424 goto error;
spastor 0:1c358ea10753 1425 }
spastor 0:1c358ea10753 1426
spastor 0:1c358ea10753 1427 dblock->bytes_out = sizeof dblock->buffer_out - zlib_ptr->avail_out;
spastor 0:1c358ea10753 1428 status = msg_process_decompressed_data(connector_ptr, session);
spastor 0:1c358ea10753 1429 }
spastor 0:1c358ea10753 1430
spastor 0:1c358ea10753 1431 goto done;
spastor 0:1c358ea10753 1432
spastor 0:1c358ea10753 1433 error:
spastor 0:1c358ea10753 1434 status = msg_inform_error(connector_ptr, session, connector_session_error_decompression_failure);
spastor 0:1c358ea10753 1435
spastor 0:1c358ea10753 1436 done:
spastor 0:1c358ea10753 1437 return status;
spastor 0:1c358ea10753 1438 }
spastor 0:1c358ea10753 1439
spastor 0:1c358ea10753 1440 static connector_status_t msg_process_compressed_data(connector_data_t * const connector_ptr, msg_session_t * const session, uint8_t * data, size_t const bytes)
spastor 0:1c358ea10753 1441 {
spastor 0:1c358ea10753 1442 connector_status_t status = connector_working;
spastor 0:1c358ea10753 1443 msg_data_block_t * const dblock = session->in_dblock;
spastor 0:1c358ea10753 1444 z_streamp zlib_ptr;
spastor 0:1c358ea10753 1445
spastor 0:1c358ea10753 1446 ASSERT_GOTO(dblock != NULL, error);
spastor 0:1c358ea10753 1447 zlib_ptr = &dblock->zlib;
spastor 0:1c358ea10753 1448
spastor 0:1c358ea10753 1449 if (zlib_ptr->avail_in > 0)
spastor 0:1c358ea10753 1450 {
spastor 0:1c358ea10753 1451 status = connector_pending;
spastor 0:1c358ea10753 1452 goto done;
spastor 0:1c358ea10753 1453 }
spastor 0:1c358ea10753 1454
spastor 0:1c358ea10753 1455 ASSERT_GOTO(bytes < sizeof dblock->buffer_in, error);
spastor 0:1c358ea10753 1456 memcpy(dblock->buffer_in, data, bytes);
spastor 0:1c358ea10753 1457
spastor 0:1c358ea10753 1458 zlib_ptr->next_in = dblock->buffer_in;
spastor 0:1c358ea10753 1459 zlib_ptr->avail_in = bytes;
spastor 0:1c358ea10753 1460
spastor 0:1c358ea10753 1461 status = msg_decompress_data(connector_ptr, session);
spastor 0:1c358ea10753 1462
spastor 0:1c358ea10753 1463 error:
spastor 0:1c358ea10753 1464 done:
spastor 0:1c358ea10753 1465 return status;
spastor 0:1c358ea10753 1466 }
spastor 0:1c358ea10753 1467 #endif
spastor 0:1c358ea10753 1468
spastor 0:1c358ea10753 1469 static connector_status_t msg_process_service_data(connector_data_t * const connector_ptr, msg_session_t * const session, uint8_t * msg_data, size_t const frame_bytes, size_t const header_bytes, unsigned const flag)
spastor 0:1c358ea10753 1470 {
spastor 0:1c358ea10753 1471 connector_status_t status = connector_working;
spastor 0:1c358ea10753 1472 uint8_t * buffer = msg_data + header_bytes;
spastor 0:1c358ea10753 1473 size_t const bytes = frame_bytes - header_bytes;
spastor 0:1c358ea10753 1474 msg_data_block_t * const dblock = session->in_dblock;
spastor 0:1c358ea10753 1475
spastor 0:1c358ea10753 1476 ASSERT_GOTO(dblock != NULL, error);
spastor 0:1c358ea10753 1477 if (session->current_state != msg_state_receive)
spastor 0:1c358ea10753 1478 {
spastor 0:1c358ea10753 1479 status = ((session->current_state == msg_state_send_error) || (session->current_state == msg_state_delete)) ? connector_working : connector_active;
spastor 0:1c358ea10753 1480 goto done;
spastor 0:1c358ea10753 1481 }
spastor 0:1c358ea10753 1482
spastor 0:1c358ea10753 1483 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 1484 if (MsgIsCompressed(dblock->status_flag))
spastor 0:1c358ea10753 1485 {
spastor 0:1c358ea10753 1486 status = msg_process_compressed_data(connector_ptr, session, buffer, bytes);
spastor 0:1c358ea10753 1487 goto done;
spastor 0:1c358ea10753 1488 }
spastor 0:1c358ea10753 1489 #endif
spastor 0:1c358ea10753 1490
spastor 0:1c358ea10753 1491 if (MsgIsLastData(flag))
spastor 0:1c358ea10753 1492 MsgSetLastData(dblock->status_flag);
spastor 0:1c358ea10753 1493
spastor 0:1c358ea10753 1494 status = msg_pass_service_data(connector_ptr, session, buffer, bytes);
spastor 0:1c358ea10753 1495
spastor 0:1c358ea10753 1496 error:
spastor 0:1c358ea10753 1497 done:
spastor 0:1c358ea10753 1498 return status;
spastor 0:1c358ea10753 1499 }
spastor 0:1c358ea10753 1500
spastor 0:1c358ea10753 1501 static connector_status_t msg_process_start(connector_data_t * const connector_ptr, connector_msg_data_t * const msg_ptr, uint8_t * ptr, uint16_t const length)
spastor 0:1c358ea10753 1502 {
spastor 0:1c358ea10753 1503 connector_status_t status = connector_working;
spastor 0:1c358ea10753 1504 connector_session_error_t result = connector_session_error_none;
spastor 0:1c358ea10753 1505 msg_session_t * session;
spastor 0:1c358ea10753 1506 uint8_t * start_packet = ptr;
spastor 0:1c358ea10753 1507 uint8_t flag = message_load_u8(start_packet, flags);
spastor 0:1c358ea10753 1508 uint16_t const session_id = message_load_be16(start_packet, transaction_id);
spastor 0:1c358ea10753 1509 connector_bool_t const client_owned = MsgIsNotRequest(flag);
spastor 0:1c358ea10753 1510
spastor 0:1c358ea10753 1511 session = msg_find_session(msg_ptr, session_id, client_owned);
spastor 0:1c358ea10753 1512 if (session == NULL)
spastor 0:1c358ea10753 1513 {
spastor 0:1c358ea10753 1514 uint16_t const service_id = message_load_be16(start_packet, service_id);
spastor 0:1c358ea10753 1515
spastor 0:1c358ea10753 1516 if (client_owned)
spastor 0:1c358ea10753 1517 {
spastor 0:1c358ea10753 1518 result = connector_session_error_unknown_session;
spastor 0:1c358ea10753 1519 goto error;
spastor 0:1c358ea10753 1520 }
spastor 0:1c358ea10753 1521
spastor 0:1c358ea10753 1522 session = msg_create_session(connector_ptr, msg_ptr, service_id, client_owned, &status);
spastor 0:1c358ea10753 1523 if (session == NULL)
spastor 0:1c358ea10753 1524 {
spastor 0:1c358ea10753 1525 switch (status)
spastor 0:1c358ea10753 1526 {
spastor 0:1c358ea10753 1527 case connector_pending:
spastor 0:1c358ea10753 1528 result = connector_session_error_busy;
spastor 0:1c358ea10753 1529 status = connector_working;
spastor 0:1c358ea10753 1530 break;
spastor 0:1c358ea10753 1531
spastor 0:1c358ea10753 1532 default:
spastor 0:1c358ea10753 1533 result = connector_session_error_fatal;
spastor 0:1c358ea10753 1534 break;
spastor 0:1c358ea10753 1535 }
spastor 0:1c358ea10753 1536
spastor 0:1c358ea10753 1537 goto error;
spastor 0:1c358ea10753 1538 }
spastor 0:1c358ea10753 1539
spastor 0:1c358ea10753 1540 session->session_id = session_id;
spastor 0:1c358ea10753 1541 if (session->out_dblock != NULL)
spastor 0:1c358ea10753 1542 {
spastor 0:1c358ea10753 1543 result = msg_initialize_data_block(session, msg_ptr->capabilities[msg_capability_client].window_size, msg_block_state_send_response);
spastor 0:1c358ea10753 1544 if (result != connector_session_error_none)
spastor 0:1c358ea10753 1545 goto error;
spastor 0:1c358ea10753 1546 }
spastor 0:1c358ea10753 1547
spastor 0:1c358ea10753 1548 result = msg_initialize_data_block(session, msg_ptr->capabilities[msg_capability_client].window_size, msg_block_state_recv_request);
spastor 0:1c358ea10753 1549 if (result != connector_session_error_none)
spastor 0:1c358ea10753 1550 goto error;
spastor 0:1c358ea10753 1551 }
spastor 0:1c358ea10753 1552 else
spastor 0:1c358ea10753 1553 {
spastor 0:1c358ea10753 1554 if (session->current_state == msg_state_send_error)
spastor 0:1c358ea10753 1555 goto done;
spastor 0:1c358ea10753 1556
spastor 0:1c358ea10753 1557 if (client_owned)
spastor 0:1c358ea10753 1558 {
spastor 0:1c358ea10753 1559 result = msg_initialize_data_block(session, msg_ptr->capabilities[msg_capability_client].window_size, msg_block_state_recv_response);
spastor 0:1c358ea10753 1560 if (result != connector_session_error_none)
spastor 0:1c358ea10753 1561 goto error;
spastor 0:1c358ea10753 1562 }
spastor 0:1c358ea10753 1563 }
spastor 0:1c358ea10753 1564
spastor 0:1c358ea10753 1565 {
spastor 0:1c358ea10753 1566 uint8_t const compression = message_load_u8(start_packet, compression_id);
spastor 0:1c358ea10753 1567
spastor 0:1c358ea10753 1568 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 1569 if (compression == MSG_COMPRESSION_NONE)
spastor 0:1c358ea10753 1570 MsgClearCompression(session->in_dblock->status_flag);
spastor 0:1c358ea10753 1571 #else
spastor 0:1c358ea10753 1572 if (compression != MSG_COMPRESSION_NONE)
spastor 0:1c358ea10753 1573 {
spastor 0:1c358ea10753 1574 result = connector_session_error_decompression_failure;
spastor 0:1c358ea10753 1575 goto error;
spastor 0:1c358ea10753 1576 }
spastor 0:1c358ea10753 1577 #endif
spastor 0:1c358ea10753 1578 }
spastor 0:1c358ea10753 1579
spastor 0:1c358ea10753 1580 MsgSetStart(flag);
spastor 0:1c358ea10753 1581 status = msg_process_service_data(connector_ptr, session, ptr, length, record_end(start_packet), flag);
spastor 0:1c358ea10753 1582 goto done;
spastor 0:1c358ea10753 1583
spastor 0:1c358ea10753 1584 error:
spastor 0:1c358ea10753 1585 {
spastor 0:1c358ea10753 1586 connector_status_t error_status = (session != NULL) ? msg_inform_error(connector_ptr, session, result) : msg_send_error(connector_ptr, msg_ptr, session, session_id, result, flag);
spastor 0:1c358ea10753 1587
spastor 0:1c358ea10753 1588 if (error_status == connector_abort)
spastor 0:1c358ea10753 1589 status = connector_abort;
spastor 0:1c358ea10753 1590 }
spastor 0:1c358ea10753 1591
spastor 0:1c358ea10753 1592 done:
spastor 0:1c358ea10753 1593 return status;
spastor 0:1c358ea10753 1594 }
spastor 0:1c358ea10753 1595
spastor 0:1c358ea10753 1596 static connector_status_t msg_process_data(connector_data_t * const connector_ptr, connector_msg_data_t * const msg_ptr, uint8_t * ptr, uint16_t const length)
spastor 0:1c358ea10753 1597 {
spastor 0:1c358ea10753 1598 connector_status_t status = connector_working;
spastor 0:1c358ea10753 1599 msg_session_t * session;
spastor 0:1c358ea10753 1600 uint8_t * const data_packet = ptr;
spastor 0:1c358ea10753 1601 uint8_t const flag = message_load_u8(data_packet, flags);
spastor 0:1c358ea10753 1602 uint16_t const session_id = message_load_be16(data_packet, transaction_id);
spastor 0:1c358ea10753 1603 connector_bool_t const client_owned = MsgIsNotRequest(flag);
spastor 0:1c358ea10753 1604
spastor 0:1c358ea10753 1605 session = msg_find_session(msg_ptr, session_id, client_owned);
spastor 0:1c358ea10753 1606 if (session == NULL)
spastor 0:1c358ea10753 1607 {
spastor 0:1c358ea10753 1608 status = msg_send_error(connector_ptr, msg_ptr, session, session_id, connector_session_error_unknown_session, flag);
spastor 0:1c358ea10753 1609 goto done;
spastor 0:1c358ea10753 1610 }
spastor 0:1c358ea10753 1611
spastor 0:1c358ea10753 1612 status = msg_process_service_data(connector_ptr, session, ptr, length, record_end(data_packet), flag);
spastor 0:1c358ea10753 1613
spastor 0:1c358ea10753 1614 done:
spastor 0:1c358ea10753 1615 return status;
spastor 0:1c358ea10753 1616 }
spastor 0:1c358ea10753 1617
spastor 0:1c358ea10753 1618 static connector_status_t msg_process_ack(connector_msg_data_t * const msg_fac, uint8_t const * ptr)
spastor 0:1c358ea10753 1619 {
spastor 0:1c358ea10753 1620 msg_session_t * session;
spastor 0:1c358ea10753 1621 uint8_t const * const ack_packet = ptr;
spastor 0:1c358ea10753 1622
spastor 0:1c358ea10753 1623 {
spastor 0:1c358ea10753 1624 uint16_t const session_id = message_load_be16(ack_packet, transaction_id);
spastor 0:1c358ea10753 1625 uint8_t const flag = message_load_u8(ack_packet, flags);
spastor 0:1c358ea10753 1626 connector_bool_t const client_owned = MsgIsRequest(flag);
spastor 0:1c358ea10753 1627
spastor 0:1c358ea10753 1628 session = msg_find_session(msg_fac, session_id, client_owned);
spastor 0:1c358ea10753 1629 /* already closed? done sending all data */
spastor 0:1c358ea10753 1630 if (session == NULL)
spastor 0:1c358ea10753 1631 goto done;
spastor 0:1c358ea10753 1632 }
spastor 0:1c358ea10753 1633
spastor 0:1c358ea10753 1634 {
spastor 0:1c358ea10753 1635 msg_data_block_t * const dblock = session->out_dblock;
spastor 0:1c358ea10753 1636
spastor 0:1c358ea10753 1637 ASSERT_GOTO(dblock != NULL, error);
spastor 0:1c358ea10753 1638 dblock->available_window = message_load_be32(ack_packet, window_size);
spastor 0:1c358ea10753 1639 dblock->ack_count = message_load_be32(ack_packet, ack_count);
spastor 0:1c358ea10753 1640
spastor 0:1c358ea10753 1641 if (dblock->available_window > 0)
spastor 0:1c358ea10753 1642 {
spastor 0:1c358ea10753 1643 MsgClearAckPending(dblock->status_flag);
spastor 0:1c358ea10753 1644 if (session->current_state == msg_state_wait_ack)
spastor 0:1c358ea10753 1645 session->current_state = session->saved_state;
spastor 0:1c358ea10753 1646 }
spastor 0:1c358ea10753 1647 }
spastor 0:1c358ea10753 1648
spastor 0:1c358ea10753 1649 error:
spastor 0:1c358ea10753 1650 done:
spastor 0:1c358ea10753 1651 return connector_working;
spastor 0:1c358ea10753 1652 }
spastor 0:1c358ea10753 1653
spastor 0:1c358ea10753 1654 static connector_status_t msg_process_error(connector_data_t * const connector_ptr, connector_msg_data_t * const msg_fac, uint8_t * const ptr)
spastor 0:1c358ea10753 1655 {
spastor 0:1c358ea10753 1656 connector_status_t status = connector_working;
spastor 0:1c358ea10753 1657 uint8_t * const error_packet = ptr;
spastor 0:1c358ea10753 1658 uint8_t const flag = message_load_u8(error_packet, flags);
spastor 0:1c358ea10753 1659 connector_bool_t const client_request_error = connector_bool(MsgIsRequest(flag) && MsgIsNotSender(flag));
spastor 0:1c358ea10753 1660 connector_bool_t const cloud_response_error = connector_bool(MsgIsNotRequest(flag) && MsgIsSender(flag));
spastor 0:1c358ea10753 1661 connector_bool_t const client_owned = connector_bool(client_request_error || cloud_response_error);
spastor 0:1c358ea10753 1662 uint16_t const session_id = message_load_be16(error_packet, transaction_id);
spastor 0:1c358ea10753 1663 msg_session_t * const session = msg_find_session(msg_fac, session_id, client_owned);
spastor 0:1c358ea10753 1664
spastor 0:1c358ea10753 1665 if (session != NULL)
spastor 0:1c358ea10753 1666 {
spastor 0:1c358ea10753 1667 if ((session->current_state != msg_state_delete) && (session->current_state != msg_state_send_error))
spastor 0:1c358ea10753 1668 {
spastor 0:1c358ea10753 1669 uint8_t const error_val = message_load_u8(error_packet, error_code);
spastor 0:1c358ea10753 1670
spastor 0:1c358ea10753 1671 ASSERT_GOTO(error_val < connector_session_error_count, error);
spastor 0:1c358ea10753 1672 {
spastor 0:1c358ea10753 1673 connector_session_error_t const msg_error = (connector_session_error_t)error_val;
spastor 0:1c358ea10753 1674
spastor 0:1c358ea10753 1675 status = msg_inform_error(connector_ptr, session, msg_error);
spastor 0:1c358ea10753 1676 if ((status != connector_pending) && (status != connector_abort))
spastor 0:1c358ea10753 1677 status = msg_delete_session(connector_ptr, msg_fac, session);
spastor 0:1c358ea10753 1678 }
spastor 0:1c358ea10753 1679 }
spastor 0:1c358ea10753 1680 }
spastor 0:1c358ea10753 1681 else
spastor 0:1c358ea10753 1682 {
spastor 0:1c358ea10753 1683 connector_debug_printf("msg_process_error: unable to find session id = %d\n", session_id);
spastor 0:1c358ea10753 1684 }
spastor 0:1c358ea10753 1685
spastor 0:1c358ea10753 1686 error:
spastor 0:1c358ea10753 1687 return status;
spastor 0:1c358ea10753 1688 }
spastor 0:1c358ea10753 1689
spastor 0:1c358ea10753 1690 static connector_status_t msg_discovery(connector_data_t * const connector_ptr, void * const facility_data, uint8_t * const packet, unsigned int * const receive_timeout)
spastor 0:1c358ea10753 1691 {
spastor 0:1c358ea10753 1692 uint8_t const capability_flag = MSG_FLAG_REQUEST;
spastor 0:1c358ea10753 1693
spastor 0:1c358ea10753 1694 UNUSED_PARAMETER(packet);
spastor 0:1c358ea10753 1695 UNUSED_PARAMETER(receive_timeout);
spastor 0:1c358ea10753 1696
spastor 0:1c358ea10753 1697 return msg_send_capabilities(connector_ptr, facility_data, capability_flag);
spastor 0:1c358ea10753 1698 }
spastor 0:1c358ea10753 1699
spastor 0:1c358ea10753 1700 static void msg_switch_session(connector_msg_data_t * const msg_ptr, msg_session_t * const session)
spastor 0:1c358ea10753 1701 {
spastor 0:1c358ea10753 1702 if (!msg_ptr->session_locked)
spastor 0:1c358ea10753 1703 {
spastor 0:1c358ea10753 1704 msg_ptr->session_locked = connector_true;
spastor 0:1c358ea10753 1705 msg_ptr->session.current = (session->prev != NULL) ? session->prev : msg_ptr->session.tail;
spastor 0:1c358ea10753 1706 msg_ptr->session_locked = connector_false;
spastor 0:1c358ea10753 1707 }
spastor 0:1c358ea10753 1708 }
spastor 0:1c358ea10753 1709
spastor 0:1c358ea10753 1710 static connector_status_t msg_process_pending(connector_data_t * const connector_ptr, connector_msg_data_t * const msg_ptr, unsigned int * const receive_timeout)
spastor 0:1c358ea10753 1711 {
spastor 0:1c358ea10753 1712 connector_status_t status = connector_idle;
spastor 0:1c358ea10753 1713
spastor 0:1c358ea10753 1714 if (msg_ptr->session_locked) goto done;
spastor 0:1c358ea10753 1715
spastor 0:1c358ea10753 1716 #if (defined CONNECTOR_DATA_SERVICE)
spastor 0:1c358ea10753 1717 if (msg_ptr->pending_service_request != NULL)
spastor 0:1c358ea10753 1718 {
spastor 0:1c358ea10753 1719 status = msg_start_session(connector_ptr, msg_ptr);
spastor 0:1c358ea10753 1720 if (status != connector_working) goto done;
spastor 0:1c358ea10753 1721 }
spastor 0:1c358ea10753 1722 #endif
spastor 0:1c358ea10753 1723
spastor 0:1c358ea10753 1724 #if (defined CONNECTOR_DATA_POINTS)
spastor 0:1c358ea10753 1725 status = dp_process_request(connector_ptr, connector_transport_tcp);
spastor 0:1c358ea10753 1726 if ((status != connector_idle) && (status != connector_working))
spastor 0:1c358ea10753 1727 goto done;
spastor 0:1c358ea10753 1728 #endif
spastor 0:1c358ea10753 1729
spastor 0:1c358ea10753 1730 msg_ptr->session_locked = connector_true;
spastor 0:1c358ea10753 1731 if (msg_ptr->session.current == NULL)
spastor 0:1c358ea10753 1732 msg_ptr->session.current = msg_ptr->session.tail;
spastor 0:1c358ea10753 1733 msg_ptr->session_locked = connector_false;
spastor 0:1c358ea10753 1734
spastor 0:1c358ea10753 1735 *receive_timeout = MAX_RECEIVE_TIMEOUT_IN_SECONDS;
spastor 0:1c358ea10753 1736 if (msg_ptr->session.current != NULL)
spastor 0:1c358ea10753 1737 {
spastor 0:1c358ea10753 1738 msg_session_t * const session = msg_ptr->session.current;
spastor 0:1c358ea10753 1739
spastor 0:1c358ea10753 1740 status = connector_working;
spastor 0:1c358ea10753 1741
spastor 0:1c358ea10753 1742 *receive_timeout = MIN_RECEIVE_TIMEOUT_IN_SECONDS;
spastor 0:1c358ea10753 1743 switch (session->current_state)
spastor 0:1c358ea10753 1744 {
spastor 0:1c358ea10753 1745 case msg_state_init:
spastor 0:1c358ea10753 1746 case msg_state_wait_ack:
spastor 0:1c358ea10753 1747 case msg_state_receive:
spastor 0:1c358ea10753 1748 case msg_state_wait_send_complete:
spastor 0:1c358ea10753 1749 msg_switch_session(msg_ptr, session);
spastor 0:1c358ea10753 1750 break;
spastor 0:1c358ea10753 1751
spastor 0:1c358ea10753 1752 case msg_state_get_data:
spastor 0:1c358ea10753 1753 session->saved_state = msg_state_get_data;
spastor 0:1c358ea10753 1754 status = msg_get_service_data(connector_ptr, session);
spastor 0:1c358ea10753 1755 if (status == connector_pending)
spastor 0:1c358ea10753 1756 msg_switch_session(msg_ptr, session);
spastor 0:1c358ea10753 1757 break;
spastor 0:1c358ea10753 1758
spastor 0:1c358ea10753 1759 case msg_state_send_data:
spastor 0:1c358ea10753 1760 status = msg_send_data(connector_ptr, session);
spastor 0:1c358ea10753 1761 break;
spastor 0:1c358ea10753 1762
spastor 0:1c358ea10753 1763 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 1764 case msg_state_compress:
spastor 0:1c358ea10753 1765 status = msg_compress_data(connector_ptr, session);
spastor 0:1c358ea10753 1766 break;
spastor 0:1c358ea10753 1767
spastor 0:1c358ea10753 1768 case msg_state_decompress:
spastor 0:1c358ea10753 1769 status = msg_decompress_data(connector_ptr, session);
spastor 0:1c358ea10753 1770 break;
spastor 0:1c358ea10753 1771
spastor 0:1c358ea10753 1772 case msg_state_process_decompressed:
spastor 0:1c358ea10753 1773 status = msg_process_decompressed_data(connector_ptr, session);
spastor 0:1c358ea10753 1774 break;
spastor 0:1c358ea10753 1775 #endif
spastor 0:1c358ea10753 1776
spastor 0:1c358ea10753 1777 case msg_state_send_ack:
spastor 0:1c358ea10753 1778 status = msg_send_ack(connector_ptr, msg_ptr, session);
spastor 0:1c358ea10753 1779 break;
spastor 0:1c358ea10753 1780
spastor 0:1c358ea10753 1781 case msg_state_send_error:
spastor 0:1c358ea10753 1782 {
spastor 0:1c358ea10753 1783 uint8_t const flag = (uint8_t)session->error_flag;
spastor 0:1c358ea10753 1784 uint16_t const session_id = (uint16_t)session->session_id;
spastor 0:1c358ea10753 1785
spastor 0:1c358ea10753 1786 status = msg_send_error(connector_ptr, msg_ptr, session, session_id, session->error, flag);
spastor 0:1c358ea10753 1787 break;
spastor 0:1c358ea10753 1788 }
spastor 0:1c358ea10753 1789
spastor 0:1c358ea10753 1790 case msg_state_delete:
spastor 0:1c358ea10753 1791 status = msg_delete_session(connector_ptr, msg_ptr, session);
spastor 0:1c358ea10753 1792 break;
spastor 0:1c358ea10753 1793
spastor 0:1c358ea10753 1794 default:
spastor 0:1c358ea10753 1795 status = connector_init_error;
spastor 0:1c358ea10753 1796 connector_debug_printf("Failed %X, state%d\n", session, session->current_state);
spastor 0:1c358ea10753 1797 ASSERT_GOTO(connector_false, done);
spastor 0:1c358ea10753 1798 break;
spastor 0:1c358ea10753 1799 }
spastor 0:1c358ea10753 1800 }
spastor 0:1c358ea10753 1801
spastor 0:1c358ea10753 1802 done:
spastor 0:1c358ea10753 1803 return status;
spastor 0:1c358ea10753 1804 }
spastor 0:1c358ea10753 1805
spastor 0:1c358ea10753 1806 static connector_status_t msg_process(connector_data_t * const connector_ptr, void * const facility_data, uint8_t * const edp_header, unsigned int * const receive_timeout)
spastor 0:1c358ea10753 1807 {
spastor 0:1c358ea10753 1808 connector_status_t status = connector_idle;
spastor 0:1c358ea10753 1809 connector_msg_data_t * const msg_ptr = facility_data;
spastor 0:1c358ea10753 1810
spastor 0:1c358ea10753 1811 ASSERT_GOTO(connector_ptr != NULL, error);
spastor 0:1c358ea10753 1812 ASSERT_GOTO(msg_ptr != NULL, error);
spastor 0:1c358ea10753 1813
spastor 0:1c358ea10753 1814 if (edp_header != NULL)
spastor 0:1c358ea10753 1815 {
spastor 0:1c358ea10753 1816 uint8_t * const data_ptr = GET_PACKET_DATA_POINTER(edp_header, PACKET_EDP_FACILITY_SIZE);
spastor 0:1c358ea10753 1817 uint16_t const length = message_load_be16(edp_header, length);
spastor 0:1c358ea10753 1818 uint8_t const opcode = *data_ptr;
spastor 0:1c358ea10753 1819
spastor 0:1c358ea10753 1820 switch (opcode)
spastor 0:1c358ea10753 1821 {
spastor 0:1c358ea10753 1822 case msg_opcode_capability:
spastor 0:1c358ea10753 1823 status = msg_process_capabilities(connector_ptr, msg_ptr, data_ptr);
spastor 0:1c358ea10753 1824 break;
spastor 0:1c358ea10753 1825
spastor 0:1c358ea10753 1826 case msg_opcode_start:
spastor 0:1c358ea10753 1827 status = msg_process_start(connector_ptr, msg_ptr, data_ptr, length);
spastor 0:1c358ea10753 1828 break;
spastor 0:1c358ea10753 1829
spastor 0:1c358ea10753 1830 case msg_opcode_data:
spastor 0:1c358ea10753 1831 status = msg_process_data(connector_ptr, msg_ptr, data_ptr, length);
spastor 0:1c358ea10753 1832 break;
spastor 0:1c358ea10753 1833
spastor 0:1c358ea10753 1834 case msg_opcode_ack:
spastor 0:1c358ea10753 1835 status = msg_process_ack(msg_ptr, data_ptr);
spastor 0:1c358ea10753 1836 break;
spastor 0:1c358ea10753 1837
spastor 0:1c358ea10753 1838 case msg_opcode_error:
spastor 0:1c358ea10753 1839 status = msg_process_error(connector_ptr, msg_ptr, data_ptr);
spastor 0:1c358ea10753 1840 break;
spastor 0:1c358ea10753 1841
spastor 0:1c358ea10753 1842 default:
spastor 0:1c358ea10753 1843 connector_debug_printf("msg_process: Invalid opcode\n");
spastor 0:1c358ea10753 1844 break;
spastor 0:1c358ea10753 1845 }
spastor 0:1c358ea10753 1846 }
spastor 0:1c358ea10753 1847
spastor 0:1c358ea10753 1848 {
spastor 0:1c358ea10753 1849 connector_status_t const pending_state = msg_process_pending(connector_ptr, msg_ptr, receive_timeout);
spastor 0:1c358ea10753 1850
spastor 0:1c358ea10753 1851 if ((pending_state == connector_pending) || (pending_state == connector_working) || (pending_state == connector_active))
spastor 0:1c358ea10753 1852 {
spastor 0:1c358ea10753 1853 if (status == connector_idle)
spastor 0:1c358ea10753 1854 status = pending_state;
spastor 0:1c358ea10753 1855 }
spastor 0:1c358ea10753 1856 else
spastor 0:1c358ea10753 1857 {
spastor 0:1c358ea10753 1858 if (pending_state != connector_idle)
spastor 0:1c358ea10753 1859 status = pending_state;
spastor 0:1c358ea10753 1860 }
spastor 0:1c358ea10753 1861 }
spastor 0:1c358ea10753 1862
spastor 0:1c358ea10753 1863 if (status == connector_unavailable) status = connector_working;
spastor 0:1c358ea10753 1864
spastor 0:1c358ea10753 1865 error:
spastor 0:1c358ea10753 1866 return status;
spastor 0:1c358ea10753 1867 }
spastor 0:1c358ea10753 1868
spastor 0:1c358ea10753 1869 static connector_status_t msg_cleanup_all_sessions(connector_data_t * const connector_ptr, uint16_t const service_id)
spastor 0:1c358ea10753 1870 {
spastor 0:1c358ea10753 1871 connector_status_t status = connector_working;
spastor 0:1c358ea10753 1872 connector_msg_data_t * const msg_ptr = get_facility_data(connector_ptr, E_MSG_FAC_MSG_NUM);
spastor 0:1c358ea10753 1873 msg_session_t * session;
spastor 0:1c358ea10753 1874
spastor 0:1c358ea10753 1875 ASSERT_GOTO(msg_ptr != NULL, error);
spastor 0:1c358ea10753 1876 session= msg_ptr->session.head;
spastor 0:1c358ea10753 1877
spastor 0:1c358ea10753 1878 while(session != NULL)
spastor 0:1c358ea10753 1879 {
spastor 0:1c358ea10753 1880 msg_session_t * next_session = session->next;
spastor 0:1c358ea10753 1881
spastor 0:1c358ea10753 1882 if (session->service_id == service_id)
spastor 0:1c358ea10753 1883 {
spastor 0:1c358ea10753 1884 if (session->current_state != msg_state_delete && session->current_state != msg_state_send_error)
spastor 0:1c358ea10753 1885 msg_inform_error(connector_ptr, session, connector_session_error_cancel);
spastor 0:1c358ea10753 1886
spastor 0:1c358ea10753 1887 status = msg_delete_session(connector_ptr, msg_ptr, session);
spastor 0:1c358ea10753 1888 if (status != connector_working) goto error;
spastor 0:1c358ea10753 1889 }
spastor 0:1c358ea10753 1890
spastor 0:1c358ea10753 1891 session = next_session;
spastor 0:1c358ea10753 1892 }
spastor 0:1c358ea10753 1893
spastor 0:1c358ea10753 1894 #if (defined CONNECTOR_DATA_SERVICE)
spastor 0:1c358ea10753 1895 if (msg_ptr->pending_service_request != NULL)
spastor 0:1c358ea10753 1896 status = msg_handle_pending_request(connector_ptr, msg_ptr, NULL, connector_session_error_cancel);
spastor 0:1c358ea10753 1897 #endif
spastor 0:1c358ea10753 1898
spastor 0:1c358ea10753 1899 error:
spastor 0:1c358ea10753 1900 return status;
spastor 0:1c358ea10753 1901 }
spastor 0:1c358ea10753 1902
spastor 0:1c358ea10753 1903 static connector_status_t msg_delete_facility(connector_data_t * const connector_ptr, uint16_t const service_id)
spastor 0:1c358ea10753 1904 {
spastor 0:1c358ea10753 1905 connector_status_t status = connector_no_resource;
spastor 0:1c358ea10753 1906 connector_msg_data_t * const msg_ptr = get_facility_data(connector_ptr, E_MSG_FAC_MSG_NUM);
spastor 0:1c358ea10753 1907
spastor 0:1c358ea10753 1908 if (msg_ptr == NULL)
spastor 0:1c358ea10753 1909 {
spastor 0:1c358ea10753 1910 status = connector_idle;
spastor 0:1c358ea10753 1911 goto error;
spastor 0:1c358ea10753 1912 }
spastor 0:1c358ea10753 1913
spastor 0:1c358ea10753 1914 ASSERT_GOTO(service_id < msg_service_id_count, error);
spastor 0:1c358ea10753 1915 ASSERT_GOTO(msg_ptr->service_cb[service_id] != NULL, error);
spastor 0:1c358ea10753 1916
spastor 0:1c358ea10753 1917 msg_ptr->service_cb[service_id] = NULL;
spastor 0:1c358ea10753 1918
spastor 0:1c358ea10753 1919 {
spastor 0:1c358ea10753 1920 connector_bool_t is_empty = connector_true;
spastor 0:1c358ea10753 1921 int i;
spastor 0:1c358ea10753 1922
spastor 0:1c358ea10753 1923 for(i = 0; i < msg_service_id_count; i++)
spastor 0:1c358ea10753 1924 {
spastor 0:1c358ea10753 1925 if (msg_ptr->service_cb[i] != NULL)
spastor 0:1c358ea10753 1926 {
spastor 0:1c358ea10753 1927 is_empty = connector_false;
spastor 0:1c358ea10753 1928 break;
spastor 0:1c358ea10753 1929 }
spastor 0:1c358ea10753 1930 }
spastor 0:1c358ea10753 1931
spastor 0:1c358ea10753 1932 status = is_empty == connector_true ? del_facility_data(connector_ptr, E_MSG_FAC_MSG_NUM) : connector_working;
spastor 0:1c358ea10753 1933 }
spastor 0:1c358ea10753 1934
spastor 0:1c358ea10753 1935 error:
spastor 0:1c358ea10753 1936 return status;
spastor 0:1c358ea10753 1937 }
spastor 0:1c358ea10753 1938
spastor 0:1c358ea10753 1939
spastor 0:1c358ea10753 1940 static connector_status_t msg_init_facility(connector_data_t * const connector_ptr, unsigned int const facility_index, uint16_t service_id, connector_msg_callback_t callback)
spastor 0:1c358ea10753 1941 {
spastor 0:1c358ea10753 1942 connector_status_t status = connector_no_resource;
spastor 0:1c358ea10753 1943 connector_msg_data_t * msg_ptr = get_facility_data(connector_ptr, E_MSG_FAC_MSG_NUM);
spastor 0:1c358ea10753 1944
spastor 0:1c358ea10753 1945 if (msg_ptr == NULL)
spastor 0:1c358ea10753 1946 {
spastor 0:1c358ea10753 1947 void * fac_ptr = NULL;
spastor 0:1c358ea10753 1948 connector_config_max_transaction_t config_max_transaction;
spastor 0:1c358ea10753 1949
spastor 0:1c358ea10753 1950 status = add_facility_data(connector_ptr, facility_index, E_MSG_FAC_MSG_NUM, &fac_ptr, sizeof *msg_ptr);
spastor 0:1c358ea10753 1951 ASSERT_GOTO(status == connector_working, done);
spastor 0:1c358ea10753 1952 ASSERT_GOTO(fac_ptr != NULL, done);
spastor 0:1c358ea10753 1953
spastor 0:1c358ea10753 1954 msg_ptr = fac_ptr;
spastor 0:1c358ea10753 1955 memset(msg_ptr, 0, sizeof *msg_ptr);
spastor 0:1c358ea10753 1956
spastor 0:1c358ea10753 1957 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 1958 msg_ptr->capabilities[msg_capability_client].compression_supported = connector_true;
spastor 0:1c358ea10753 1959 #endif
spastor 0:1c358ea10753 1960
spastor 0:1c358ea10753 1961 #if (defined CONNECTOR_MSG_MAX_TRANSACTION)
spastor 0:1c358ea10753 1962 config_max_transaction.count = CONNECTOR_MSG_MAX_TRANSACTION;
spastor 0:1c358ea10753 1963 #else
spastor 0:1c358ea10753 1964 {
spastor 0:1c358ea10753 1965 connector_request_id_t request_id;
spastor 0:1c358ea10753 1966 connector_callback_status_t callback_status;
spastor 0:1c358ea10753 1967
spastor 0:1c358ea10753 1968 request_id.config_request = connector_request_id_config_max_transaction;
spastor 0:1c358ea10753 1969 callback_status = connector_callback(connector_ptr->callback, connector_class_id_config, request_id, &config_max_transaction);
spastor 0:1c358ea10753 1970 if (callback_status != connector_callback_continue && callback_status != connector_callback_unrecognized)
spastor 0:1c358ea10753 1971 {
spastor 0:1c358ea10753 1972 status = connector_abort;
spastor 0:1c358ea10753 1973 goto done;
spastor 0:1c358ea10753 1974 }
spastor 0:1c358ea10753 1975 }
spastor 0:1c358ea10753 1976 #endif
spastor 0:1c358ea10753 1977
spastor 0:1c358ea10753 1978 msg_ptr->capabilities[msg_capability_client].max_transactions = config_max_transaction.count;
spastor 0:1c358ea10753 1979
spastor 0:1c358ea10753 1980 {
spastor 0:1c358ea10753 1981 uint32_t const recv_window = 16384;
spastor 0:1c358ea10753 1982
spastor 0:1c358ea10753 1983 ASSERT(recv_window > MSG_MAX_RECV_PACKET_SIZE);
spastor 0:1c358ea10753 1984 msg_ptr->capabilities[msg_capability_client].window_size = recv_window;
spastor 0:1c358ea10753 1985 }
spastor 0:1c358ea10753 1986 }
spastor 0:1c358ea10753 1987
spastor 0:1c358ea10753 1988 msg_ptr->service_cb[service_id] = callback;
spastor 0:1c358ea10753 1989 status = connector_working;
spastor 0:1c358ea10753 1990
spastor 0:1c358ea10753 1991 done:
spastor 0:1c358ea10753 1992 return status;
spastor 0:1c358ea10753 1993 }
spastor 0:1c358ea10753 1994
spastor 0:1c358ea10753 1995 #if (defined CONNECTOR_RCI_SERVICE)
spastor 0:1c358ea10753 1996
spastor 0:1c358ea10753 1997 #include "rci_service.h"
spastor 0:1c358ea10753 1998
spastor 0:1c358ea10753 1999 #if (!defined CONNECTOR_FIRMWARE_SERVICE)
spastor 0:1c358ea10753 2000 #include "rci_fwstub.h"
spastor 0:1c358ea10753 2001 #endif
spastor 0:1c358ea10753 2002 #endif
spastor 0:1c358ea10753 2003
spastor 0:1c358ea10753 2004