Xively Official / mbed-libxively-5d6fdd4

Dependents:   xively-jumpstart-demo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers http_transport_layer.c Source File

http_transport_layer.c

Go to the documentation of this file.
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 }