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: xively-jumpstart-demo
http_transport_layer.c
00001 // Copyright (c) 2003-2013, LogMeIn, Inc. All rights reserved. 00002 // This is part of Xively C library, it is under the BSD 3-Clause license. 00003 00004 /** 00005 * \file http_transport_layer.c 00006 * \author Olgierd Humenczuk 00007 * \brief Implements HTTP _transport layer_ encoders and decoders specific to Xively REST/HTTP API [see http_transport_layer.h] 00008 */ 00009 00010 #include <string.h> 00011 #include <assert.h> 00012 #include <stdio.h> 00013 00014 #include "http_transport.h" 00015 #include "http_layer_queries.h" 00016 #include "http_consts.h" 00017 #include "http_layer_parser.h" 00018 #include "xi_macros.h" 00019 #include "xi_helpers.h" 00020 #include "xi_err.h" 00021 00022 static char XI_HTTP_QUERY_BUFFER[ XI_QUERY_BUFFER_SIZE + XI_CONTENT_BUFFER_SIZE ]; 00023 static char XI_HTTP_QUERY_DATA[ XI_CONTENT_BUFFER_SIZE ]; 00024 00025 00026 inline static char* http_encode_concat( char* buffer, size_t buffer_size 00027 , const char* query, const char* content, const char* data ) 00028 { 00029 int offset = 0; 00030 int size = ( int ) buffer_size; 00031 int s = 0; 00032 00033 s = snprintf( buffer, size, "%s", query ); 00034 XI_CHECK_S( s, size, offset, XI_HTTP_ENCODE_CREATE_DATASTREAM ); 00035 00036 if( content != 0 ) 00037 { 00038 s = snprintf( buffer + offset 00039 , XI_MAX( size - offset, 0 ) 00040 , "%s", content ); 00041 XI_CHECK_S( s, size, offset, XI_HTTP_ENCODE_CREATE_DATASTREAM ); 00042 } 00043 00044 s = snprintf( buffer + offset 00045 , XI_MAX( size - offset, 0 ) 00046 , "%s", XI_HTTP_CRLF ); 00047 XI_CHECK_S( s, size, offset, XI_HTTP_ENCODE_CREATE_DATASTREAM ); 00048 00049 00050 if( content != 0 && data != 0 ) 00051 { 00052 s = snprintf( buffer + offset 00053 , XI_MAX( size - offset, 0 ) 00054 , "%s", data ); 00055 XI_CHECK_S( s, size, offset, XI_HTTP_ENCODE_CREATE_DATASTREAM ); 00056 } 00057 00058 s = snprintf( buffer + offset 00059 , XI_MAX( size - offset, 0 ) 00060 , "%s", XI_HTTP_CRLF ); 00061 00062 XI_CHECK_S( s, size, offset, XI_HTTP_ENCODE_CREATE_DATASTREAM ); 00063 00064 return buffer; 00065 00066 err_handling: 00067 return 0; 00068 } 00069 00070 const char* http_encode_create_datastream( 00071 const data_layer_t* data_transport 00072 , const char* x_api_key 00073 , int32_t feed_id 00074 , const char *datastream_id 00075 , const xi_datapoint_t* datapoint ) 00076 { 00077 // prepare parts 00078 const char* data = data_transport->encode_create_datastream( 00079 datastream_id, datapoint ); 00080 00081 if( data == 0 ) { return 0; } 00082 00083 const char* query = http_construct_request_datastream( 00084 XI_HTTP_QUERY_POST, &feed_id 00085 , 0, x_api_key 00086 ); 00087 00088 if( query == 0 ) { return 0; } 00089 00090 const char* content = http_construct_content( strlen( data ) ); 00091 00092 return http_encode_concat( XI_HTTP_QUERY_BUFFER, sizeof( XI_HTTP_QUERY_BUFFER ) 00093 , query, content, data ); 00094 } 00095 00096 const char* http_encode_update_datastream( 00097 const data_layer_t* data_layer 00098 , const char* x_api_key 00099 , int32_t feed_id 00100 , const char *datastream_id 00101 , const xi_datapoint_t* datapoint ) 00102 { 00103 // prepare parts 00104 const char* data = data_layer->encode_datapoint( datapoint ); 00105 00106 if( data == 0 ) { return 0; } 00107 00108 const char* query = http_construct_request_datastream( 00109 XI_HTTP_QUERY_PUT 00110 , &feed_id 00111 , datastream_id 00112 , x_api_key 00113 ); 00114 00115 if( query == 0 ) { return 0; } 00116 00117 const char* content = http_construct_content( strlen( data ) ); 00118 00119 return http_encode_concat( XI_HTTP_QUERY_BUFFER, sizeof( XI_HTTP_QUERY_BUFFER ) 00120 , query, content, data ); 00121 } 00122 00123 const char* http_encode_get_datastream( 00124 const data_layer_t* data_layer 00125 , const char* x_api_key 00126 , int32_t feed_id 00127 , const char *datastream_id ) 00128 { 00129 XI_UNUSED( data_layer ); 00130 00131 // prepare parts 00132 const char* query = http_construct_request_datastream( 00133 XI_HTTP_QUERY_GET 00134 , &feed_id 00135 , datastream_id 00136 , x_api_key ); 00137 00138 if( query == 0 ) { return 0; } 00139 00140 return http_encode_concat( XI_HTTP_QUERY_BUFFER, sizeof( XI_HTTP_QUERY_BUFFER ) 00141 , query, 0, 0 ); 00142 } 00143 00144 const char* http_encode_delete_datastream( 00145 const data_layer_t* data_layer 00146 , const char* x_api_key 00147 , int32_t feed_id 00148 , const char *datastream_id ) 00149 { 00150 XI_UNUSED( data_layer ); 00151 00152 // prepare parts 00153 const char* query = http_construct_request_datastream( 00154 XI_HTTP_QUERY_DELETE 00155 , &feed_id 00156 , datastream_id 00157 , x_api_key ); 00158 00159 if( query == 0 ) { return 0; } 00160 00161 return http_encode_concat( XI_HTTP_QUERY_BUFFER, sizeof( XI_HTTP_QUERY_BUFFER ) 00162 , query, 0, 0 ); 00163 } 00164 00165 const char* http_encode_delete_datapoint( 00166 const data_layer_t* data_transport 00167 , const char* x_api_key 00168 , int32_t feed_id 00169 , const char *datastream_id 00170 , const xi_datapoint_t* o ) 00171 { 00172 XI_UNUSED( data_transport ); 00173 00174 struct tm* ptm = xi_gmtime( 00175 ( time_t* ) &o->timestamp.timestamp ); 00176 00177 int s = snprintf( XI_HTTP_QUERY_BUFFER 00178 , sizeof( XI_HTTP_QUERY_BUFFER ) 00179 , "%s/datapoints/%04d-%02d-%02dT%02d:%02d:%02d.%06ldZ" 00180 , datastream_id 00181 , ptm->tm_year + 1900 00182 , ptm->tm_mon + 1 00183 , ptm->tm_mday 00184 , ptm->tm_hour 00185 , ptm->tm_min 00186 , ptm->tm_sec 00187 , o->timestamp.micro ); 00188 00189 XI_CHECK_SIZE( s, ( int ) sizeof( XI_HTTP_QUERY_BUFFER ) 00190 , XI_HTTP_ENCODE_DELETE_DATAPOINT ); 00191 00192 { 00193 // prepare parts 00194 const char* query = http_construct_request_datastream( 00195 XI_HTTP_QUERY_DELETE 00196 , &feed_id 00197 , XI_HTTP_QUERY_BUFFER 00198 , x_api_key ); 00199 00200 if( query == 0 ) { return 0; } 00201 00202 return http_encode_concat( XI_HTTP_QUERY_BUFFER, sizeof( XI_HTTP_QUERY_BUFFER ) 00203 , query, 0, 0 ); 00204 } 00205 00206 err_handling: 00207 return 0; 00208 } 00209 00210 const char* http_encode_update_feed( 00211 const data_layer_t* data_layer 00212 , const char* x_api_key 00213 , const xi_feed_t* feed ) 00214 { 00215 // prepare buffer 00216 XI_CLEAR_STATIC_BUFFER( XI_HTTP_QUERY_DATA ); 00217 00218 // PRECONDITIONS 00219 assert( data_layer != 0 ); 00220 assert( x_api_key != 0 ); 00221 assert( feed != 0 ); 00222 00223 // variables initialization 00224 const char* content = 0; 00225 const char* query = 0; 00226 00227 { // data part preparation 00228 int offset = 0; 00229 int size = sizeof( XI_HTTP_QUERY_DATA ); 00230 int s = 0; 00231 00232 // for each datastream 00233 // generate the list of datapoints that you want to update 00234 for( size_t i = 0; i < feed->datastream_count; ++i ) 00235 { 00236 const xi_datastream_t* curr_datastream = &feed->datastreams[ i ]; 00237 00238 // for each datapoint 00239 for( size_t j = 0; j < curr_datastream->datapoint_count; ++j ) 00240 { 00241 const xi_datapoint_t* curr_datapoint 00242 = &curr_datastream->datapoints[ j ]; 00243 00244 // add the datastream id to the buffer 00245 s = snprintf( 00246 XI_HTTP_QUERY_DATA + offset, XI_MAX( size - offset, 0 ), "%s," 00247 , curr_datastream->datastream_id ); 00248 00249 XI_CHECK_S( s, size, offset, XI_HTTP_ENCODE_UPDATE_FEED ); 00250 00251 // add the datapoint data to the buffer 00252 s = data_layer->encode_datapoint_in_place( 00253 XI_HTTP_QUERY_DATA + offset, XI_MAX( size - offset, 0 ) 00254 , curr_datapoint ); 00255 00256 XI_CHECK_S( s, size, offset, XI_HTTP_ENCODE_UPDATE_FEED ); 00257 } 00258 } 00259 } 00260 00261 query = http_construct_request_feed( 00262 XI_HTTP_QUERY_PUT 00263 , &feed->feed_id 00264 , x_api_key 00265 , 0 00266 ); 00267 00268 if( query == 0 ) { goto err_handling; } 00269 00270 content = http_construct_content( strlen( XI_HTTP_QUERY_DATA ) ); 00271 00272 return http_encode_concat( XI_HTTP_QUERY_BUFFER, sizeof( XI_HTTP_QUERY_BUFFER ) 00273 , query, content, XI_HTTP_QUERY_DATA ); 00274 00275 err_handling: 00276 return 0; 00277 } 00278 00279 const char* http_encode_get_feed( 00280 const data_layer_t* data_layer 00281 , const char* x_api_key 00282 , const xi_feed_t* feed ) 00283 { 00284 // prepare buffer 00285 XI_CLEAR_STATIC_BUFFER( XI_HTTP_QUERY_DATA ); 00286 00287 // PRECONDITIONS 00288 assert( data_layer != 0 ); 00289 assert( x_api_key != 0 ); 00290 assert( feed != 0 ); 00291 00292 // variables initialization 00293 const char* query = 0; 00294 00295 { // data part preparation 00296 int offset = 0; 00297 int size = sizeof( XI_HTTP_QUERY_DATA ); 00298 int s = 0; 00299 00300 // for each datastream 00301 // generate the list of datastreams that you want to get 00302 for( size_t i = 0; i < feed->datastream_count; ++i ) 00303 { 00304 const xi_datastream_t* curr_datastream = &feed->datastreams[ i ]; 00305 00306 // add the datastream id to the buffer 00307 s = snprintf( 00308 XI_HTTP_QUERY_DATA + offset, XI_MAX( size - offset, 0 ), i == 0 ? "?datastreams=%s" : ",%s" 00309 , curr_datastream->datastream_id ); 00310 00311 XI_CHECK_S( s, size, offset, XI_HTTP_ENCODE_UPDATE_FEED ); 00312 } 00313 } 00314 00315 query = http_construct_request_feed( 00316 XI_HTTP_QUERY_GET 00317 , &feed->feed_id 00318 , x_api_key 00319 , XI_HTTP_QUERY_DATA 00320 ); 00321 00322 if( query == 0 ) { goto err_handling; } 00323 00324 return http_encode_concat( XI_HTTP_QUERY_BUFFER, sizeof( XI_HTTP_QUERY_BUFFER ) 00325 , query, 0, 0 ); 00326 00327 err_handling: 00328 return 0; 00329 } 00330 00331 const char* http_encode_datapoint_delete_range( 00332 const data_layer_t* data_layer 00333 , const char* x_api_key 00334 , int32_t feed_id 00335 , const char* datastream_id 00336 , const xi_timestamp_t* start 00337 , const xi_timestamp_t* end ) 00338 { 00339 XI_UNUSED( data_layer ); 00340 00341 struct tm stm; 00342 struct tm etm; 00343 00344 { 00345 struct tm* tmp = start ? xi_gmtime( 00346 ( time_t* ) &start->timestamp ) : 0; 00347 memcpy( &stm, tmp, sizeof( struct tm ) ); 00348 } 00349 00350 { 00351 struct tm* tmp = end ? xi_gmtime( 00352 ( time_t* ) &end->timestamp ) : 0; 00353 memcpy( &etm, tmp, sizeof( struct tm ) ); 00354 } 00355 00356 int s = 0; 00357 00358 if( start && end ) 00359 { 00360 s = snprintf( XI_HTTP_QUERY_BUFFER 00361 , sizeof( XI_HTTP_QUERY_BUFFER ) 00362 , "%s/datapoints?start=%04d-%02d-%02dT%02d:%02d:%02d.%06ldZ&end=%04d-%02d-%02dT%02d:%02d:%02d.%06ldZ" 00363 , datastream_id 00364 , stm.tm_year + 1900, stm.tm_mon + 1, stm.tm_mday 00365 , stm.tm_hour, stm.tm_min, stm.tm_sec, start->micro 00366 , etm.tm_year + 1900, etm.tm_mon + 1, etm.tm_mday 00367 , etm.tm_hour, etm.tm_min, etm.tm_sec, end->micro ); 00368 } 00369 else if( start ) 00370 { 00371 s = snprintf( XI_HTTP_QUERY_BUFFER 00372 , sizeof( XI_HTTP_QUERY_BUFFER ) 00373 , "%s/datapoints?start=%04d-%02d-%02dT%02d:%02d:%02d.%06ldZ" 00374 , datastream_id 00375 , stm.tm_year + 1900, stm.tm_mon + 1, stm.tm_mday 00376 , stm.tm_hour, stm.tm_min, stm.tm_sec, start->micro ); 00377 } 00378 else if( end ) 00379 { 00380 s = snprintf( XI_HTTP_QUERY_BUFFER 00381 , sizeof( XI_HTTP_QUERY_BUFFER ) 00382 , "%s/datapoints?end=%04d-%02d-%02dT%02d:%02d:%02d.%06ldZ" 00383 , datastream_id 00384 , etm.tm_year + 1900, etm.tm_mon + 1, etm.tm_mday 00385 , etm.tm_hour, etm.tm_min, etm.tm_sec, end->micro ); 00386 } 00387 else 00388 { 00389 // just set an error 00390 XI_CHECK_CND( 1 == 0, XI_HTTP_ENCODE_DELETE_RANGE_DATAPOINT ); 00391 } 00392 00393 XI_CHECK_SIZE( s, ( int ) sizeof( XI_HTTP_QUERY_BUFFER ) 00394 , XI_HTTP_ENCODE_DELETE_RANGE_DATAPOINT ); 00395 00396 { 00397 // prepare parts 00398 const char* query = http_construct_request_datastream( 00399 XI_HTTP_QUERY_DELETE 00400 , &feed_id 00401 , XI_HTTP_QUERY_BUFFER 00402 , x_api_key ); 00403 00404 if( query == 0 ) { return 0; } 00405 00406 return http_encode_concat( XI_HTTP_QUERY_BUFFER, sizeof( XI_HTTP_QUERY_BUFFER ) 00407 , query, 0, 0 ); 00408 } 00409 00410 err_handling: 00411 return 0; 00412 } 00413 00414 00415 const xi_response_t* http_decode_reply( 00416 const data_layer_t* data_layer 00417 , const char* response ) 00418 { 00419 XI_UNUSED( data_layer ); 00420 00421 static xi_response_t __tmp; 00422 static http_response_t* __response = &__tmp.http; 00423 00424 // just pass it further 00425 if( parse_http( __response, response ) == 0 ) 00426 { 00427 return 0; 00428 } 00429 00430 // pass it to the data_layer 00431 return &__tmp; 00432 }
Generated on Wed Jul 13 2022 17:00:32 by
1.7.2