| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578 |
- /*
- * File : gagent_httpc.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2018, RT-Thread Development Team
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Change Logs:
- * Date Author Notes
- * 2018-01-03 flyingcys first version
- */
- #include "gagent_def.h"
- #include "gagent_cloud.h"
- #include "aes.h"
- #define MAX_HTTPC_URL_LEN 1024
- #define MAX_HTTPC_RECV_LEN 2048
- struct cloud_httpc
- {
- char *recv_buf;
- int recv_len;
- };
- static struct cloud_httpc httpc;
- typedef int (*WEBCLIENT_CUSTOM_RESPONSE_CB)(size_t total, size_t offset, char *from, size_t from_len);
- static int webclient_common(int method, const char *URI,
- const char * data, size_t data_sz,
- WEBCLIENT_CUSTOM_RESPONSE_CB webclient_custom_response_cb)
- {
- struct webclient_session *session = RT_NULL;
- char *header = RT_NULL, *header_ptr;
- size_t header_sz = 0;
- int rc = WEBCLIENT_OK;
- int length = 0;
- size_t total = 0, offset = 0;
-
- rt_uint8_t *buffer = RT_NULL;
- header = (char *)rt_malloc(WEBCLIENT_HEADER_BUFSZ);
- if(RT_NULL == header)
- {
- gagent_err("malloc failed!\n");
- rc = -WEBCLIENT_NOMEM;
- goto __exit;
- }
- rt_memset(header, 0, WEBCLIENT_HEADER_BUFSZ);
- header_ptr = header;
- header_ptr += rt_snprintf(header_ptr,
- WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
- "Content-Type: application/x-www-form-urlencoded;charset:UTF-8\r\n");
-
- if(data)
- {
- header_ptr += rt_snprintf(header_ptr,
- WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
- "Content-Length:%d\r\n", strlen(data));
- }
-
- header_sz = header_ptr - header;
- session = webclient_open_custom(URI, method, header, header_sz, data, data_sz);
- if(RT_NULL == session)
- {
- gagent_err("webclient_open_custom failed!\n");
- rc = -WEBCLIENT_OK;
- goto __exit;
- }
- gagent_dbg("response:%d\n",session->response);
- buffer = (rt_uint8_t *)rt_malloc(WEBCLIENT_RESPONSE_BUFSZ);
- if(RT_NULL == buffer)
- {
- gagent_err("malloc failed!\n");
- rc = -WEBCLIENT_NOMEM;
- goto __exit;
- }
- if(session->chunk_sz > 0)
- {
- gagent_dbg("chunk_sz:%d\n", session->chunk_sz);
- total = session->chunk_sz;
- }
- else if(session->content_length > 0)
- {
- gagent_dbg("content_length:%d content_length_remainder:%d\n", session->content_length, session->content_length_remainder);
- total = session->content_length;
- }
-
- while(total != offset)
- {
- memset(buffer, 0, WEBCLIENT_RESPONSE_BUFSZ);
- length = webclient_read(session, buffer, WEBCLIENT_RESPONSE_BUFSZ);
- if(length <= 0)
- {
- rc = length;
- break;
- }
-
- if(webclient_custom_response_cb)
- webclient_custom_response_cb(total, offset, (char *)buffer, (int)length);
- offset += length;
- }
- __exit:
- if(RT_NULL != buffer)
- {
- rt_free(buffer);
- buffer = RT_NULL;
- }
- if(RT_NULL != header)
- {
- rt_free(header);
- header = RT_NULL;
- }
- if(RT_NULL != session)
- {
- webclient_close(session);
- session = RT_NULL;
- }
- return rc;
- }
- int webclient_get(const char *URI, WEBCLIENT_CUSTOM_RESPONSE_CB webclient_custom_response_cb)
- {
- return webclient_common(WEBCLIENT_GET, URI, NULL, 0, webclient_custom_response_cb);
- }
- int webclient_post(const char *URI, const char * data, size_t data_sz,
- WEBCLIENT_CUSTOM_RESPONSE_CB webclient_custom_response_cb)
- {
- return webclient_common(WEBCLIENT_POST, URI, data, data_sz, webclient_custom_response_cb);
- }
- int gagent_cloud_httpc_cb(size_t total, size_t offset, char *from, size_t from_len)
- {
- extern cloud_st *cloud;
-
- gagent_dbg("total:%d offset:%d len:%d\n", total, offset, from_len);
- gagent_dbg("buf:%s\n", from);
-
- rt_memset(httpc.recv_buf, 0, MAX_HTTPC_RECV_LEN);
- rt_memcpy(httpc.recv_buf, from, from_len);
- httpc.recv_len = from_len;
- return RT_EOK;
- }
- int gagent_cloud_register(cloud_st *cloud)
- {
- int rc = RT_EOK;
- int content_len, aes_len, i;
- //
- char *content = RT_NULL;
- char *url = RT_NULL;
- char *ptr = RT_NULL;
-
- uint8_t aes_key[16];
- char *aes_buf = RT_NULL;
- aes_context *aes_ctx = RT_NULL;
- content = (char *)rt_malloc(256);
- if(RT_NULL == content)
- {
- gagent_err("malloc faield!\n");
- rc = -RT_ENOMEM;
- goto __exit;
- }
- aes_buf = (char *)rt_malloc(256);
- if(RT_NULL == aes_buf)
- {
- rc = -RT_ENOMEM;
- goto __exit;
- }
- //data
- rt_memset(content, 0, 256);
- rt_snprintf((char *)content, 256, "mac=%02x%02x%02x%02x%02x%02x&passcode=%s&type=%s", \
- cloud->con->mac[0], cloud->con->mac[1], cloud->con->mac[2], cloud->con->mac[3], cloud->con->mac[4], cloud->con->mac[5], \
- cloud->con->passcode, "normal");
- content_len = strlen(content);
- rt_memset(aes_key, 0, sizeof(aes_key));
- gagent_strtohex((char *)aes_key, cloud->con->pk_secret, strlen(cloud->con->pk_secret) > 32 ? 32 : strlen(cloud->con->pk_secret));
- gagent_dbg("content:%s, pk_secret:%s\n", content, cloud->con->pk_secret);
- aes_ctx = (aes_context *)rt_malloc(sizeof(aes_context));
- if(RT_NULL == aes_ctx)
- {
- rc = -RT_ENOMEM;
- goto __exit;
- }
- rt_memset(aes_ctx, 0, sizeof(aes_context));
- aes_setkey_enc(aes_ctx, aes_key, 128);
- //
- rt_memset(aes_buf, 0, 256);
-
- content_len = strlen(content);
- if(content_len % 16)
- content_len = gagent_add_pkcs(content, content_len);
-
- aes_len = 0;
- for(i = 0; i < content_len; i += 16)
- {
- aes_crypt_ecb(aes_ctx, AES_ENCRYPT, (uint8_t *)content + i, (uint8_t *)aes_buf + i);
- aes_len += 16;
- }
- ptr = content;
- rt_memset(ptr, 0, 256);
-
- strcpy(ptr, "data=");
- ptr += strlen("data=");
-
- if(aes_len > 0)
- {
- for(i = 0; i < aes_len; i ++)
- {
- ptr += rt_snprintf(ptr, 256 - (ptr - content), "%02x", aes_buf[i]);
- }
- }
- gagent_dbg("content:%s\n", content);
-
- url = (char *)rt_malloc(MAX_HTTPC_URL_LEN);
- if(RT_NULL == url)
- {
- rc = -RT_ENOMEM;
- goto __exit;
- }
- ptr = url;
- memset(ptr, 0, MAX_HTTPC_URL_LEN);
-
- //url
- ptr += rt_snprintf(ptr, MAX_HTTPC_URL_LEN - (ptr - url), "http://%s:%s", G_SERVICE_DOMAIN, G_SERVICE_PORT);
- ptr += rt_snprintf(ptr, MAX_HTTPC_URL_LEN - (ptr - url), "/dev/%s/device", cloud->con->pk);
-
- gagent_dbg("url:%s\n", url);
- httpc.recv_buf = RT_NULL;
- httpc.recv_buf = (char *)rt_malloc(MAX_HTTPC_RECV_LEN);
- if(RT_NULL == httpc.recv_buf)
- {
- rc = -RT_ENOMEM;
- goto __exit;
- }
-
- rc = webclient_post((const char *)url, (const char *)content, strlen(content), gagent_cloud_httpc_cb);
- if(rc != RT_EOK)
- {
- gagent_err("weblient_post failed!\n");
- goto __exit;
- }
- //
- rt_memset(content, 0, 256);
- aes_len = gagent_strtohex((char *)content, (char *)httpc.recv_buf, httpc.recv_len);
- rt_memset(aes_ctx, 0, sizeof(aes_context));
- aes_setkey_dec(aes_ctx, aes_key, 128);
-
- rt_memset(aes_buf, 0, 256);
- for(i = 0; i < aes_len; i += 16)
- aes_crypt_ecb(aes_ctx, AES_DECRYPT, (uint8_t *)content + i, (uint8_t *)aes_buf + i);
- gagent_dbg("%s\n", aes_buf);
- if(strstr(aes_buf, "did=") != NULL)
- rt_memcpy(cloud->con->did, aes_buf + strlen("did="), DID_LENGTH);
-
- __exit:
- if(RT_NULL != httpc.recv_buf)
- {
- rt_free(httpc.recv_buf);
- httpc.recv_buf = RT_NULL;
- }
-
- if(RT_NULL != url)
- {
- rt_free(url);
- url = RT_NULL;
- }
- if(RT_NULL != aes_ctx)
- {
- rt_free(aes_ctx);
- aes_ctx = RT_NULL;
- }
- if(RT_NULL != aes_buf)
- {
- rt_free(aes_buf);
- aes_buf = RT_NULL;
- }
-
- if(RT_NULL != content)
- {
- rt_free(content);
- content = RT_NULL;
- }
- return rc;
- }
- int gagent_cloud_provision(cloud_st *cloud)
- {
- int rc = RT_EOK;
- int content_len, aes_len, i;
- char *url = RT_NULL;
- char *content = RT_NULL;
- char *ptr = RT_NULL;
- char *ptr_tail = RT_NULL;
- char aes_key[16];
- char *aes_buf = RT_NULL;
- aes_context *aes_ctx = RT_NULL;
- content = (char *)rt_malloc(256);
- if(RT_NULL == content)
- {
- rc = -RT_ENOMEM;
- goto __exit;
- }
- aes_buf = (char *)rt_malloc(256);
- if(RT_NULL == aes_buf)
- {
- rc = -RT_ENOMEM;
- goto __exit;
- }
- //data
- rt_memset(content, 0, 256);
- strcpy(content, cloud->con->did);
- rt_memset(aes_key, 0, sizeof(aes_key));
- gagent_strtohex((char *)aes_key, cloud->con->pk_secret, strlen(cloud->con->pk_secret) > 32 ? 32 : strlen(cloud->con->pk_secret));
- gagent_dbg("content:%s, pk_secret:%s\n", content, cloud->con->pk_secret);
- aes_ctx = (aes_context *)rt_malloc(sizeof(aes_context));
- if(RT_NULL == aes_ctx)
- {
- rc = -RT_ENOMEM;
- goto __exit;
- }
- rt_memset(aes_ctx, 0, sizeof(aes_context));
- aes_setkey_enc(aes_ctx, (uint8_t *)aes_key, 128);
- //
- rt_memset(aes_buf, 0, 256);
- content_len = strlen(content);
- if(content_len % 16)
- content_len = gagent_add_pkcs(content, content_len);
- aes_len = 0;
- for(i = 0; i < content_len; i += 16)
- {
- aes_crypt_ecb(aes_ctx, AES_ENCRYPT, (uint8_t *)content + i, (uint8_t *)aes_buf + i);
- aes_len += 16;
- }
- ptr = content;
- if(aes_len > 0)
- {
- for(i = 0; i < aes_len; i ++)
- {
- ptr += rt_snprintf(ptr, 256 - (ptr - content), "%02x", aes_buf[i]);
- }
- }
- gagent_dbg("content:%s\n", content);
- url = (char *)rt_malloc(MAX_HTTPC_URL_LEN);
- if(RT_NULL == url)
- {
- rc = -RT_ENOMEM;
- return rc;
- }
- ptr = url;
- rt_memset(url, 0, MAX_HTTPC_URL_LEN);
- //url
- ptr += rt_snprintf(ptr, MAX_HTTPC_URL_LEN - (ptr - url), "http://%s:%s", G_SERVICE_DOMAIN, G_SERVICE_PORT);
- ptr += rt_snprintf(ptr, MAX_HTTPC_URL_LEN - (ptr - url), "/dev/%s/device?", cloud->con->pk);
- ptr += rt_snprintf(ptr, MAX_HTTPC_URL_LEN - (ptr - url), "did=%s", content);
- gagent_dbg("url:%s\n", url);
- //
- rt_memset(cloud->mqtt_server, 0, sizeof(cloud->mqtt_server));
- rt_memcpy(cloud->mqtt_server, G_M2M_DOMAIN, sizeof(G_M2M_DOMAIN));
- //
- cloud->mqtt_port = 0;
- cloud->mqtt_port = atoi(G_M2M_PORT);
- httpc.recv_buf = RT_NULL;
- httpc.recv_buf = (char *)rt_malloc(MAX_HTTPC_RECV_LEN);
- if(RT_NULL == httpc.recv_buf)
- {
- rc = -RT_ENOMEM;
- goto __exit;
- }
- rc = webclient_get((const char *)url, gagent_cloud_httpc_cb);
- if(rc != RT_EOK)
- {
- rt_kprintf("weblient_post failed!\n");
- goto __exit;
- }
- rt_memset(content, 0, 256);
- aes_len = gagent_strtohex(content, httpc.recv_buf, httpc.recv_len);
- rt_memset(aes_ctx, 0, sizeof(aes_context));
- aes_setkey_dec(aes_ctx, (uint8_t *)aes_key, 128);
- rt_memset(aes_buf, 0, 256);
- for(i = 0; i < aes_len; i += 16)
- aes_crypt_ecb(aes_ctx, AES_DECRYPT, (uint8_t *)content + i, (uint8_t *)aes_buf + i);
- gagent_dbg("%s\n", aes_buf);
- //mqtt_server
- ptr = strstr(aes_buf, "host=");
- if(ptr > 0)
- {
- ptr += strlen("host=");
- ptr_tail = strchr(ptr, '&');
- if(ptr_tail > 0)
- {
- rt_memset(cloud->mqtt_server, 0, sizeof(cloud->mqtt_server));
- rt_memcpy(cloud->mqtt_server, ptr, (ptr_tail - ptr));
- }
- }
- //mqtt_port
- ptr = strstr(aes_buf, "port=");
- if(ptr > 0)
- {
- ptr += strlen("port=");
- ptr_tail = strchr(ptr, '&');
- if(ptr_tail > 0)
- {
- *ptr_tail = '\0';
- cloud->mqtt_port = 0;
- cloud->mqtt_port = atoi(ptr);
- }
- }
- gagent_dbg("mqtt_server:%s port:%d\n", cloud->mqtt_server, cloud->mqtt_port);
- __exit:
- if(RT_NULL != httpc.recv_buf)
- {
- rt_free(httpc.recv_buf);
- httpc.recv_buf = RT_NULL;
- }
- if(RT_NULL != url)
- {
- rt_free(url);
- url = RT_NULL;
- }
- if(RT_NULL != aes_ctx)
- {
- rt_free(aes_ctx);
- aes_ctx = RT_NULL;
- }
- if(RT_NULL != aes_buf)
- {
- rt_free(aes_buf);
- aes_buf = RT_NULL;
- }
- if(RT_NULL != content)
- {
- rt_free(content);
- content = RT_NULL;
- }
- return rc;
- }
- int gagent_cloud_check_ota(cloud_st *cloud)
- {
- int rc = RT_EOK;
- char *url = RT_NULL;
- char *content = RT_NULL;
- char *ptr = RT_NULL;
- content = (char *)rt_malloc(256);
- if(RT_NULL == content)
- {
- gagent_err("malloc faield!\n");
- rc = -RT_ENOMEM;
- goto __exit;
- }
- //data
- rt_memset(content, 0, 256);
- rt_snprintf((char *)content, 256, "passcode=%s&type=%d&hard_version=%s&soft_version=%s", \
- cloud->con->passcode, GAGENT_HARD_SOC, cloud->con->hard_version, cloud->con->soft_version);
- gagent_dbg("content:%s\n", content);
- url = (char *)rt_malloc(MAX_HTTPC_URL_LEN);
- if(RT_NULL == url)
- {
- rc = -RT_ENOMEM;
- return rc;
- }
- ptr = url;
- rt_memset(url, 0, MAX_HTTPC_URL_LEN);
- //url
- ptr += rt_snprintf(ptr, MAX_HTTPC_URL_LEN - (ptr - url), "http://%s:%s", G_SERVICE_DOMAIN, G_SERVICE_PORT);
- ptr += rt_snprintf(ptr, MAX_HTTPC_URL_LEN - (ptr - url), "/dev/ota/v4.1/update_and_check/%s", cloud->con->did);
- gagent_dbg("url:%s\n", url);
- httpc.recv_buf = RT_NULL;
- httpc.recv_buf = (char *)rt_malloc(MAX_HTTPC_RECV_LEN);
- if(RT_NULL != httpc.recv_buf)
- {
- rc = -RT_ENOMEM;
- goto __exit;
- }
- rc = webclient_post((const char *)url, (const char *)content, strlen(content), gagent_cloud_httpc_cb);
- if(rc != RT_EOK)
- {
- gagent_err("weblient_post failed!\n");
- goto __exit;
- }
- __exit:
- if(RT_NULL != httpc.recv_buf)
- rt_free(httpc.recv_buf);
- if(RT_NULL != url)
- rt_free(url);
- if(RT_NULL != content)
- rt_free(content);
- return rc;
- }
|