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.
Dependents: STM32F746_iothub_client_sample_mqtt f767zi_mqtt iothub_client_sample_amqp iothub_client_sample_http ... more
xio.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 "azure_c_shared_utility/gballoc.h" 00007 #include "azure_c_shared_utility/optimize_size.h" 00008 #include "azure_c_shared_utility/xio.h" 00009 #include "azure_c_shared_utility/xlogging.h" 00010 00011 static const char* CONCRETE_OPTIONS = "concreteOptions"; 00012 00013 typedef struct XIO_INSTANCE_TAG 00014 { 00015 const IO_INTERFACE_DESCRIPTION* io_interface_description; 00016 CONCRETE_IO_HANDLE concrete_xio_handle; 00017 } XIO_INSTANCE; 00018 00019 XIO_HANDLE xio_create(const IO_INTERFACE_DESCRIPTION* io_interface_description, const void* xio_create_parameters) 00020 { 00021 XIO_INSTANCE* xio_instance; 00022 /* Codes_SRS_XIO_01_003: [If the argument io_interface_description is NULL, xio_create shall return NULL.] */ 00023 if ((io_interface_description == NULL) || 00024 /* Codes_SRS_XIO_01_004: [If any io_interface_description member is NULL, xio_create shall return NULL.] */ 00025 (io_interface_description->concrete_io_retrieveoptions == NULL) || 00026 (io_interface_description->concrete_io_create == NULL) || 00027 (io_interface_description->concrete_io_destroy == NULL) || 00028 (io_interface_description->concrete_io_open == NULL) || 00029 (io_interface_description->concrete_io_close == NULL) || 00030 (io_interface_description->concrete_io_send == NULL) || 00031 (io_interface_description->concrete_io_dowork == NULL) || 00032 (io_interface_description->concrete_io_setoption == NULL)) 00033 { 00034 xio_instance = NULL; 00035 } 00036 else 00037 { 00038 xio_instance = (XIO_INSTANCE*)malloc(sizeof(XIO_INSTANCE)); 00039 00040 /* Codes_SRS_XIO_01_017: [If allocating the memory needed for the IO interface fails then xio_create shall return NULL.] */ 00041 if (xio_instance != NULL) 00042 { 00043 /* Codes_SRS_XIO_01_001: [xio_create shall return on success a non-NULL handle to a new IO interface.] */ 00044 xio_instance->io_interface_description = io_interface_description; 00045 00046 /* Codes_SRS_XIO_01_002: [In order to instantiate the concrete IO implementation the function concrete_io_create from the io_interface_description shall be called, passing the xio_create_parameters argument.] */ 00047 xio_instance->concrete_xio_handle = xio_instance->io_interface_description->concrete_io_create((void*)xio_create_parameters); 00048 00049 /* Codes_SRS_XIO_01_016: [If the underlying concrete_io_create call fails, xio_create shall return NULL.] */ 00050 if (xio_instance->concrete_xio_handle == NULL) 00051 { 00052 free(xio_instance); 00053 xio_instance = NULL; 00054 } 00055 } 00056 } 00057 return (XIO_HANDLE)xio_instance; 00058 } 00059 00060 void xio_destroy(XIO_HANDLE xio) 00061 { 00062 /* Codes_SRS_XIO_01_007: [If the argument io is NULL, xio_destroy shall do nothing.] */ 00063 if (xio != NULL) 00064 { 00065 XIO_INSTANCE* xio_instance = (XIO_INSTANCE*)xio; 00066 00067 /* Codes_SRS_XIO_01_006: [xio_destroy shall also call the concrete_io_destroy function that is member of the io_interface_description argument passed to xio_create, while passing as argument to concrete_io_destroy the result of the underlying concrete_io_create handle that was called as part of the xio_create call.] */ 00068 xio_instance->io_interface_description->concrete_io_destroy(xio_instance->concrete_xio_handle); 00069 00070 /* Codes_SRS_XIO_01_005: [xio_destroy shall free all resources associated with the IO handle.] */ 00071 free(xio_instance); 00072 } 00073 } 00074 00075 int xio_open(XIO_HANDLE xio, 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) 00076 { 00077 int result; 00078 00079 if (xio == NULL) 00080 { 00081 /* Codes_SRS_XIO_01_021: [If handle is NULL, xio_open shall return a non-zero value.] */ 00082 result = __FAILURE__; 00083 } 00084 else 00085 { 00086 XIO_INSTANCE* xio_instance = (XIO_INSTANCE*)xio; 00087 00088 /* Codes_SRS_XIO_01_019: [xio_open shall call the specific concrete_xio_open function specified in xio_create, passing callback function and context arguments for three events: open completed, bytes received, and IO error.] */ 00089 if (xio_instance->io_interface_description->concrete_io_open(xio_instance->concrete_xio_handle, on_io_open_complete, on_io_open_complete_context, on_bytes_received, on_bytes_received_context, on_io_error, on_io_error_context) != 0) 00090 { 00091 /* Codes_SRS_XIO_01_022: [If the underlying concrete_io_open fails, xio_open shall return a non-zero value.] */ 00092 result = __FAILURE__; 00093 } 00094 else 00095 { 00096 /* Codes_SRS_XIO_01_020: [On success, xio_open shall return 0.] */ 00097 result = 0; 00098 } 00099 } 00100 00101 return result; 00102 } 00103 00104 int xio_close(XIO_HANDLE xio, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context) 00105 { 00106 int result; 00107 00108 if (xio == NULL) 00109 { 00110 /* Codes_SRS_XIO_01_025: [If handle is NULL, xio_close shall return a non-zero value.] */ 00111 result = __FAILURE__; 00112 } 00113 else 00114 { 00115 XIO_INSTANCE* xio_instance = (XIO_INSTANCE*)xio; 00116 00117 /* Codes_SRS_XIO_01_023: [xio_close shall call the specific concrete_io_close function specified in xio_create.] */ 00118 if (xio_instance->io_interface_description->concrete_io_close(xio_instance->concrete_xio_handle, on_io_close_complete, callback_context) != 0) 00119 { 00120 /* Codes_SRS_XIO_01_026: [If the underlying concrete_io_close fails, xio_close shall return a non-zero value.] */ 00121 result = __FAILURE__; 00122 } 00123 else 00124 { 00125 /* Codes_SRS_XIO_01_024: [On success, xio_close shall return 0.] */ 00126 result = 0; 00127 } 00128 } 00129 00130 return result; 00131 } 00132 00133 int xio_send(XIO_HANDLE xio, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context) 00134 { 00135 int result; 00136 00137 /* Codes_SRS_XIO_01_011: [No error check shall be performed on buffer and size.] */ 00138 /* Codes_SRS_XIO_01_010: [If handle is NULL, xio_send shall return a non-zero value.] */ 00139 if (xio == NULL) 00140 { 00141 result = __FAILURE__; 00142 } 00143 else 00144 { 00145 XIO_INSTANCE* xio_instance = (XIO_INSTANCE*)xio; 00146 00147 /* Codes_SRS_XIO_01_008: [xio_send shall pass the sequence of bytes pointed to by buffer to the concrete IO implementation specified in xio_create, by calling the concrete_io_send function while passing down the buffer and size arguments to it.] */ 00148 /* Codes_SRS_XIO_01_009: [On success, xio_send shall return 0.] */ 00149 /* Codes_SRS_XIO_01_015: [If the underlying concrete_io_send fails, xio_send shall return a non-zero value.] */ 00150 /* Codes_SRS_XIO_01_027: [xio_send shall pass to the concrete_io_send function the on_send_complete and callback_context arguments.] */ 00151 result = xio_instance->io_interface_description->concrete_io_send(xio_instance->concrete_xio_handle, buffer, size, on_send_complete, callback_context); 00152 } 00153 00154 return result; 00155 } 00156 00157 void xio_dowork(XIO_HANDLE xio) 00158 { 00159 /* Codes_SRS_XIO_01_018: [When the handle argument is NULL, xio_dowork shall do nothing.] */ 00160 if (xio != NULL) 00161 { 00162 XIO_INSTANCE* xio_instance = (XIO_INSTANCE*)xio; 00163 00164 /* Codes_SRS_XIO_01_012: [xio_dowork shall call the concrete XIO implementation specified in xio_create, by calling the concrete_io_dowork function.] */ 00165 xio_instance->io_interface_description->concrete_io_dowork(xio_instance->concrete_xio_handle); 00166 } 00167 } 00168 00169 int xio_setoption(XIO_HANDLE xio, const char* optionName, const void* value) 00170 { 00171 int result; 00172 00173 /* Codes_SRS_XIO_03_030: [If the xio argument or the optionName argument is NULL, xio_setoption shall return a non-zero value.] */ 00174 if (xio == NULL || optionName == NULL) 00175 { 00176 result = __FAILURE__; 00177 } 00178 else 00179 { 00180 XIO_INSTANCE* xio_instance = (XIO_INSTANCE*)xio; 00181 00182 if (strcmp(CONCRETE_OPTIONS, optionName) == 0) 00183 { 00184 /*then value is a pointer to OPTIONHANDLER_HANDLE*/ 00185 if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, xio_instance->concrete_xio_handle) != OPTIONHANDLER_OK) 00186 { 00187 LogError("unable to OptionHandler_FeedOptions"); 00188 result = __FAILURE__; 00189 } 00190 else 00191 { 00192 result = 0; 00193 } 00194 } 00195 else /*passthrough*/ 00196 { 00197 /* Codes_SRS_XIO_003_028: [xio_setoption shall pass the optionName and value to the concrete IO implementation specified in xio_create by invoking the concrete_xio_setoption function.] */ 00198 /* Codes_SRS_XIO_03_029: [xio_setoption shall return 0 upon success.] */ 00199 /* Codes_SRS_XIO_03_031: [If the underlying concrete_xio_setoption fails, xio_setOption shall return a non-zero value.] */ 00200 result = xio_instance->io_interface_description->concrete_io_setoption(xio_instance->concrete_xio_handle, optionName, value); 00201 } 00202 } 00203 00204 return result; 00205 } 00206 00207 static void* xio_CloneOption(const char* name, const void* value) 00208 { 00209 void *result; 00210 if ( 00211 (name == NULL) || 00212 (value == NULL) 00213 ) 00214 { 00215 LogError("invalid argument detected: const char* name=%p, const void* value=%p", name, value); 00216 result = NULL; 00217 } 00218 else 00219 { 00220 if (strcmp(name, CONCRETE_OPTIONS) == 0) 00221 { 00222 result = (void*)value; 00223 } 00224 else 00225 { 00226 LogError("unknown option: %s", name); 00227 result = NULL; 00228 } 00229 } 00230 return result; 00231 } 00232 00233 00234 static void xio_DestroyOption(const char* name, const void* value) 00235 { 00236 if ( 00237 (name == NULL) || 00238 (value == NULL) 00239 ) 00240 { 00241 LogError("invalid argument detected: const char* name=%p, const void* value=%p", name, value); 00242 } 00243 else 00244 { 00245 if (strcmp(name, CONCRETE_OPTIONS) == 0) 00246 { 00247 OptionHandler_Destroy((OPTIONHANDLER_HANDLE)value); 00248 } 00249 else 00250 { 00251 LogError("unknown option: %s", name); 00252 } 00253 } 00254 } 00255 00256 OPTIONHANDLER_HANDLE xio_retrieveoptions(XIO_HANDLE xio) 00257 { 00258 OPTIONHANDLER_HANDLE result; 00259 00260 if (xio == NULL) 00261 { 00262 LogError("invalid argument detected: XIO_HANDLE xio=%p", xio); 00263 result = NULL; 00264 } 00265 else 00266 { 00267 XIO_INSTANCE* xio_instance = (XIO_INSTANCE*)xio; 00268 /*xio_retrieveoptions shall return a OPTIONHANDLER_HANDLE that has 1 option called "underlyingOptions" which is of type OPTIONHANDLER_HANDLE*/ 00269 result = OptionHandler_Create(xio_CloneOption, xio_DestroyOption, (pfSetOption)xio_setoption); 00270 if (result == NULL) 00271 { 00272 LogError("unable to OptionHandler_Create"); 00273 /*return as is*/ 00274 } 00275 else 00276 { 00277 OPTIONHANDLER_HANDLE concreteOptions = xio_instance->io_interface_description->concrete_io_retrieveoptions(xio_instance->concrete_xio_handle); 00278 if (concreteOptions == NULL) 00279 { 00280 LogError("unable to concrete_io_retrieveoptions"); 00281 OptionHandler_Destroy(result); 00282 result = NULL; 00283 } 00284 else 00285 { 00286 if (OptionHandler_AddOption(result, CONCRETE_OPTIONS, concreteOptions) != OPTIONHANDLER_OK) 00287 { 00288 LogError("unable to OptionHandler_AddOption"); 00289 OptionHandler_Destroy(concreteOptions); 00290 OptionHandler_Destroy(result); 00291 result = NULL; 00292 } 00293 else 00294 { 00295 /*all is fine*/ 00296 } 00297 } 00298 } 00299 } 00300 00301 return result; 00302 } 00303
Generated on Wed Jul 13 2022 23:38:02 by
1.7.2