Ignore:
Timestamp:
Feb 1, 2019, 9:57:09 PM (5 years ago)
Author:
coas-nagasima
Message:

TINETとSocket APIなどを更新

File:
1 edited

Legend:

Unmodified
Added
Removed
  • asp3_tinet_ecnl_rx/trunk/app1_usb_watt_meter/src/client.c

    r350 r364  
    11/*
    22 *  TOPPERS ECHONET Lite Communication Middleware
    3  * 
     3 *
    44 *  Copyright (C) 2016 Cores Co., Ltd. Japan
    5  * 
     5 *
    66 *  上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
    77 *  ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
     
    2626 *      由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
    2727 *      免責すること.
    28  * 
     28 *
    2929 *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
    3030 *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
     
    3232 *  アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
    3333 *  の責任を負わない.
    34  * 
     34 *
    3535 *  @(#) $Id$
    3636 */
     
    4848#include "ff.h"
    4949#include "util/ntstdio.h"
     50#include "client.h"
     51#include "jsonsl.h"
    5052
    5153#define SKIP_PEER_VERIFICATION
    5254//#define SKIP_HOSTNAME_VERIFICATION
     55
     56const char SCOPE_DRIVE_FILE[] = "https://www.googleapis.com/auth/drive.file";
     57const char GRANT_TYPE_DEVICE[] = "http://oauth.net/grant_type/device/1.0";
     58
    5359char response[80];
    54 extern ntstdio_t ntstdio;
     60char errbuf[CURL_ERROR_SIZE];
     61
     62google_drive_t google_drive;
     63
     64void curl_setopt_common(CURL *curl);
     65int google_drive_error_callback(jsonsl_t jsn, jsonsl_error_t err,
     66        struct jsonsl_state_st *state, char *errat);
     67void google_drive_state_callback(jsonsl_t jsn, jsonsl_action_t action,
     68        struct jsonsl_state_st *state, const char *buf);
    5569
    5670void client_init(void)
    5771{
     72        google_drive_t *gd = &google_drive;
     73        jsonsl_t jsn;
     74
     75        memset(gd, 0, sizeof(google_drive_t));
     76        memcpy(gd->fname, "1:/log/20160101000000.log", sizeof(gd->fname));
     77
     78        jsn = gd->jsn = jsonsl_new(3);
     79        jsn->data = gd;
     80        jsn->error_callback = google_drive_error_callback;
     81        jsn->action_callback = google_drive_state_callback;
     82        jsonsl_enable_all_callbacks(jsn);
     83
    5884        //uITRON4_minit(ITRON_POOL_SIZE);
    5985
     
    6187}
    6288
    63 size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp)
    64 {
    65         int rest = size * nmemb;
     89size_t write_callback(void *buffer, size_t size, size_t nmemb, void *arg)
     90{
     91        google_drive_t *gd = (google_drive_t *)arg;
     92        jsonsl_t jsn = gd->jsn;
     93        size_t len = size * nmemb, pos;
     94        jsonsl_char_t data;
     95
     96        for (pos = 0; pos < len; pos++) {
     97                data = *((jsonsl_char_t *)&((uint8_t *)buffer)[pos]);
     98
     99                if ((gd->jsn_buf_pos >= 0) && (gd->jsn_buf_pos < sizeof(gd->jsn_buf)))
     100                        gd->jsn_buf[gd->jsn_buf_pos++] = data;
     101                jsonsl_feed(jsn, &data, 1);
     102        }
     103
     104        return len;
     105}
     106
     107void get_device_id_state_start(google_drive_t *gd, struct jsonsl_state_st *state, const char *buf)
     108{
     109        switch (gd->state) {
     110        case psRoot:
     111                if (state->level != 2) {
     112                        break;
     113                }
     114                else if (strcmp(buf, "device_code") == 0) {
     115                        gd->state = psDeviceCode;
     116                }
     117                else if (strcmp(buf, "user_code") == 0) {
     118                        gd->state = psUserCode;
     119                }
     120                else if (strcmp(buf, "expires_in") == 0) {
     121                        gd->state = psExpiresIn;
     122                }
     123                else if (strcmp(buf, "interval") == 0) {
     124                        gd->state = psInterval;
     125                }
     126                else if (strcmp(buf, "verification_url") == 0) {
     127                        gd->state = psVerificationUrl;
     128                }
     129                else if (strcmp(buf, "error") == 0) {
     130                        gd->state = psError;
     131                }
     132                else if (strcmp(buf, "error_description") == 0) {
     133                        gd->state = psErrorDescription;
     134                }
     135                break;
     136        case psDeviceCode:
     137                if (state->type == JSONSL_T_STRING) {
     138                        strlcpy(gd->credential.device_code, buf, sizeof(gd->credential.device_code));
     139                        gd->state = psRoot;
     140                }
     141                break;
     142        case psUserCode:
     143                if (state->type == JSONSL_T_STRING) {
     144                        strlcpy(gd->credential.user_code, buf, sizeof(gd->credential.user_code));
     145                        gd->state = psRoot;
     146                }
     147                break;
     148        case psExpiresIn:
     149                if (state->type == JSONSL_T_SPECIAL) {
     150                        gd->credential.expires_in = atoi(buf);
     151                        gd->state = psRoot;
     152                }
     153                break;
     154        case psInterval:
     155                if (state->type == JSONSL_T_SPECIAL) {
     156                        gd->credential.interval = atoi(buf);
     157                        gd->state = psRoot;
     158                }
     159                break;
     160        case psVerificationUrl:
     161                if (state->type == JSONSL_T_STRING) {
     162                        strlcpy(gd->credential.verification_url, buf, sizeof(gd->credential.verification_url));
     163                        gd->state = psRoot;
     164                }
     165                break;
     166        case psError:
     167                if (state->type == JSONSL_T_STRING) {
     168                        strlcpy(gd->error.error, buf, sizeof(gd->error.error));
     169                        gd->state = psRoot;
     170                }
     171                break;
     172        case psErrorDescription:
     173                if (state->type == JSONSL_T_STRING) {
     174                        strlcpy(gd->error.error_description, buf, sizeof(gd->error.error_description));
     175                        gd->state = psRoot;
     176                }
     177                break;
     178        }
     179}
     180
     181void get_device_id_state_end(google_drive_t *gd, struct jsonsl_state_st *state, const char *buf)
     182{
     183}
     184
     185int get_device_id(google_drive_t *gd, const char *scope)
     186{
     187        client_info_t *client_info = &gd->client_info;
     188        credential_t *credential = &gd->credential;
     189        CURLcode ret;
     190        CURL *curl;
     191        struct curl_slist *slist1;
     192        size_t len;
     193        char *postdata;
     194        jsonsl_t jsn = gd->jsn;
     195
     196        gd->jsn_buf_pos = -1;
     197
     198        jsonsl_reset(jsn);
     199        gd->start = get_device_id_state_start;
     200        gd->end = get_device_id_state_end;
     201
     202        slist1 = NULL;
     203        slist1 = curl_slist_append(slist1, "Content-Type: application/x-www-form-urlencoded");
     204
     205        curl = curl_easy_init();
     206
     207        char *client_id = curl_easy_escape(curl, client_info->client_id, strnlen(client_info->client_id, sizeof(client_info->client_id)));
     208        char *esc_scope = curl_easy_escape(curl, scope, strlen(scope));
     209
     210        len = sizeof("client_id=") + strlen(client_id) + sizeof("scope=") + strlen(esc_scope);
     211        postdata = malloc(len);
     212        snprintf(postdata, len, "client_id=%s&scope=%s", client_id, esc_scope);
     213
     214        curl_free(client_id);
     215        curl_free(esc_scope);
     216
     217        curl_easy_setopt(curl, CURLOPT_URL, "https://accounts.google.com/o/oauth2/device/code");
     218        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postdata);
     219        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)strnlen(postdata, len));
     220        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist1);
     221        curl_setopt_common(curl);
     222
     223        curl_easy_setopt(curl, CURLOPT_WRITEDATA, gd);
     224        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
     225
     226        ret = curl_easy_perform(curl);
     227
     228        free(postdata);
     229
     230        curl_easy_cleanup(curl);
     231        curl = NULL;
     232        curl_slist_free_all(slist1);
     233        slist1 = NULL;
     234
     235        return (int)ret;
     236}
     237
     238void get_access_token_state_start(google_drive_t *gd, struct jsonsl_state_st *state, const char *buf)
     239{
     240        switch (gd->state) {
     241        case psRoot:
     242                if (state->level != 2) {
     243                        break;
     244                }
     245                else if (strcmp(buf, "access_token") == 0) {
     246                        gd->state = psAccessToken;
     247                }
     248                else if (strcmp(buf, "expires_in") == 0) {
     249                        gd->state = psExpiresIn;
     250                }
     251                else if (strcmp(buf, "refresh_token") == 0) {
     252                        gd->state = psRefreshToken;
     253                }
     254                else if (strcmp(buf, "scope") == 0) {
     255                        gd->state = psScope;
     256                }
     257                else if (strcmp(buf, "token_type") == 0) {
     258                        gd->state = psTokenType;
     259                }
     260                else if (strcmp(buf, "error") == 0) {
     261                        gd->state = psError;
     262                }
     263                else if (strcmp(buf, "error_description") == 0) {
     264                        gd->state = psErrorDescription;
     265                }
     266                break;
     267        case psAccessToken:
     268                if (state->type == JSONSL_T_STRING) {
     269                        strlcpy(gd->credential.access_token, buf, sizeof(gd->credential.access_token));
     270                        gd->state = psRoot;
     271                }
     272                break;
     273        case psExpiresIn:
     274                if (state->type == JSONSL_T_SPECIAL) {
     275                        gd->credential.expires_in = atoi(buf);
     276                        gd->state = psRoot;
     277                }
     278                break;
     279        case psRefreshToken:
     280                if (state->type == JSONSL_T_STRING) {
     281                        strlcpy(gd->credential.refresh_token, buf, sizeof(gd->credential.refresh_token));
     282                        gd->state = psRoot;
     283                }
     284                break;
     285        case psScope:
     286                if (state->type == JSONSL_T_STRING) {
     287                        strlcpy(gd->credential.scope, buf, sizeof(gd->credential.scope));
     288                        gd->state = psRoot;
     289                }
     290                break;
     291        case psTokenType:
     292                if (state->type == JSONSL_T_STRING) {
     293                        strlcpy(gd->credential.token_type, buf, sizeof(gd->credential.token_type));
     294                        gd->state = psRoot;
     295                }
     296                break;
     297        case psError:
     298                if (state->type == JSONSL_T_STRING) {
     299                        strlcpy(gd->error.error, buf, sizeof(gd->error.error));
     300                        gd->state = psRoot;
     301                }
     302                break;
     303        case psErrorDescription:
     304                if (state->type == JSONSL_T_STRING) {
     305                        strlcpy(gd->error.error_description, buf, sizeof(gd->error.error_description));
     306                        gd->state = psRoot;
     307                }
     308                break;
     309        }
     310}
     311
     312void get_access_token_state_end(google_drive_t *gd, struct jsonsl_state_st *state, const char *buf)
     313{
     314}
     315
     316int get_access_token(google_drive_t *gd)
     317{
     318        client_info_t *client_info = &gd->client_info;
     319        credential_t *credential = &gd->credential;
     320        CURLcode ret;
     321        CURL *curl;
     322        struct curl_slist *slist1;
     323        size_t len;
     324        char *postdata;
     325        jsonsl_t jsn = gd->jsn;
     326
     327        gd->jsn_buf_pos = -1;
     328
     329        jsonsl_reset(jsn);
     330        gd->start = get_access_token_state_start;
     331        gd->end = get_access_token_state_end;
     332
     333        slist1 = NULL;
     334        slist1 = curl_slist_append(slist1, "Content-Type: application/x-www-form-urlencoded");
     335
     336        curl = curl_easy_init();
     337
     338        char *client_id = curl_easy_escape(curl, client_info->client_id, strnlen(client_info->client_id, sizeof(client_info->client_id)));
     339        char *client_secret = curl_easy_escape(curl, client_info->client_secret, strnlen(client_info->client_secret, sizeof(client_info->client_secret)));
     340        char *grant_type = curl_easy_escape(curl, GRANT_TYPE_DEVICE, strnlen(GRANT_TYPE_DEVICE, sizeof(GRANT_TYPE_DEVICE)));
     341
     342        len = sizeof("client_id=") + strlen(client_id) + sizeof("client_secret=") + strlen(client_secret)
     343                + sizeof("code=") + strlen(credential->device_code) + sizeof("grant_type=") + strlen(grant_type);
     344        postdata = malloc(len);
     345        snprintf(postdata, len, "client_id=%s&client_secret=%s&code=%s&grant_type=%s",
     346                client_id, client_secret, credential->device_code, grant_type);
     347
     348        curl_free(client_id);
     349        curl_free(client_secret);
     350        curl_free(grant_type);
     351
     352        curl_easy_setopt(curl, CURLOPT_URL, "https://www.googleapis.com/oauth2/v4/token");
     353        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postdata);
     354        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)strnlen(postdata, len));
     355        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist1);
     356        curl_setopt_common(curl);
     357
     358        curl_easy_setopt(curl, CURLOPT_WRITEDATA, gd);
     359        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
     360
     361        ret = curl_easy_perform(curl);
     362
     363        free(postdata);
     364
     365        curl_easy_cleanup(curl);
     366        curl = NULL;
     367        curl_slist_free_all(slist1);
     368        slist1 = NULL;
     369
     370        return (int)ret;
     371}
     372
     373void update_access_token_state_start(google_drive_t *gd, struct jsonsl_state_st *state, const char *buf)
     374{
     375        switch (gd->state) {
     376        case psRoot:
     377                if (state->level != 2) {
     378                        break;
     379                }
     380                else if (strcmp(buf, "access_token") == 0) {
     381                        gd->state = psAccessToken;
     382                }
     383                else if (strcmp(buf, "expires_in") == 0) {
     384                        gd->state = psExpiresIn;
     385                }
     386                else if (strcmp(buf, "scope") == 0) {
     387                        gd->state = psScope;
     388                }
     389                else if (strcmp(buf, "token_type") == 0) {
     390                        gd->state = psTokenType;
     391                }
     392                else if (strcmp(buf, "error") == 0) {
     393                        gd->state = psError;
     394                }
     395                else if (strcmp(buf, "error_description") == 0) {
     396                        gd->state = psErrorDescription;
     397                }
     398                break;
     399        case psAccessToken:
     400                if (state->type == JSONSL_T_STRING) {
     401                        strlcpy(gd->credential.access_token, buf, sizeof(gd->credential.access_token));
     402                        gd->state = psRoot;
     403                }
     404                break;
     405        case psExpiresIn:
     406                if (state->type == JSONSL_T_SPECIAL) {
     407                        gd->credential.expires_in = atoi(buf);
     408                        gd->state = psRoot;
     409                }
     410                break;
     411        case psScope:
     412                if (state->type == JSONSL_T_STRING) {
     413                        strlcpy(gd->credential.scope, buf, sizeof(gd->credential.scope));
     414                        gd->state = psRoot;
     415                }
     416                break;
     417        case psTokenType:
     418                if (state->type == JSONSL_T_STRING) {
     419                        strlcpy(gd->credential.token_type, buf, sizeof(gd->credential.token_type));
     420                        gd->state = psRoot;
     421                }
     422                break;
     423        case psError:
     424                if (state->type == JSONSL_T_STRING) {
     425                        strlcpy(gd->error.error, buf, sizeof(gd->error.error));
     426                        gd->state = psRoot;
     427                }
     428                break;
     429        case psErrorDescription:
     430                if (state->type == JSONSL_T_STRING) {
     431                        strlcpy(gd->error.error_description, buf, sizeof(gd->error.error_description));
     432                        gd->state = psRoot;
     433                }
     434                break;
     435        }
     436}
     437
     438void update_access_token_state_end(google_drive_t *gd, struct jsonsl_state_st *state, const char *buf)
     439{
     440}
     441
     442int update_access_token(google_drive_t *gd)
     443{
     444        client_info_t *client_info = &gd->client_info;
     445        credential_t *credential = &gd->credential;
     446        CURLcode ret;
     447        CURL *curl;
     448        struct curl_slist *slist1;
     449        size_t len;
     450        char *postdata;
     451        jsonsl_t jsn = gd->jsn;
     452
     453        gd->jsn_buf_pos = -1;
     454
     455        jsonsl_reset(jsn);
     456        gd->start = update_access_token_state_start;
     457        gd->end = update_access_token_state_end;
     458
     459        slist1 = NULL;
     460        slist1 = curl_slist_append(slist1, "Content-Type: application/x-www-form-urlencoded");
     461
     462        curl = curl_easy_init();
     463
     464        char *client_id = curl_easy_escape(curl, client_info->client_id, strnlen(client_info->client_id, sizeof(client_info->client_id)));
     465        char *client_secret = curl_easy_escape(curl, client_info->client_secret, strnlen(client_info->client_secret, sizeof(client_info->client_secret)));
     466
     467        len = sizeof("client_id=") + strlen(client_id) + sizeof("client_secret=") + strlen(client_secret)
     468                + sizeof("refresh_token=") + strlen(credential->refresh_token);
     469        postdata = malloc(len);
     470        snprintf(postdata, len, "client_id=%s&client_secret=%s&code=%s&grant_type=refresh_token",
     471                client_id, client_secret, credential->refresh_token);
     472
     473        curl_free(client_id);
     474        curl_free(client_secret);
     475
     476        curl_easy_setopt(curl, CURLOPT_URL, "https://www.googleapis.com/oauth2/v4/token");
     477        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postdata);
     478        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)strnlen(postdata, len));
     479        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist1);
     480        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
     481        curl_setopt_common(curl);
     482
     483        curl_easy_setopt(curl, CURLOPT_WRITEDATA, gd);
     484        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
     485
     486        ret = curl_easy_perform(curl);
     487
     488        free(postdata);
     489
     490        curl_easy_cleanup(curl);
     491        curl = NULL;
     492        curl_slist_free_all(slist1);
     493        slist1 = NULL;
     494
     495        return (int)ret;
     496}
     497
     498void revoke_device_state_start(google_drive_t *gd, struct jsonsl_state_st *state, const char *buf)
     499{
     500}
     501
     502void revoke_device_state_end(google_drive_t *gd, struct jsonsl_state_st *state, const char *buf)
     503{
     504}
     505
     506int revoke_device(google_drive_t *gd)
     507{
     508        client_info_t *client_info = &gd->client_info;
     509        credential_t *credential = &gd->credential;
     510        CURLcode ret;
     511        CURL *curl;
     512        size_t len;
     513        struct curl_slist *slist1;
     514        char *postdata;
     515        jsonsl_t jsn = gd->jsn;
     516
     517        gd->jsn_buf_pos = -1;
     518
     519        jsonsl_reset(jsn);
     520        gd->start = revoke_device_state_start;
     521        gd->end = revoke_device_state_end;
     522
     523        slist1 = NULL;
     524        slist1 = curl_slist_append(slist1, "Content-Type: application/x-www-form-urlencoded");
     525
     526        curl = curl_easy_init();
     527
     528        len = sizeof("token=") + strlen(credential->access_token);
     529        postdata = malloc(len);
     530        snprintf(postdata, len, "token=%s", credential->access_token);
     531
     532        curl_easy_setopt(curl, CURLOPT_URL, "https://accounts.google.com/o/oauth2/revoke");
     533        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postdata);
     534        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)strnlen(postdata, len));
     535        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist1);
     536        curl_setopt_common(curl);
     537
     538        curl_easy_setopt(curl, CURLOPT_WRITEDATA, gd);
     539        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
     540
     541        ret = curl_easy_perform(curl);
     542
     543        free(postdata);
     544
     545        curl_easy_cleanup(curl);
     546        curl = NULL;
     547        curl_slist_free_all(slist1);
     548        slist1 = NULL;
     549
     550        return (int)ret;
     551}
     552
     553void upload_file_state_start(google_drive_t *gd, struct jsonsl_state_st *state, const char *buf)
     554{
     555        switch (gd->state) {
     556        case psRoot:
     557                if (state->level != 2) {
     558                        break;
     559                }
     560                else if (strcmp(buf, "kind") == 0) {
     561                        gd->state = psKind;
     562                }
     563                else if (strcmp(buf, "id") == 0) {
     564                        gd->state = psId;
     565                }
     566                else if (strcmp(buf, "name") == 0) {
     567                        gd->state = psName;
     568                }
     569                else if (strcmp(buf, "mimeType") == 0) {
     570                        gd->state = psMimeType;
     571                }
     572                else if (strcmp(buf, "error") == 0) {
     573                        gd->state = psError;
     574                }
     575                else if (strcmp(buf, "error_description") == 0) {
     576                        gd->state = psErrorDescription;
     577                }
     578                break;
     579        case psKind:
     580                if (state->type == JSONSL_T_STRING) {
     581                        strlcpy(gd->file.kind, buf, sizeof(gd->file.kind));
     582                        gd->state = psRoot;
     583                }
     584                break;
     585        case psId:
     586                if (state->type == JSONSL_T_STRING) {
     587                        strlcpy(gd->file.id, buf, sizeof(gd->file.id));
     588                        gd->state = psRoot;
     589                }
     590                break;
     591        case psName:
     592                if (state->type == JSONSL_T_STRING) {
     593                        strlcpy(gd->file.name, buf, sizeof(gd->file.name));
     594                        gd->state = psRoot;
     595                }
     596                break;
     597        case psMimeType:
     598                if (state->type == JSONSL_T_STRING) {
     599                        strlcpy(gd->file.mimeType, buf, sizeof(gd->file.mimeType));
     600                        gd->state = psRoot;
     601                }
     602                break;
     603        case psError:
     604                if (state->type == JSONSL_T_STRING) {
     605                        strlcpy(gd->error.error, buf, sizeof(gd->error.error));
     606                        gd->state = psRoot;
     607                }
     608                break;
     609        case psErrorDescription:
     610                if (state->type == JSONSL_T_STRING) {
     611                        strlcpy(gd->error.error_description, buf, sizeof(gd->error.error_description));
     612                        gd->state = psRoot;
     613                }
     614                break;
     615        }
     616}
     617
     618void upload_file_state_end(google_drive_t *gd, struct jsonsl_state_st *state, const char *buf)
     619{
     620}
     621
     622size_t read_callback(char *buffer, size_t size, size_t nitems, void *arg)
     623{
     624        FIL *file = (FIL *)arg;
     625        UINT ret = 0;
     626        FRESULT res;
     627
     628        res = f_read(file, buffer, size * nitems, &ret);
     629        if (res != FR_OK)
     630                return 0;
     631
     632        int rest = ret;
    66633        int len;
    67634
     
    76643                response[len] = '\0';
    77644
    78                 ntstdio_printf(&ntstdio, response);
    79 
    80                 dly_tsk(100 * 1000);
     645                printf(response);
     646
     647                dly_tsk(100);
    81648
    82649                rest -= len;
     
    84651        }
    85652
    86         return size * nmemb;
    87 }
    88 
    89 size_t read_data(char *buffer, size_t size, size_t nitems, void *instream)
    90 {
    91         FIL *file = (FIL *)instream;
    92         UINT ret = 0;
    93         FRESULT res;
    94 
    95         res = f_read(file, buffer, size * nitems, &ret);
    96         if (res != FR_OK)
    97                 return 0;
    98 
    99         int rest = ret;
    100         int len;
    101 
    102         while (rest > 0) {
    103                 len = rest;
    104                 if (len > (sizeof(response) - 1)) {
    105                         len = sizeof(response) - 1;
    106                 }
    107 
    108                 memcpy(response, buffer, len);
    109 
    110                 response[len] = '\0';
    111 
    112                 ntstdio_printf(&ntstdio, response);
    113 
    114                 dly_tsk(100);
    115 
    116                 rest -= len;
    117                 buffer = (char *)buffer + len;
    118         }
    119 
    120653        return ret;
    121654}
    122655
    123 char errbuf[CURL_ERROR_SIZE];
     656int seek_callback(void *arg, curl_off_t offset, int origin)
     657{
     658        FIL *file = (FIL *)arg;
     659        BYTE mode;
     660        FRESULT ret;
     661
     662        switch (origin) {
     663        case SEEK_SET:
     664                mode = F_SEEK_SET;
     665                break;
     666        case SEEK_CUR:
     667                mode = F_SEEK_CUR;
     668                break;
     669        case SEEK_END:
     670                mode = F_SEEK_END;
     671                break;
     672        default:
     673                return CURL_SEEKFUNC_FAIL;
     674        }
     675
     676        ret = f_seek(file, offset, mode);
     677        if (ret != F_OK)
     678                return CURL_SEEKFUNC_FAIL;
     679
     680        return CURL_SEEKFUNC_OK;
     681}
     682
     683int upload_file(google_drive_t *gd, const char *filename, const char *localfilepath)
     684{
     685        CURLcode ret;
     686        CURL *curl;
     687        curl_mime *mime;
     688        curl_mimepart *part;
     689        struct curl_slist *slist1;
     690        size_t len;
     691        char *postdata, *authorization;
     692        static const char buf[] = "Expect:";
     693        jsonsl_t jsn = gd->jsn;
     694        FIL file;
     695        FRESULT fret;
     696
     697        gd->jsn_buf_pos = -1;
     698
     699        jsonsl_reset(jsn);
     700        gd->start = upload_file_state_start;
     701        gd->end = upload_file_state_end;
     702
     703        fret = f_open(&file, localfilepath, FA_READ);
     704        if (fret != FR_OK) {
     705                printf("log file open error %d\n", fret);
     706                return -1;
     707        }
     708
     709        len = sizeof("{\"name\":\"\"}") + strlen(filename);
     710        postdata = malloc(len);
     711        snprintf(postdata, len, "{\"name\":\"%s\"}", filename);
     712
     713        curl = curl_easy_init();
     714
     715        mime = curl_mime_init(curl);
     716        part = curl_mime_addpart(mime);
     717        curl_mime_name(part, "metadata");
     718        curl_mime_type(part, "application/json;charset=utf-8");
     719        curl_mime_data(part, postdata, CURL_ZERO_TERMINATED);
     720        free(postdata);
     721
     722        part = curl_mime_addpart(mime);
     723        curl_mime_name(part, "file");
     724        curl_mime_type(part, "application/json");
     725        curl_mime_data_cb(part, file.fsize, read_callback, seek_callback, NULL, &file);
     726
     727        len = sizeof("Authorization: Bearer ") + strnlen(gd->credential.access_token, sizeof(gd->credential.access_token));
     728        authorization = malloc(len);
     729        snprintf(authorization, len, "Authorization: Bearer %s", gd->credential.access_token);
     730        slist1 = NULL;
     731        slist1 = curl_slist_append(slist1, authorization);
     732        free(authorization);
     733
     734        slist1 = curl_slist_append(slist1, buf);
     735
     736        curl_easy_setopt(curl, CURLOPT_URL, "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart");
     737        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
     738        curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
     739        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist1);
     740        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
     741        curl_setopt_common(curl);
     742
     743        curl_easy_setopt(curl, CURLOPT_WRITEDATA, gd);
     744        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
     745
     746        ret = curl_easy_perform(curl);
     747
     748        curl_easy_cleanup(curl);
     749        curl = NULL;
     750        curl_mime_free(mime);
     751        mime = NULL;
     752        curl_slist_free_all(slist1);
     753        slist1 = NULL;
     754
     755        f_close(&file);
     756
     757        return (int)ret;
     758}
     759
     760int google_drive_error_callback(jsonsl_t jsn, jsonsl_error_t err,
     761        struct jsonsl_state_st *state, char *errat)
     762{
     763        return 0;
     764}
     765
     766void google_drive_state_callback(jsonsl_t jsn, jsonsl_action_t action,
     767        struct jsonsl_state_st *state, const char *buf)
     768{
     769        google_drive_t *gd = (google_drive_t *)jsn->data;
     770
     771        switch (action) {
     772        case JSONSL_ACTION_PUSH:
     773                switch (state->type) {
     774                case JSONSL_T_SPECIAL:
     775                        gd->jsn_buf[0] = *buf;
     776                        gd->jsn_buf_pos = 1;
     777                        break;
     778                case JSONSL_T_STRING:
     779                case JSONSL_T_HKEY:
     780                        gd->jsn_buf_pos = 0;
     781                        break;
     782                default:
     783                        gd->jsn_buf_pos = -1;
     784                }
     785                break;
     786        case JSONSL_ACTION_POP:
     787                switch (state->type) {
     788                case JSONSL_T_SPECIAL:
     789                case JSONSL_T_STRING:
     790                case JSONSL_T_HKEY:
     791                        gd->jsn_buf_pos--;
     792                        if (gd->jsn_buf_pos < sizeof(gd->jsn_buf)) {
     793                                gd->jsn_buf[gd->jsn_buf_pos] = '\0';
     794                        }
     795                        gd->start(gd, state, gd->jsn_buf);
     796                        break;
     797                default:
     798                        gd->jsn_buf[0] = '\0';
     799                        break;
     800                }
     801                gd->jsn_buf_pos = -1;
     802                break;
     803        default:
     804                gd->jsn_buf_pos = -1;
     805                break;
     806        }
     807}
    124808
    125809static void get_logfname(char *fname)
     
    185869        ret = f_open(&file, fname, FA_CREATE_ALWAYS | FA_WRITE);
    186870        if (ret != FR_OK) {
    187                 ntstdio_printf(&ntstdio, "not open a upload file %d\n", ret);
     871                printf("not open a upload file %d\n", ret);
    188872                return ret;
    189873        }
     
    232916        f_putc('}', &file);
    233917
    234 file_close:
    235918        f_close(&file);
    236919
     
    238921}
    239922
    240 void client_task(intptr_t exinf)
    241 {
    242         CURL *curl;
     923void curl_setopt_common(CURL *curl)
     924{
    243925        CURLcode res;
    244         int error = 0;
    245         //const char *data = "{\"value\":\"data post\"}";
    246         struct curl_slist *list = NULL;
    247         FIL file;
    248         FRESULT ret;
    249         char fname[] = {"1:/log/20160101000000.log"};
    250 
    251         get_logfname(fname);
    252 
    253         ret = write_log(fname);
    254         if (ret != FR_OK) {
    255                 ntstdio_printf(&ntstdio, "log file write error %d\n", ret);
    256                 return;
    257         }
    258 
    259         ret = f_open(&file, fname, FA_READ);
    260         if (ret != FR_OK) {
    261                 ntstdio_printf(&ntstdio, "log file open error %d\n", ret);
    262                 return;
    263         }
    264 
    265         ntstdio_printf(&ntstdio, "cURL start\n");
    266 
    267         curl = curl_easy_init();
    268         if (curl == NULL) {
    269                 ntstdio_printf(&ntstdio, "curl_easy_init() failed\n");
    270                 goto file_close;
    271         }
    272926
    273927        /* ask libcurl to show us the verbose output */
    274         curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
    275 
    276         res = curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/");
     928        res = curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
    277929        if (res != CURLE_OK)
    278                 ntstdio_printf(&ntstdio, "CURLOPT_URL failed: %s\n",
     930                printf("CURLOPT_VERBOSE failed: %s\n",
    279931                        curl_easy_strerror(res));
    280932
     
    283935
    284936        /* provide a buffer to store errors in */
    285         curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
     937        res = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
     938        if (res != CURLE_OK)
     939                printf("CURLOPT_ERRORBUFFER failed: %s\n",
     940                        curl_easy_strerror(res));
    286941
    287942#ifdef SKIP_PEER_VERIFICATION
     
    298953        res = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
    299954        if (res != CURLE_OK)
    300                 ntstdio_printf(&ntstdio, "CURLOPT_SSL_VERIFYPEER failed: %s\n",
     955                printf("CURLOPT_SSL_VERIFYPEER failed: %s\n",
    301956                        curl_easy_strerror(res));
    302957#else
    303958        res = curl_easy_setopt(curl, CURLOPT_CAINFO, "0:/certs/ca-cert.pem");
    304959        if (res != CURLE_OK)
    305                 ntstdio_printf(&ntstdio, "CURLOPT_CAINFO failed: %s\n",
     960                printf("CURLOPT_CAINFO failed: %s\n",
    306961                        curl_easy_strerror(res));
    307962
    308963        res = curl_easy_setopt(curl, CURLOPT_SSLCERT, "0:/certs/client-cert.pem");
    309964        if (res != CURLE_OK)
    310                 ntstdio_printf(&ntstdio, "CURLOPT_SSLCERT failed: %s\n",
     965                printf("CURLOPT_SSLCERT failed: %s\n",
    311966                        curl_easy_strerror(res));
    312967
    313968        res = curl_easy_setopt(curl, CURLOPT_SSLKEY, "0:/certs/client-key.pem");
    314969        if (res != CURLE_OK)
    315                 ntstdio_printf(&ntstdio, "CURLOPT_SSLKEY failed: %s\n",
     970                printf("CURLOPT_SSLKEY failed: %s\n",
    316971                        curl_easy_strerror(res));
    317972#endif
     
    326981        res = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
    327982        if (res != CURLE_OK)
    328                 ntstdio_printf(&ntstdio, "CURLOPT_SSL_VERIFYHOST failed: %s\n",
     983                printf("CURLOPT_SSL_VERIFYHOST failed: %s\n",
    329984                        curl_easy_strerror(res));
    330985#endif
     
    332987        /*res = curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy.example.com:8080");
    333988        if (res != CURLE_OK)
    334                 ntstdio_printf(&ntstdio, "CURLOPT_PROXY failed: %s\n",
     989                printf("CURLOPT_PROXY failed: %s\n",
    335990                        curl_easy_strerror(res));*/
    336991
    337         curl_easy_setopt(curl, CURLOPT_POST, 1);
    338 
    339         /* size of the POST data */
    340         //curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(data));
    341         curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, file.fsize);
    342 
    343         /* pass in a pointer to the data - libcurl will not copy */
    344         //curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
    345 
    346         list = curl_slist_append(list, "Content-Type: application/json");
    347 
    348         curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
    349 
    350         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&error);
    351 
    352         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
    353 
    354         /* now specify which file to upload */
    355         curl_easy_setopt(curl, CURLOPT_READDATA, &file);
    356 
    357         /* we want to use our own read function */
    358         curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_data);
    359 
    360         ntstdio_printf(&ntstdio, "cURL perform the request\n");
    361         tslp_tsk(100 * 1000);
    362 
    363         /* Perform the request, res will get the return code */
    364         res = curl_easy_perform(curl);
    365         /* Check for errors */
    366         if (res != CURLE_OK) {
    367                 ntstdio_printf(&ntstdio, "curl_easy_perform() failed: %s\n",
     992        res = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
     993        if (res != CURLE_OK)
     994                printf("CURLOPT_NOPROGRESS failed: %s\n",
    368995                        curl_easy_strerror(res));
    369                 ntstdio_printf(&ntstdio, errbuf);
    370         }
    371 
    372         /* always cleanup */
    373         curl_easy_cleanup(curl);
    374 
    375         ntstdio_printf(&ntstdio, "cURL end\n");
    376 
    377 file_close:
    378         f_close(&file);
    379 }
    380 
    381 void client_fin(void)
    382 {
     996
     997        res = curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L);
     998        if (res != CURLE_OK)
     999                printf("CURLOPT_MAXREDIRS failed: %s\n",
     1000                        curl_easy_strerror(res));
     1001
     1002        res = curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
     1003        if (res != CURLE_OK)
     1004                printf("CURLOPT_TCP_KEEPALIVE failed: %s\n",
     1005                        curl_easy_strerror(res));
     1006}
     1007
     1008void client_set_client_id(const char *client_id)
     1009{
     1010        google_drive_t *gd = &google_drive;
     1011
     1012        strlcpy(gd->client_info.client_id, client_id, sizeof(gd->client_info.client_id));
     1013}
     1014
     1015void client_set_client_secret(const char *client_secret)
     1016{
     1017        google_drive_t *gd = &google_drive;
     1018
     1019        strlcpy(gd->client_info.client_secret, client_secret, sizeof(gd->client_info.client_secret));
     1020}
     1021
     1022int client_get_device_id(int argc, char **argv)
     1023{
     1024        google_drive_t *gd = &google_drive;
     1025        int ret;
     1026
     1027        ret = get_device_id(gd, SCOPE_DRIVE_FILE);
     1028        if (ret == 0) {
     1029                printf("Device was registered. Enter the code at the following URL\n");
     1030                printf("url:  %s\n", gd->credential.verification_url);
     1031                printf("code: %s\n", gd->credential.user_code);
     1032        }
     1033        else {
     1034                printf("Device register failed! %d\n", ret);
     1035        }
     1036
     1037        return ret;
     1038}
     1039
     1040int client_get_access_token(int argc, char **argv)
     1041{
     1042        google_drive_t *gd = &google_drive;
     1043        int ret;
     1044
     1045        ret = get_access_token(gd);
     1046        if (ret == 0) {
     1047                printf("Access token was give\n");
     1048                printf("Refresh token: %s\n", gd->credential.refresh_token);
     1049                printf("Access token: %s\n", gd->credential.access_token);
     1050        }
     1051        else {
     1052                printf("Access token gain failed. %d\n", ret);
     1053        }
     1054
     1055        return ret;
     1056}
     1057
     1058int client_update_access_token(int argc, char **argv)
     1059{
     1060        google_drive_t *gd = &google_drive;
     1061        int ret;
     1062
     1063        ret = update_access_token(gd);
     1064        if (ret == 0) {
     1065                printf("Access token was update\n");
     1066                printf("Access token: %s\n", gd->credential.access_token);
     1067        }
     1068        else {
     1069                printf("Access token update failed. %d\n", ret);
     1070        }
     1071
     1072        return ret;
     1073}
     1074
     1075int client_revoke(int argc, char **argv)
     1076{
     1077        google_drive_t *gd = &google_drive;
     1078        int ret;
     1079
     1080        ret = revoke_device(gd);
     1081        if (ret == 0) {
     1082                printf("Device was revoked.\n");
     1083        }
     1084        else {
     1085                printf("Device revoke failed. %d\n", ret);
     1086        }
     1087
     1088        return ret;
     1089}
     1090
     1091int client_upload_file(int argc, char **argv)
     1092{
     1093        google_drive_t *gd = &google_drive;
     1094        int ret;
     1095        FRESULT fret;
     1096        char fname[] = { "1:/log/20160101000000.log" };
     1097
     1098        get_logfname(fname);
     1099
     1100        fret = write_log(fname);
     1101        if (fret != FR_OK) {
     1102                printf("log file write error %d\n", fret);
     1103                return (int)fret;
     1104        }
     1105
     1106        ret = upload_file(gd, &fname[7], fname);
     1107        if (ret == 0) {
     1108                printf("%s was uploaded.\n", &fname[7]);
     1109        }
     1110        else {
     1111                printf("%s upload failed. %d\n", &fname[7], ret);
     1112        }
     1113
     1114        return ret;
     1115}
     1116
     1117void client_final(void)
     1118{
     1119        google_drive_t *gd = &google_drive;
     1120        jsonsl_t jsn = gd->jsn;
     1121
    3831122        curl_global_cleanup();
    384 }
     1123        jsonsl_destroy(jsn);
     1124}
Note: See TracChangeset for help on using the changeset viewer.