Files
kunlun/app/grapp/httpd/src/httpd_socket_clinet.c
2024-09-28 14:24:04 +08:00

283 lines
8.1 KiB
C

#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");
}
}
}
}
}