#include "lwip/sockets.h" #include "os_mem_api.h" #include "os_task_api.h" #include "httpd_socket_client.h" /** The receive buffer size */ #define HTTP_CLIENT_BUFF_SIZE 1024 /** client task prio */ #define HTTP_CLIENT_TASK_PRIO 6 typedef struct _http_client_t { iot_eth_config_t eth_cfg; int32_t client_conn_fd; os_task_h client_task_handle; client_conn_state state; int8_t client_recv_buff[HTTP_CLIENT_BUFF_SIZE]; http_client_recv_fn client_recv_func; } http_client_t; #define HTTP_CLIENT_SOCKET_ALLOC() (http_client_t *)os_mem_malloc \ (0, sizeof(http_client_t)) static http_client_t *g_http_client = NULL; static void httpd_socket_client_task(); /** * Initialize the client * * @return the return value of httpd_client_init */ int8_t httpd_client_init(iot_eth_config_t *cfg) { iot_cus_printf("http_client_init\n"); g_http_client = HTTP_CLIENT_SOCKET_ALLOC(); IOT_ASSERT(g_http_client); os_mem_set(g_http_client, 0, sizeof(http_client_t)); g_http_client->state = CLIENT_CONN_IDLE; g_http_client->eth_cfg = *cfg; g_http_client->client_task_handle = os_create_task(httpd_socket_client_task, NULL, HTTP_CLIENT_TASK_PRIO); if (g_http_client->client_task_handle == NULL) { g_http_client->client_conn_fd = -1; iot_cus_printf("[err]task create failed\n"); return -1; } iot_cus_printf("client_task_handle creat success\n"); return 0; } uint32_t httpd_client_get_state(void) { if (g_http_client == NULL) { iot_cus_printf("[err]can not find the connection\n"); return 0; } iot_cus_printf("httpd_client_get_state =%d\n", g_http_client->state); return (uint32_t)g_http_client->state; } static void httpd_client_enable_connect_state_rpt(void) { g_http_client->state |= SOCKET_CONN_RPT_STATUS; } void httpd_client_disable_connect_state_rpt(void) { g_http_client->state &= ~SOCKET_CONN_RPT_STATUS; } /** * set server addr * * @param server_ip: the ip of the server * @param server_port: the port of the server * @return the server addr valid */ int8_t httpd_client_set_server_addr(uint32_t server_ip, const uint16_t server_port) { if (server_ip == 0 ||server_port == 0) { return -1; } if (server_ip != g_http_client->eth_cfg.server_ip || server_port != g_http_client->eth_cfg.port) { if (g_http_client->state != CLIENT_CONN_IDLE) { httpd_client_close(); } g_http_client->eth_cfg.server_ip = server_ip; g_http_client->eth_cfg.port = server_port; } return 0; } /** * connect to server * * @param server_ip: the ip of the server * @param server_port: the port of the server 8081 * @return the return value of gs_client_connect */ static int32_t httpd_client_connect(uint32_t server_ip, const uint16_t server_port) { int32_t ret = 0; struct sockaddr_in ser_addr; iot_cus_printf("http_client_connect: start server_ip=%x " "server_port=%d\n", server_ip, server_port); if ((server_ip == 0) || (server_port == 0)) { ret = -128; goto out; } g_http_client->state = CLIENT_CONN_CONNING; ser_addr.sin_family= AF_INET; ser_addr.sin_port = htons(server_port); ser_addr.sin_addr.s_addr = server_ip; //creat socket if ((g_http_client->client_conn_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { ret = -129; goto out; } if (connect(g_http_client->client_conn_fd, (struct sockaddr*)&ser_addr, sizeof(struct sockaddr_in)) != ERR_OK){ ret = -130; goto out; } g_http_client->state = CLIENT_CONN_CONNECTED; httpd_client_enable_connect_state_rpt(); iot_cus_printf("[http]connect fd=%d success\n", g_http_client->client_conn_fd); out: if (ret < 0) { iot_cus_printf("[err]connect failed ret=%d client_conn_fd=%d\n", ret, g_http_client->client_conn_fd); g_http_client->state = CLIENT_CONN_IDLE; } return ret; } /** * Used to specify the function that should be called when a * connection receives data. * * @param recv callback function to call when data is received */ int8_t httpd_client_register_recv(http_client_recv_fn recv) { if (recv != NULL) { g_http_client->client_recv_func = recv; return ERR_OK; } return -1; } /** send data to tcp ,it should be called by app * * @param ptr Data to send * @param length Length of data to send * @return the return the send_bytes that have sent. */ int32_t httpd_client_send(const void* ptr, uint16_t length) { int32_t ret; if ((ptr == NULL) || (length == 0)) { iot_cus_printf("[err]param error, ptr=%p, length=%d\n",ptr, length); ret = -128; goto out; } else if (g_http_client->state == CLIENT_CONN_IDLE) { iot_cus_printf("[err]not connect server\n"); ret = -129; goto out; } else { ret = send(g_http_client->client_conn_fd, ptr, length, 0); iot_cus_printf("already send %d bytes\n", ret); } out: return ret; } /* close the connecting */ int32_t httpd_client_close() { int32_t ret = -1; if (g_http_client->client_conn_fd >= 0) { ret = lwip_close(g_http_client->client_conn_fd); } iot_cus_printf("httpd_client_close fd=%d ret=%d\n", g_http_client->client_conn_fd, ret); g_http_client->client_conn_fd = -1; g_http_client->state = CLIENT_CONN_IDLE; return ret; } /* the task processes the connection */ static void httpd_socket_client_task(void) { fd_set ser_fdset; int32_t max_fd = 1; struct timeval gs_time; int32_t ret = -1; iot_cus_printf("enter socket_client_task!\n"); IOT_ASSERT(g_http_client); while(1) { gs_time.tv_sec = 130; /* need large than heartbeat */ gs_time.tv_usec = 0; // check connect if (g_http_client->state == CLIENT_CONN_IDLE) { if (g_http_client->eth_cfg.server_ip == 0 || g_http_client->eth_cfg.port == 0) { os_delay(1000); continue; } ret = httpd_client_connect(g_http_client->eth_cfg.server_ip, g_http_client->eth_cfg.port); if (ret < 0) { httpd_client_close(); } } if (g_http_client->state != CLIENT_CONN_CONNECTED) { os_delay(1000); continue; } os_mem_set((void *)&ser_fdset, 0, sizeof(fd_set)); //add client fd FD_SET(g_http_client->client_conn_fd, &ser_fdset); if (max_fd < g_http_client->client_conn_fd) { max_fd = g_http_client->client_conn_fd; } ret = select(max_fd + 1, &ser_fdset, NULL, NULL, &gs_time); if (ret < 0) { iot_cus_printf("select failure\n"); continue; } else if (ret == 0) { iot_cus_printf("time out!\n"); httpd_client_close(); continue; } else { //deal with the message if (FD_ISSET(g_http_client->client_conn_fd, &ser_fdset)) { int32_t byte_num; os_mem_set(g_http_client->client_recv_buff, 0, HTTP_CLIENT_BUFF_SIZE); byte_num = recv(g_http_client->client_conn_fd, g_http_client->client_recv_buff, HTTP_CLIENT_BUFF_SIZE, 0); if (byte_num > 0) { iot_cus_printf("message form client:%s, len=%d\n", g_http_client->client_recv_buff, byte_num); if (g_http_client->client_recv_func != NULL) { g_http_client->client_recv_func( (int8_t *)&(g_http_client->client_recv_buff), byte_num); } else { httpd_client_send(g_http_client->client_recv_buff, byte_num); iot_cus_printf("need to register the recv func\n"); } } else { httpd_client_close(); iot_cus_printf("recv nothing!!!\n"); } } } } }