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