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