Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: EthernetInterface NTPClient iothub_amqp_transport iothub_client mbed-rtos mbed
Fork of iothub_client_sample_amqp by
socketio_mbed.c
00001 // Copyright (c) Microsoft. All rights reserved. 00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 00003 00004 #include <stdlib.h> 00005 #ifdef _CRTDBG_MAP_ALLOC 00006 #include <crtdbg.h> 00007 #endif 00008 00009 #include <stddef.h> 00010 #include <stdio.h> 00011 #include <string.h> 00012 #include "azure_c_shared_utility/socketio.h" 00013 #include "azure_c_shared_utility/singlylinkedlist.h" 00014 #include "azure_c_shared_utility/tcpsocketconnection_c.h" 00015 #include "azure_c_shared_utility/xlogging.h" 00016 00017 #define UNABLE_TO_COMPLETE -2 00018 #define MBED_RECEIVE_BYTES_VALUE 128 00019 00020 typedef enum IO_STATE_TAG 00021 { 00022 IO_STATE_CLOSED, 00023 IO_STATE_OPENING, 00024 IO_STATE_OPEN, 00025 IO_STATE_CLOSING, 00026 IO_STATE_ERROR 00027 } IO_STATE; 00028 00029 typedef struct PENDING_SOCKET_IO_TAG 00030 { 00031 unsigned char* bytes; 00032 size_t size; 00033 ON_SEND_COMPLETE on_send_complete; 00034 void* callback_context; 00035 SINGLYLINKEDLIST_HANDLE pending_io_list; 00036 } PENDING_SOCKET_IO; 00037 00038 typedef struct SOCKET_IO_INSTANCE_TAG 00039 { 00040 TCPSOCKETCONNECTION_HANDLE tcp_socket_connection; 00041 ON_BYTES_RECEIVED on_bytes_received; 00042 ON_IO_ERROR on_io_error; 00043 void* on_bytes_received_context; 00044 void* on_io_error_context; 00045 char* hostname; 00046 int port; 00047 IO_STATE io_state; 00048 SINGLYLINKEDLIST_HANDLE pending_io_list; 00049 } SOCKET_IO_INSTANCE; 00050 00051 /*this function will clone an option given by name and value*/ 00052 static void* socketio_CloneOption(const char* name, const void* value) 00053 { 00054 (void)(name, value); 00055 return NULL; 00056 } 00057 00058 /*this function destroys an option previously created*/ 00059 static void socketio_DestroyOption(const char* name, const void* value) 00060 { 00061 (void)(name, value); 00062 } 00063 00064 static OPTIONHANDLER_HANDLE socketio_retrieveoptions(CONCRETE_IO_HANDLE socket_io) 00065 { 00066 OPTIONHANDLER_HANDLE result; 00067 (void)socket_io; 00068 result = OptionHandler_Create(socketio_CloneOption, socketio_DestroyOption, socketio_setoption); 00069 if (result == NULL) 00070 { 00071 /*return as is*/ 00072 } 00073 else 00074 { 00075 /*insert here work to add the options to "result" handle*/ 00076 } 00077 return result; 00078 } 00079 00080 static const IO_INTERFACE_DESCRIPTION socket_io_interface_description = 00081 { 00082 socketio_retrieveoptions, 00083 socketio_create, 00084 socketio_destroy, 00085 socketio_open, 00086 socketio_close, 00087 socketio_send, 00088 socketio_dowork, 00089 socketio_setoption 00090 }; 00091 00092 static void indicate_error(SOCKET_IO_INSTANCE* socket_io_instance) 00093 { 00094 if (socket_io_instance->on_io_error != NULL) 00095 { 00096 socket_io_instance->on_io_error(socket_io_instance->on_io_error_context); 00097 } 00098 } 00099 00100 static int add_pending_io(SOCKET_IO_INSTANCE* socket_io_instance, const unsigned char* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context) 00101 { 00102 int result; 00103 PENDING_SOCKET_IO* pending_socket_io = (PENDING_SOCKET_IO*)malloc(sizeof(PENDING_SOCKET_IO)); 00104 if (pending_socket_io == NULL) 00105 { 00106 result = __LINE__; 00107 } 00108 else 00109 { 00110 pending_socket_io->bytes = (unsigned char*)malloc(size); 00111 if (pending_socket_io->bytes == NULL) 00112 { 00113 free(pending_socket_io); 00114 result = __LINE__; 00115 } 00116 else 00117 { 00118 pending_socket_io->size = size; 00119 pending_socket_io->on_send_complete = on_send_complete; 00120 pending_socket_io->callback_context = callback_context; 00121 pending_socket_io->pending_io_list = socket_io_instance->pending_io_list; 00122 (void)memcpy(pending_socket_io->bytes, buffer, size); 00123 00124 if (singlylinkedlist_add(socket_io_instance->pending_io_list, pending_socket_io) == NULL) 00125 { 00126 free(pending_socket_io->bytes); 00127 free(pending_socket_io); 00128 result = __LINE__; 00129 } 00130 else 00131 { 00132 result = 0; 00133 } 00134 } 00135 } 00136 00137 return result; 00138 } 00139 00140 CONCRETE_IO_HANDLE socketio_create(void* io_create_parameters) 00141 { 00142 SOCKETIO_CONFIG* socket_io_config = io_create_parameters; 00143 SOCKET_IO_INSTANCE* result; 00144 00145 if (socket_io_config == NULL) 00146 { 00147 result = NULL; 00148 } 00149 else 00150 { 00151 result = malloc(sizeof(SOCKET_IO_INSTANCE)); 00152 if (result != NULL) 00153 { 00154 result->pending_io_list = singlylinkedlist_create(); 00155 if (result->pending_io_list == NULL) 00156 { 00157 free(result); 00158 result = NULL; 00159 } 00160 else 00161 { 00162 result->hostname = (char*)malloc(strlen(socket_io_config->hostname) + 1); 00163 if (result->hostname == NULL) 00164 { 00165 singlylinkedlist_destroy(result->pending_io_list); 00166 free(result); 00167 result = NULL; 00168 } 00169 else 00170 { 00171 strcpy(result->hostname, socket_io_config->hostname); 00172 result->port = socket_io_config->port; 00173 result->on_bytes_received = NULL; 00174 result->on_io_error = NULL; 00175 result->on_bytes_received_context = NULL; 00176 result->on_io_error_context = NULL; 00177 result->io_state = IO_STATE_CLOSED; 00178 result->tcp_socket_connection = NULL; 00179 } 00180 } 00181 } 00182 } 00183 00184 return result; 00185 } 00186 00187 void socketio_destroy(CONCRETE_IO_HANDLE socket_io) 00188 { 00189 if (socket_io != NULL) 00190 { 00191 SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io; 00192 00193 tcpsocketconnection_destroy(socket_io_instance->tcp_socket_connection); 00194 00195 /* clear all pending IOs */ 00196 LIST_ITEM_HANDLE first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list); 00197 while (first_pending_io != NULL) 00198 { 00199 PENDING_SOCKET_IO* pending_socket_io = (PENDING_SOCKET_IO*)singlylinkedlist_item_get_value(first_pending_io); 00200 if (pending_socket_io != NULL) 00201 { 00202 free(pending_socket_io->bytes); 00203 free(pending_socket_io); 00204 } 00205 00206 (void)singlylinkedlist_remove(socket_io_instance->pending_io_list, first_pending_io); 00207 first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list); 00208 } 00209 00210 singlylinkedlist_destroy(socket_io_instance->pending_io_list); 00211 free(socket_io_instance->hostname); 00212 free(socket_io); 00213 } 00214 } 00215 00216 int socketio_open(CONCRETE_IO_HANDLE socket_io, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context) 00217 { 00218 int result; 00219 00220 SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io; 00221 if (socket_io == NULL) 00222 { 00223 result = __LINE__; 00224 } 00225 else 00226 { 00227 socket_io_instance->tcp_socket_connection = tcpsocketconnection_create(); 00228 if (socket_io_instance->tcp_socket_connection == NULL) 00229 { 00230 result = __LINE__; 00231 } 00232 else 00233 { 00234 if (tcpsocketconnection_connect(socket_io_instance->tcp_socket_connection, socket_io_instance->hostname, socket_io_instance->port) != 0) 00235 { 00236 tcpsocketconnection_destroy(socket_io_instance->tcp_socket_connection); 00237 socket_io_instance->tcp_socket_connection = NULL; 00238 result = __LINE__; 00239 } 00240 else 00241 { 00242 tcpsocketconnection_set_blocking(socket_io_instance->tcp_socket_connection, false, 0); 00243 00244 socket_io_instance->on_bytes_received = on_bytes_received; 00245 socket_io_instance->on_bytes_received_context = on_bytes_received_context; 00246 00247 socket_io_instance->on_io_error = on_io_error; 00248 socket_io_instance->on_io_error_context = on_io_error_context; 00249 00250 socket_io_instance->io_state = IO_STATE_OPEN; 00251 00252 if (on_io_open_complete != NULL) 00253 { 00254 on_io_open_complete(on_io_open_complete_context, IO_OPEN_OK); 00255 } 00256 00257 result = 0; 00258 } 00259 } 00260 } 00261 00262 return result; 00263 } 00264 00265 int socketio_close(CONCRETE_IO_HANDLE socket_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context) 00266 { 00267 int result = 0; 00268 00269 if (socket_io == NULL) 00270 { 00271 result = __LINE__; 00272 } 00273 else 00274 { 00275 SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io; 00276 00277 if ((socket_io_instance->io_state == IO_STATE_CLOSED) || 00278 (socket_io_instance->io_state == IO_STATE_CLOSING)) 00279 { 00280 result = __LINE__; 00281 } 00282 else 00283 { 00284 tcpsocketconnection_close(socket_io_instance->tcp_socket_connection); 00285 socket_io_instance->tcp_socket_connection = NULL; 00286 socket_io_instance->io_state = IO_STATE_CLOSED; 00287 00288 if (on_io_close_complete != NULL) 00289 { 00290 on_io_close_complete(callback_context); 00291 } 00292 00293 result = 0; 00294 } 00295 } 00296 00297 return result; 00298 } 00299 00300 int socketio_send(CONCRETE_IO_HANDLE socket_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context) 00301 { 00302 int result; 00303 00304 if ((socket_io == NULL) || 00305 (buffer == NULL) || 00306 (size == 0)) 00307 { 00308 /* Invalid arguments */ 00309 result = __LINE__; 00310 } 00311 else 00312 { 00313 SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io; 00314 if (socket_io_instance->io_state != IO_STATE_OPEN) 00315 { 00316 result = __LINE__; 00317 } 00318 else 00319 { 00320 LIST_ITEM_HANDLE first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list); 00321 if (first_pending_io != NULL) 00322 { 00323 if (add_pending_io(socket_io_instance, buffer, size, on_send_complete, callback_context) != 0) 00324 { 00325 result = __LINE__; 00326 } 00327 else 00328 { 00329 result = 0; 00330 } 00331 } 00332 else 00333 { 00334 int send_result = tcpsocketconnection_send(socket_io_instance->tcp_socket_connection, buffer, size); 00335 if (send_result != size) 00336 { 00337 if (send_result < 0) 00338 { 00339 send_result = 0; 00340 } 00341 00342 /* queue data */ 00343 if (add_pending_io(socket_io_instance, (unsigned char*)buffer + send_result, size - send_result, on_send_complete, callback_context) != 0) 00344 { 00345 result = __LINE__; 00346 } 00347 else 00348 { 00349 result = 0; 00350 } 00351 } 00352 else 00353 { 00354 if (on_send_complete != NULL) 00355 { 00356 on_send_complete(callback_context, IO_SEND_OK); 00357 } 00358 00359 result = 0; 00360 } 00361 } 00362 } 00363 } 00364 00365 return result; 00366 } 00367 00368 void socketio_dowork(CONCRETE_IO_HANDLE socket_io) 00369 { 00370 if (socket_io != NULL) 00371 { 00372 SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io; 00373 if (socket_io_instance->io_state == IO_STATE_OPEN) 00374 { 00375 int received = 1; 00376 00377 LIST_ITEM_HANDLE first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list); 00378 while (first_pending_io != NULL) 00379 { 00380 PENDING_SOCKET_IO* pending_socket_io = (PENDING_SOCKET_IO*)singlylinkedlist_item_get_value(first_pending_io); 00381 if (pending_socket_io == NULL) 00382 { 00383 socket_io_instance->io_state = IO_STATE_ERROR; 00384 indicate_error(socket_io_instance); 00385 break; 00386 } 00387 00388 int send_result = tcpsocketconnection_send(socket_io_instance->tcp_socket_connection, (const char*)pending_socket_io->bytes, pending_socket_io->size); 00389 if (send_result != pending_socket_io->size) 00390 { 00391 if (send_result < 0) 00392 { 00393 if (send_result < UNABLE_TO_COMPLETE) 00394 { 00395 // Bad error. Indicate as much. 00396 socket_io_instance->io_state = IO_STATE_ERROR; 00397 indicate_error(socket_io_instance); 00398 } 00399 break; 00400 } 00401 else 00402 { 00403 /* send something, wait for the rest */ 00404 (void)memmove(pending_socket_io->bytes, pending_socket_io->bytes + send_result, pending_socket_io->size - send_result); 00405 } 00406 } 00407 else 00408 { 00409 if (pending_socket_io->on_send_complete != NULL) 00410 { 00411 pending_socket_io->on_send_complete(pending_socket_io->callback_context, IO_SEND_OK); 00412 } 00413 00414 free(pending_socket_io->bytes); 00415 free(pending_socket_io); 00416 if (singlylinkedlist_remove(socket_io_instance->pending_io_list, first_pending_io) != 0) 00417 { 00418 socket_io_instance->io_state = IO_STATE_ERROR; 00419 indicate_error(socket_io_instance); 00420 } 00421 } 00422 00423 first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list); 00424 } 00425 00426 while (received > 0) 00427 { 00428 unsigned char* recv_bytes = malloc(MBED_RECEIVE_BYTES_VALUE); 00429 if (recv_bytes == NULL) 00430 { 00431 LogError("Socketio_Failure: NULL allocating input buffer."); 00432 indicate_error(socket_io_instance); 00433 } 00434 else 00435 { 00436 received = tcpsocketconnection_receive(socket_io_instance->tcp_socket_connection, (char*)recv_bytes, MBED_RECEIVE_BYTES_VALUE); 00437 if (received > 0) 00438 { 00439 if (socket_io_instance->on_bytes_received != NULL) 00440 { 00441 /* explictly ignoring here the result of the callback */ 00442 (void)socket_io_instance->on_bytes_received(socket_io_instance->on_bytes_received_context, recv_bytes, received); 00443 } 00444 } 00445 free(recv_bytes); 00446 } 00447 } 00448 } 00449 } 00450 } 00451 00452 int socketio_setoption(CONCRETE_IO_HANDLE socket_io, const char* optionName, const void* value) 00453 { 00454 /* Not implementing any options */ 00455 return __LINE__; 00456 } 00457 00458 const IO_INTERFACE_DESCRIPTION* socketio_get_interface_description(void) 00459 { 00460 return &socket_io_interface_description; 00461 } 00462
Generated on Tue Jul 12 2022 12:43:23 by
