Files
ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.c
Michael Sauer 1b0501179d build: W600-SDK importiert, Firmware-Build und Hello am EVK
Docker-Build mit gcc-arm-none-eabi 4.9-2014q4 (statt Homebrew-Cask) verwendet,
Dockerfile/tools/docker.sh dafür aus Task 13 vorgezogen. cmake/sdk.cmake schont
gcc 4.9 (kennt -fcommon/-Wno-error=... nicht). Zwei zusätzliche SDK-Stubs
(EarlyInit, pre_gpio_config) in src/sys/sdk_stubs.c ergänzt, siehe sdk/PATCHES.md.
2026-09-11 12:52:26 +02:00

1686 lines
46 KiB
C

/**************************************************************************
* File Name : tls_netconn.c
* Author :
* Version :
* Date :
* Description :
*
* Copyright (c) 2014 Winner Microelectronics Co., Ltd.
* All rights reserved.
*
***************************************************************************/
#include "wm_config.h"
#if TLS_CONFIG_SOCKET_RAW
#include "tls_netconn.h"
#include "wm_debug.h"
#include "wm_regs.h"
#include "lwip/sys.h"
#include "lwip/tcp.h"
#include "lwip/udp.h"
#include "lwip/tcpip.h"
#include <string.h>
#include "wm_sockets.h"
struct tls_netconn *p_net_conn[TLS_MAX_NETCONN_NUM];
#if CONN_SEM_NOT_FREE
sys_sem_t conn_op_completed[TLS_MAX_NETCONN_NUM] = {NULL};
#endif
//static err_t net_tcp_sent_cb(void *arg, struct tcp_pcb *pcb, u16_t len);
static void net_tcp_err_cb(void *arg, err_t err);
static err_t net_tcp_poll_cb(void *arg, struct tcp_pcb *pcb);
static void net_free_socket(int socketno);
//static err_t net_do_writemore(struct tls_netconn *conn);
#define BUF_CIRC_CNT_TO_END(head,tail,size) \
({int end = (size) - (tail); \
int n = ((head) + end) & ((size)-1); \
n < end ? n : end;})
u32 current_src_ip = 0;
void tls_net_set_sourceip(u32 ipvalue)
{
current_src_ip = ipvalue;
}
u32 tls_net_get_sourceip(void)
{
return current_src_ip;
}
struct tls_netconn *get_server_conn(struct tls_netconn *conn)
{
struct tls_netconn *server_conn = NULL;
do{
server_conn = dl_list_first(&conn->list, struct tls_netconn, list);
conn = server_conn;
}while((server_conn != NULL) && server_conn->client);
return server_conn;
}
static struct tls_netconn *net_alloc_socket(struct tls_netconn *conn)
{
int sock=-1, i=0, j=0;
u32 cpu_sr;
struct tls_netconn * conn_t = NULL;
for (i = 0; i < TLS_MAX_NETCONN_NUM; i++)
{
if(p_net_conn[i] == NULL)
{
sock = i;
break;
}
}
if (i == TLS_MAX_NETCONN_NUM){
TLS_DBGPRT_ERR("\nnet_alloc_socket error\n");
return NULL;
}
if(conn != NULL)
{
j = dl_list_len(&conn->list);
if(j>=4)
{
TLS_DBGPRT_ERR("list len > 4\n");
sock = -1;
}
}
if(sock < 0)
{
TLS_DBGPRT_ERR("sock < 0\n");
return NULL;
}
cpu_sr = tls_os_set_critical();
conn_t = tls_mem_alloc(sizeof(struct tls_netconn));
tls_os_release_critical(cpu_sr);
if (NULL != conn_t) {
p_net_conn[sock] = conn_t;
memset(conn_t, 0, sizeof(struct tls_netconn));
conn_t->used = true;
conn_t->state = NETCONN_STATE_NONE;
conn_t->skt_num = sock + 1;//TLS_MAX_NETCONN_NUM +
dl_list_init(&conn_t->list);
#if CONN_SEM_NOT_FREE
TLS_DBGPRT_INFO("conn_op_completed[%d]=%x\n",sock, conn_op_completed[sock]);
if(NULL == conn_op_completed[sock])
{
if(sys_sem_new(&conn_op_completed[sock], 0) != ERR_OK)
{
net_free_socket(conn_t->skt_num);
}
}
#else
if (sys_sem_new(&conn_t->op_completed, 0) != ERR_OK) {
net_free_socket(conn_t->skt_num);
}
#endif
}
TLS_DBGPRT_INFO("net_alloc_socket conn ptr = 0x%x\n", conn_t);
return conn_t;
// return NULL;
}
static void net_free_socket(int socketno)
{
int index;
u32 cpu_sr;
struct tls_netconn *conn = NULL;
conn = tls_net_get_socket(socketno);
if(conn == NULL || TRUE != conn->used)
{
TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used);
return;
}
TLS_DBGPRT_INFO("conn ptr = 0x%x\n", conn);
#if !CONN_SEM_NOT_FREE
if (NULL != conn->op_completed)
{
sys_sem_free(&conn->op_completed);
}
#endif
conn->used = false;
if(conn->client && conn->list.prev != NULL && conn->list.prev != &conn->list)
{
TLS_DBGPRT_INFO("del from list.\n");
cpu_sr = tls_os_set_critical();
dl_list_del(&conn->list);
tls_os_release_critical(cpu_sr);
}
index = conn->skt_num - 1;//TLS_MAX_NETCONN_NUM -
if (conn->pcb.tcp)
{
tcp_close(conn->pcb.tcp);
conn->pcb.tcp = NULL;
}
tls_mem_free(conn);
cpu_sr = tls_os_set_critical();
conn = NULL;
p_net_conn[index] = NULL;
tls_os_release_critical(cpu_sr);
}
static void net_send_event_to_hostif(struct tls_netconn *conn,
int event)
{
struct tls_socket_desc *skt_desc = conn->skd;
TLS_DBGPRT_INFO("skt_desc->state_changed: 0x%x, event=%d\n", skt_desc->state_changed, event);
if(skt_desc->state_changed)
{
skt_desc->state_changed(conn->skt_num, event, conn->state);
}
}
static void net_tcp_close_connect(int socketno)
{
err_t err;
struct tls_netconn *conn = NULL;
conn = tls_net_get_socket(socketno);
if(conn == NULL || TRUE != conn->used)
{
TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used);
return;
}
if (NULL == conn->pcb.tcp){
TLS_DBGPRT_ERR("\ntcp=null\n");
return;
}
/* Set back some callback pointers */
tcp_arg(conn->pcb.tcp, NULL);
if (conn->pcb.tcp->state == LISTEN) {
tcp_accept(conn->pcb.tcp, NULL);
} else {
/* some callbacks have to be reset if tcp_close is not successful */
tcp_recv(conn->pcb.tcp, NULL);
tcp_accept(conn->pcb.tcp, NULL);
tcp_sent(conn->pcb.tcp, NULL);
tcp_poll(conn->pcb.tcp, NULL, 4);
tcp_err(conn->pcb.tcp, NULL);
}
err = tcp_close(conn->pcb.tcp);
if (err)
err = tcp_shutdown(conn->pcb.tcp, 1, 1);
if (err == ERR_OK) {
/* Closing succeeded */
TLS_DBGPRT_INFO("tcp %d closed\n", conn->skt_num);
conn->state = NETCONN_STATE_NONE;
/* Set back some callback pointers as conn is going away */
conn->pcb.tcp = NULL;
net_free_socket(socketno);
/* Trigger select() in socket layer. Make sure everybody notices activity
on the connection, error first! */
} else {
/* Closing failed, restore some of the callbacks */
/* Closing of listen pcb will never fail! */
LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN));
//tcp_sent(conn->pcb.tcp, net_tcp_sent_cb);
tcp_poll(conn->pcb.tcp, net_tcp_poll_cb, 4);
tcp_err(conn->pcb.tcp, net_tcp_err_cb);
tcp_arg(conn->pcb.tcp, (void *)socketno);
/* don't restore recv callback: we don't want to receive any more data */
}
}
static err_t net_tcp_poll_cb(void *arg, struct tcp_pcb *pcb)
{
err_t err_ret = ERR_OK;
struct tls_netconn *conn = NULL;
struct tls_netconn *server_conn = NULL;
int socketno = (int)arg;
conn = tls_net_get_socket(socketno);
if(conn == NULL || TRUE != conn->used || NULL == pcb)
{
TLS_DBGPRT_ERR("\nconn=%x,used=%d,pcb=%x\n",conn, conn->used, pcb);
return ERR_ARG;
}
//TLS_DBGPRT_INFO("net_tcp_poll_cb start\n");
/*
if (conn == NULL || pcb == NULL) {
TLS_DBGPRT_ERR("\npcb=null\n");
return ERR_CLSD;
}
*/
if (conn->write_state && (conn->state == NETCONN_STATE_CONNECTED)) {
//net_do_writemore(conn);
} else if (conn->state == NETCONN_STATE_CLOSED) {
net_tcp_close_connect(socketno);
} else {
if ((pcb->state == CLOSE_WAIT) || (pcb->state == CLOSED)) {
if (conn->pcb.tcp != NULL) {
tcp_arg(conn->pcb.tcp, NULL);
tcp_accept(conn->pcb.tcp, NULL);
tcp_recv(conn->pcb.tcp, NULL);
tcp_sent(conn->pcb.tcp, NULL);
tcp_poll(conn->pcb.tcp, NULL, 4);
tcp_err(conn->pcb.tcp, NULL);
tcp_close(conn->pcb.tcp);
conn->state = NETCONN_STATE_NONE;
net_send_event_to_hostif(conn, NET_EVENT_TCP_DISCONNECT);
conn->pcb.tcp = NULL;
net_free_socket(socketno);
}
}
}
if (conn){
if(conn->client && conn->idle_time > 0)
{
TLS_DBGPRT_INFO("conn->skt_num=%d, conn->client=%d\n", conn->skt_num, conn->client);
// server_conn = dl_list_first(&conn->list, struct tls_netconn, list);
server_conn = get_server_conn(conn);
if(server_conn)
{
--conn->idle_time;
if(conn->idle_time == 0)
{
tcp_abort(pcb);
//tls_socket_close(conn->skt_num);
TLS_DBGPRT_INFO("update conn->idle_time %d\n", conn->idle_time);
return ERR_ABRT;
}
}
}
if((conn->skd) != NULL && (conn->skd->pollf) != NULL)
{
err_ret = conn->skd->pollf(conn->skt_num);
if(err_ret == ERR_ABRT)
tcp_abort(pcb);
return err_ret;
}
}
return ERR_OK;
}
static void net_tcp_err_cb(void *arg, err_t err)
{
struct tls_netconn *conn = NULL;
struct tcp_pcb *pcb = NULL;
int socketno = (int)arg;
u8 event = NET_EVENT_TCP_CONNECT_FAILED;
conn = tls_net_get_socket(socketno);
if(conn == NULL || TRUE != conn->used)
{
TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used);
return;
}
pcb = conn->pcb.tcp;
TLS_DBGPRT_INFO("tcp err = %d, pcb==%x, conn==%x, skt==%x\n", err, (char *)pcb, (char *)conn, conn->skd);
if (pcb) {
tcp_arg(pcb, NULL);
tcp_sent(pcb, NULL);
tcp_recv(pcb, NULL);
tcp_err(pcb, NULL);
if (!conn->client) {
tcp_accept(pcb, NULL);
}
if(err == ERR_OK)
{
tcp_close(pcb);
}
if(conn->state != NETCONN_STATE_NONE)
{
conn->state = NETCONN_STATE_NONE;
event = NET_EVENT_TCP_DISCONNECT;
}
net_send_event_to_hostif(conn, event);
if(conn->skd->errf != NULL)
{
conn->skd->errf(conn->skt_num, err);
}
conn->pcb.tcp = NULL;
net_free_socket(socketno);
//printf("\nfree socket\n");
}
}
#if (RAW_SOCKET_USE_CUSTOM_PBUF)
static struct raw_sk_pbuf_custom*
raw_sk_alloc_pbuf_custom(void)
{
return (struct raw_sk_pbuf_custom*)mem_malloc(sizeof(struct raw_sk_pbuf_custom));
}
static void
raw_sk_free_pbuf_custom(struct raw_sk_pbuf_custom* p)
{
if(p != NULL)
{
mem_free(p);
p = NULL;
}
}
static void
raw_sk_free_pbuf_custom_fn(struct pbuf *p)
{
struct raw_sk_pbuf_custom *pcr = (struct raw_sk_pbuf_custom*)p;
if(p != NULL)
{
//printf("\nraw_sk_free_pbuf_custom_fn,len=%d, custom pcb=%x, conn=%x, conn pcb=%x\n\n",p->tot_len, pcr->pcb, pcr->conn, ((struct tls_netconn *)pcr->conn)->pcb.tcp);
if(TRUE == ((struct tls_netconn *)pcr->conn)->used && pcr->pcb == ((struct tls_netconn *)pcr->conn)->pcb.tcp)
{
tcp_recved((struct tcp_pcb *)pcr->pcb, p->tot_len);
}
if (pcr->original != NULL) {
// printf("\ngo to pbuf_free,original pbuf=%x\n",pcr->original);
pbuf_free(pcr->original);
}
raw_sk_free_pbuf_custom(pcr);
}
}
#endif
/**
* Receive callback function for TCP connect.
*/
static err_t net_tcp_recv_cb(void *arg,
struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
struct tls_netconn *conn;
struct tls_netconn *server_conn = NULL;
err_t err_ret = ERR_OK;
u16 datalen = 0;
#if (RAW_SOCKET_USE_CUSTOM_PBUF)
struct raw_sk_pbuf_custom *pcr = NULL;
struct pbuf *newpbuf = NULL;
#endif
struct pbuf *p_tmp,*p_next;
int socketno = -1;
// TLS_DBGPRT_INFO("net_tcp_recv_cb err=%d\n", err);
LWIP_UNUSED_ARG(pcb);
LWIP_ASSERT("must have a pcb argument", pcb != NULL);
LWIP_ASSERT("must have an argument", arg < 0);
socketno = (int)arg;
conn = tls_net_get_socket(socketno);
if(conn == NULL || TRUE != conn->used)
{
TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used);
return ERR_ARG;
}
LWIP_ASSERT("tcp recv for wrong pcb!", conn->pcb.tcp == pcb);
if (err) {
/* tcp is disconnect */
TLS_DBGPRT_INFO("err code = %d\n", err);
err_ret = err;
#if 0
if (conn->pcb.tcp != NULL) {
tcp_arg(conn->pcb.tcp, NULL);
tcp_accept(conn->pcb.tcp, NULL);
tcp_recv(conn->pcb.tcp, NULL);
tcp_sent(conn->pcb.tcp, NULL);
tcp_poll(conn->pcb.tcp, NULL, 4);
tcp_err(conn->pcb.tcp, NULL);
tcp_close(conn->pcb.tcp);
conn->state = NETCONN_STATE_NONE;
net_send_event_to_hostif(conn, NET_EVENT_TCP_DISCONNECT);
conn->pcb.tcp = NULL;
net_free_socket(conn);
}
#endif
if(conn->skd != NULL && conn->skd->recvf != NULL)
{
TLS_DBGPRT_INFO("conn->skd->recvf to call.");
err_ret = conn->skd->recvf(conn->skt_num, p, err);
if(err_ret == ERR_ABRT)
tcp_abort(pcb);
p = NULL;
}
if (p){
pbuf_free(p);
p = NULL;
}
return err_ret;
}
if (pcb == NULL ||conn == NULL) {//p == NULL ||
TLS_DBGPRT_INFO("pcb = 0x%x, p = 0x%x\n", pcb ,p);
return ERR_VAL;
}
if(p == NULL)
{
TLS_DBGPRT_ERR("received 0\n");
net_tcp_err_cb((void *)socketno, ERR_OK);
return ERR_OK;
}
#if 0//(RAW_SOCKET_USE_CUSTOM_PBUF)
pcr = raw_sk_alloc_pbuf_custom();
if(pcr == NULL)
{
return ERR_MEM;
}
//newpbuf = pbuf_alloced_custom(PBUF_RAW, p->tot_len, PBUF_REF, &pcr->pc, p->payload, p->tot_len);
newpbuf = &(pcr->pc);
newpbuf->len = 0;
newpbuf->payload = NULL;
newpbuf->tot_len = p->tot_len;
newpbuf->next = p;
newpbuf->flags = PBUF_FLAG_IS_CUSTOM;
newpbuf->type = PBUF_REF;
newpbuf->ref =1;
if (newpbuf == NULL) {
raw_sk_free_pbuf_custom(pcr);
return ERR_MEM;
}
pcr->original = p;
pcr->param = pcb;
pcr->pc.custom_free_function = raw_sk_free_pbuf_custom_fn;
#endif
#if !RAW_SOCKET_USE_CUSTOM_PBUF
tcp_recved(pcb, p->tot_len);
#endif
if(conn->client && conn->idle_time > 0)
{
TLS_DBGPRT_INFO("conn->skt_num=%d, conn->client=%d\n", conn->skt_num, conn->client);
// server_conn = dl_list_first(&conn->list, struct tls_netconn, list);
server_conn = get_server_conn(conn);
TLS_DBGPRT_INFO("server_conn=%p\n", server_conn);
if(server_conn)
{
conn->idle_time = server_conn->idle_time;
TLS_DBGPRT_INFO("update conn->idle_time %d\n", conn->idle_time);
}
}
if(conn->skd->recvf != NULL)
{
tls_net_set_sourceip(ip_addr_get_ip4_u32(&pcb->remote_ip));
datalen = p->tot_len;
if (conn->skd->recvwithipf != NULL){
//conn->skd->recvwithipf(conn->skt_num, datalen, (u8 *)(&(pcb->remote_ip.addr)), pcb->remote_port, ERR_OK);
err_ret = conn->skd->recvwithipf(conn->skt_num, datalen, (u8 *)(&(ip_2_ip4(&pcb->remote_ip)->addr)), pcb->remote_port, ERR_OK);
if(err_ret == ERR_ABRT)
tcp_abort(pcb);
}
p_next = p;
for(p_tmp = p; p_tmp != NULL; )
{
p_next = p_tmp->next;
p_tmp->next = NULL;
if(err_ret == ERR_ABRT)
{
pbuf_free(p_tmp);
}
else if(err_ret == ERR_OK)
{
if(p_next != NULL)
printf("\npbufcat p next=%x\n",(u32)p_next);
#if (RAW_SOCKET_USE_CUSTOM_PBUF)
pcr = raw_sk_alloc_pbuf_custom();
if(pcr == NULL)
{
return ERR_MEM;
}
newpbuf = pbuf_alloced_custom(PBUF_RAW, p_tmp->len, PBUF_REF, &pcr->pc, p_tmp->payload, p_tmp->len);
if (newpbuf == NULL) {
raw_sk_free_pbuf_custom(pcr);
return ERR_MEM;
}
pcr->original = p_tmp;
pcr->conn = conn;
pcr->pcb = pcb;
pcr->pc.custom_free_function = raw_sk_free_pbuf_custom_fn;
err_ret = conn->skd->recvf(conn->skt_num, newpbuf, ERR_OK);
#else
err_ret = conn->skd->recvf(conn->skt_num, p_tmp, ERR_OK);
#endif
if(err_ret == ERR_ABRT)
tcp_abort(pcb);
}
p_tmp = p_next;
}
}
else
{
#if 0//(RAW_SOCKET_USE_CUSTOM_PBUF)
raw_sk_free_pbuf_custom(pcr);
#endif
if (p)
pbuf_free(p);
}
return err_ret;
}
#if 0
static err_t net_tcp_sent_cb(void *arg, struct tcp_pcb *pcb, u16_t len)
{
struct tls_netconn *conn = (struct tls_netconn *)arg;
//TLS_DBGPRT_INFO("s\n");
if (conn->write_state && (conn->state == NETCONN_STATE_CONNECTED)) {
net_do_writemore(conn);
} else if (conn->state == NETCONN_STATE_CLOSED) {
net_tcp_close_connect(conn);
}
return ERR_OK;
}
#endif
/**
* tcp connnect callback
*/
static err_t net_tcp_connect_cb(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct tls_netconn *conn;
err_t err_ret = ERR_OK;
int socketno = -1;
socketno = (int)arg;
conn = tls_net_get_socket(socketno);
if(conn == NULL || conn->used != TRUE){
TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used);
tcp_abort(pcb);
return ERR_ABRT;
}
//pcb = conn->pcb.tcp;
if ((conn->proto == TLS_NETCONN_TCP) && (err == ERR_OK)) {
TLS_DBGPRT_INFO("net_tcp_connect_cb =====> state : %d\n", pcb->state);
conn->state = NETCONN_STATE_CONNECTED;
net_send_event_to_hostif(conn, NET_EVENT_TCP_CONNECTED);
} else {
TLS_DBGPRT_INFO("the err is =%d\n", err);
}
if(conn->skd != NULL && conn->skd->connf != NULL)
{
err_ret = conn->skd->connf(conn->skt_num, err);
if(err_ret == ERR_ABRT)
tcp_abort(pcb);
return err_ret;
}
return err;
}
/**
* Accept callback function for TCP netconns.
*/
static err_t net_tcp_accept_cb(void *arg,
struct tcp_pcb *newpcb, err_t err)
{
err_t err_ret = ERR_OK;
struct tls_netconn *conn = NULL;
struct tls_netconn *newconn;
struct tcp_pcb *pcb;
u32 cpu_sr;
int socketno = -1;
//TLS_DBGPRT_INFO("=====>\n");
#if 0
if (conn->tcp_connect_cnt >= TLS_MAX_SOCKET_NUM) {
return ERR_ABRT;
}
#endif
socketno = (int)arg;
conn = tls_net_get_socket(socketno);
if(conn == NULL || conn->used != TRUE){
TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used);
tcp_abort(newpcb);
return ERR_ABRT;
}
if (conn){
tcp_accepted(conn->pcb.tcp);
}
newconn = net_alloc_socket(conn);
//printf("\nnew conn==%x, new pcb==%x\n",newconn,newpcb);
if (!newconn) {
/* connection aborted */
/* not happen */
tcp_abort(newpcb);
//printf("\r\nnet_tcp_accept_cb err\r\n");
return ERR_ABRT;
}
//conn->tcp_connect_cnt++;
newconn->used = true;
newconn->pcb.tcp = newpcb;
newconn->client = true;
newconn->idle_time = conn->idle_time;
newconn->proto = TLS_NETCONN_TCP;
newconn->state = NETCONN_STATE_CONNECTED;
pcb = newconn->pcb.tcp;
ip_set_option(newconn->pcb.tcp, SOF_KEEPALIVE);
newconn->skd = conn->skd;
tcp_arg(pcb, (void *)(newconn->skt_num));
tcp_recv(pcb, net_tcp_recv_cb);
//tcp_sent(pcb, net_tcp_sent_cb);
tcp_poll(pcb, net_tcp_poll_cb, 2);
tcp_err(pcb, net_tcp_err_cb);
cpu_sr = tls_os_set_critical();
dl_list_add_tail(&conn->list, &newconn->list);
tls_os_release_critical(cpu_sr);
newconn->port = host_to_le16(pcb->remote_port);
newconn->localport = conn->localport;
// ip_addr_set(&newconn->addr, &pcb->remote_ip);
ip_addr_copy(newconn->addr, pcb->remote_ip);
net_send_event_to_hostif(newconn, NET_EVENT_TCP_JOINED);
if(conn->skd->acceptf != NULL)
{
err_ret =conn->skd->acceptf(newconn->skt_num, err);
if(err_ret == ERR_ABRT)
{
tcp_abort(pcb);
}
}
//conn->state = NETCONN_STATE_CONNECTED;
return err_ret;
}
/**
* Receive callback function for UDP netconns.
*/
static void net_udp_recv_cb(void *arg, struct udp_pcb *pcb,
struct pbuf *p, const ip_addr_t *srcaddr, u16_t port)
{
struct tls_netconn *conn;
u32 datalen = 0;
int socketno = -1;
//TLS_DBGPRT_INFO("=====>\n");
LWIP_UNUSED_ARG(pcb); /* only used for asserts... */
LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL);
LWIP_ASSERT("recv_udp must have an argument", arg < 0);
socketno = (int)arg;
conn = tls_net_get_socket(socketno);
if(conn == NULL || conn->used != TRUE || NULL == pcb){
TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used);
if (p != NULL)
pbuf_free(p);
return;
}
LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);
/*
if (conn == NULL || pcb == NULL) {
TLS_DBGPRT_INFO("if (conn == NULL || pcb == NULL) \n");
if (p != NULL)
pbuf_free(p);
return;
}
*/
if(conn->skd->recvf != NULL)
{
datalen = p->tot_len;
/*if Address is broadcast, update source IP according to source address and source port according to sender*/
// if ((conn->addr.addr == IPADDR_BROADCAST)||((conn->addr.addr & 0xFF) == 0xFF))
if((ip_addr_get_ip4_u32(&conn->addr) == IPADDR_BROADCAST) || ((ip_addr_get_ip4_u32(&conn->addr) & 0xFF) == 0xFF))
{
tls_net_set_sourceip(ip_addr_get_ip4_u32(srcaddr));
conn->port = port;
}else{
tls_net_set_sourceip(ip_addr_get_ip4_u32(&conn->addr));
}
if (conn->skd->recvwithipf != NULL){
conn->skd->recvwithipf(conn->skt_num, datalen, (u8 *)(&(ip_2_ip4(srcaddr)->addr)), port, ERR_OK);
}
conn->skd->recvf(conn->skt_num, p, ERR_OK);
}
else
{
if (p){
pbuf_free(p);
p = NULL;
}
}
return;
}
/**
* Start create TCP connection
*/
static err_t net_tcp_start(struct tls_netconn *conn)
{
struct tcp_pcb *pcb;
err_t err;
u16 localportnum = conn->localport;
//TLS_DBGPRT_INFO("=====>\n");
conn->pcb.tcp = tcp_new();
pcb = conn->pcb.tcp;
if (pcb == NULL) {
TLS_DBGPRT_INFO("could not allocate tcp pcb\n");
return ERR_VAL;
}
tcp_arg(pcb, (void *)(conn->skt_num));
if (conn->client) {
TLS_DBGPRT_INFO("pcb = 0x%x, conn->addr = 0x%x, port = %d, localport=%d\n",
pcb, ip_addr_get_ip4_u32(&conn->addr), conn->port, conn->localport);
tcp_err(pcb, net_tcp_err_cb);
tcp_recv(pcb, net_tcp_recv_cb);
//tcp_nagle_disable(pcb);
if (pcb->recv != NULL) {
TLS_DBGPRT_INFO("pcb->recv != NULL\n");
}
//tcp_sent(pcb, net_tcp_sent_cb);
tcp_poll(pcb, net_tcp_poll_cb, 4);
ip_set_option(pcb, SOF_KEEPALIVE);
if(localportnum > 0 && localportnum <= 0xFFFF)
{
err = tcp_bind(pcb, IP_ADDR_ANY, localportnum);
if (err != ERR_OK)
{
TLS_DBGPRT_INFO("tcp bind failed %d\n", err);
return err;
}
}
err = tcp_connect(pcb, &conn->addr, conn->port, net_tcp_connect_cb);
if (err != ERR_OK) {
TLS_DBGPRT_INFO("tcp connect failed %d\n", err);
return err;
}
if (conn->localport == 0){
conn->localport = pcb->local_port;
}
} else {
TLS_DBGPRT_INFO("pcb ptr = 0x%x, conn->port = %d\n",
pcb, conn->port);
ip_set_option(pcb, SOF_REUSEADDR);
err = tcp_bind(pcb, IP_ADDR_ANY, conn->port);
if (err != ERR_OK) {
TLS_DBGPRT_INFO("tcp bind failed %d\n", err);
return err;
}
conn->pcb.tcp = tcp_listen(pcb);
//ip_set_option(conn->pcb.tcp, SOF_KEEPALIVE);
if (conn->pcb.tcp == NULL) {
tcp_close(pcb);
/* create tcp sever failed */
TLS_DBGPRT_INFO("tcp listen failed\n");
return ERR_VAL;
}
tcp_arg(conn->pcb.tcp, (void *)(conn->skt_num));
tcp_accept(conn->pcb.tcp, net_tcp_accept_cb);
}
return ERR_OK;
}
/**
* Start create UDP connection
*/
static err_t net_udp_start(struct tls_netconn *conn)
{
struct udp_pcb *udppcb;
u16 localportnum = conn->localport;
udppcb = udp_new();
if(udppcb == NULL) {
return ERR_MEM;
}
conn->pcb.udp = udppcb;
if (udp_bind(udppcb, IP_ADDR_ANY, localportnum)!= ERR_OK){
TLS_DBGPRT_INFO("udp connect failed\n");
return ERR_CONN;
}
if (conn->localport == 0){
conn->localport = udppcb->local_port;
}
/* Set a receive callback for the upcb */
udp_recv(udppcb, net_udp_recv_cb, (void *)(conn->skt_num));
return ERR_OK;
}
#if 0
static err_t net_do_writemore(struct tls_netconn *conn)
{
err_t err = ERR_OK;
void *dataptr;
u16 len, available;
u8 write_finished = 0;
u32 diff;
u8 apiflags = TCP_WRITE_FLAG_COPY;
u8 dontblock = 0;
dataptr = (u8_t*)conn->current_msg->dataptr + conn->current_msg->write_offset;
diff = conn->current_msg->len - conn->current_msg->write_offset;
if (diff > 0xffffUL) { /* max_u16_t */
len = 0xffff;
apiflags |= TCP_WRITE_FLAG_MORE;
} else {
len = (u16_t)diff;
}
available = tcp_sndbuf(conn->pcb.tcp);
if (available < len) {
/* don't try to write more than sendbuf */
len = available;
if (dontblock){
if (!len) {
err = ERR_WOULDBLOCK;
goto err_mem;
}
} else {
apiflags |= TCP_WRITE_FLAG_MORE;
}
}
err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags);
err_mem:
if (err == ERR_OK) {
conn->current_msg->write_offset += len;
if ((conn->current_msg->write_offset == conn->current_msg->len) || dontblock) {
/* everything was written */
write_finished = 1;
conn->current_msg->write_offset = 0;
}
tcp_output(conn->pcb.tcp);
} else if ((err == ERR_MEM) && !dontblock) {
/* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called
we do NOT return to the application thread, since ERR_MEM is
only a temporary error! */
/* tcp_write returned ERR_MEM, try tcp_output anyway */
tcp_output(conn->pcb.tcp);
} else {
/* On errors != ERR_MEM, we don't try writing any more but return
the error to the application thread. */
write_finished = 1;
conn->current_msg->len = 0;
}
if (write_finished) {
/* everything was written: set back connection state
and back to application task */
conn->current_msg->err = err;
conn->write_state = false;
tls_mem_free(conn->current_msg);
conn->current_msg = NULL;
}
return ERR_OK;
}
#endif
static err_t net_skt_tcp_send(struct tls_net_msg *net_msg)
{
struct tcp_pcb *pcb = NULL;
struct tls_netconn *conn;
err_t err;
//TLS_DBGPRT_INFO("=====>\n");
conn = tls_net_get_socket(net_msg->skt_no);
if(conn == NULL || TRUE != conn->used)
{
TLS_DBGPRT_ERR("conn =%x,used=%d\n", conn, conn->used);
return ERR_ARG;
}
pcb = conn->pcb.tcp;
/*
When tcp error occured, lwip will delete the pcb and sometimes GSKT.
This function maybe registered by GSKT_TimerSend, so we must check if GSKT has been delted!!!
*/
err = tcp_write(pcb, net_msg->dataptr, net_msg->len, TCP_WRITE_FLAG_COPY);
if (err == ERR_OK){
//sys_sem_signal(&net_msg->conn->op_completed);
tcp_output(pcb);
}
else
{
// TLS_DBGPRT_INFO("err:%d\n", err);
}
return err;
}
/**
* Send data on a UDP pcb
*/
static void net_do_send(void *ctx)
{
struct tls_net_msg *msg = (struct tls_net_msg *)ctx;
struct tls_netconn *conn = NULL;
struct pbuf *p;
int socketno = msg->skt_no;
//TLS_DBGPRT_INFO("=====>\n");
p = msg->p;
conn = tls_net_get_socket(socketno);
if(conn == NULL || TRUE != conn->used)
{
TLS_DBGPRT_ERR("conn =%x,used=%d\n", conn, conn->used);
if(p)
pbuf_free(p);
#if CONN_SEM_NOT_FREE
sys_sem_signal(&conn_op_completed[socketno - 1]);
#endif
return;
}
#if LWIP_CHECKSUM_ON_COPY
if (ip_addr_isany(&msg->addr)) {
msg->err = udp_send_chksum(conn->pcb.udp, p,
0, 0);
} else {
msg->err = udp_sendto_chksum(conn->pcb.udp, p,
&msg->addr, msg->port,
0, 0);
}
#else /* LWIP_CHECKSUM_ON_COPY */
if (ip_addr_isany(&msg->addr)) {
msg->err = udp_send(conn->pcb.udp, p);
} else {
msg->err = udp_sendto(conn->pcb.udp, p,
&msg->addr, msg->port);
}
#endif /* LWIP_CHECKSUM_ON_COPY */
pbuf_free(p);
#if CONN_SEM_NOT_FREE
sys_sem_signal(&conn_op_completed[socketno - 1]);
#else
conn = tls_net_get_socket(socketno);
if(conn && TRUE == conn->used)
{
sys_sem_signal(&conn->op_completed);
}
#endif
}
/**
* Send data on a TCP pcb
*/
static void net_do_write(void *ctx)
{
struct tls_net_msg *net_msg = (struct tls_net_msg *)ctx;
struct tls_netconn *conn = NULL;
struct tls_netconn *server_conn = NULL;
int socketno = -1;
//TLS_DBGPRT_INFO("=====>\n");
socketno = net_msg->skt_no;
conn = tls_net_get_socket(socketno);
if(conn == NULL ||TRUE != conn->used)
{
TLS_DBGPRT_ERR("\n conn=%x,used=%d\n",conn, conn->used);
#if CONN_SEM_NOT_FREE
sys_sem_signal(&conn_op_completed[socketno - 1]);
#endif
return;
}
//TLS_DBGPRT_INFO("s=%d,p=0x%x\n", conn->state, conn->pcb.tcp);
#if 0
if (ERR_IS_FATAL(conn->last_err)) {
net_msg->err = conn->last_err;
}
#endif
if (conn->proto == TLS_NETCONN_TCP) {
#if LWIP_TCP
if (conn->state != NETCONN_STATE_CONNECTED) {
/* netconn is connecting, closing or in blocking write */
net_msg->err = ERR_INPROGRESS;
} else if (conn->pcb.tcp != NULL) {
conn->write_state = true;
//conn->write_offset = 0;
net_msg->err = net_skt_tcp_send(net_msg);
/* for both cases: if do_writemore was called, don't ACK the APIMSG
since do_writemore ACKs it! */
} else {
net_msg->err = ERR_CONN;
TLS_DBGPRT_INFO("==>err=%d\n", net_msg->err);
}
if(conn->client && conn->idle_time > 0)
{
TLS_DBGPRT_INFO("conn->skt_num=%d, conn->client=%d\n", conn->skt_num, conn->client);
// server_conn = dl_list_first(&conn->list, struct tls_netconn, list);
server_conn = get_server_conn(conn);
TLS_DBGPRT_INFO("server_conn=%p\n", server_conn);
if(server_conn)
{
conn->idle_time = server_conn->idle_time;
TLS_DBGPRT_INFO("update conn->idle_time %d\n", conn->idle_time);
}
}
#else /* LWIP_TCP */
net_msg->err = ERR_VAL;
#endif /* LWIP_TCP */
#if (LWIP_UDP || LWIP_RAW)
} else {
net_msg->err = ERR_VAL;
#endif /* (LWIP_UDP || LWIP_RAW) */
}
//tls_mem_free(net_msg->dataptr);
//if(net_msg->err != ERR_OK)
{
//TLS_DBGPRT_INFO("conn->proto=%d, err=%d\n", conn->proto, net_msg->err);
//TLS_DBGPRT_INFO("free net_msg->dataptr=%p\n", net_msg->dataptr);
#if CONN_SEM_NOT_FREE
sys_sem_signal(&conn_op_completed[socketno - 1]);
#else
conn = tls_net_get_socket(socketno);
if(conn && TRUE == conn->used)
{
sys_sem_signal(&conn->op_completed);
}
#endif
}
#if 0
tls_mem_free(net_msg);
#endif
}
static void do_create_connect(void *ctx)
{
struct tls_net_msg *net_msg = (struct tls_net_msg *)ctx;
struct tls_netconn *conn;
err_t err;
int socketno = -1;
//TLS_DBGPRT_INFO("=====>\n");
socketno = net_msg->skt_no;
conn = tls_net_get_socket(socketno);
if(conn == NULL || TRUE != conn->used)
{
tls_mem_free(net_msg);
TLS_DBGPRT_ERR("\nconn=%x,usde=%d\n",conn, conn->used);
return;
}
TLS_DBGPRT_INFO("conn ptr = 0x%x, conn->skt_num=%d, conn->client=%d\n", conn, conn->skt_num, conn->client);
switch (conn->proto) {
case TLS_NETCONN_UDP:
err = net_udp_start(conn);
if (err != ERR_OK){
conn->state = NETCONN_STATE_NONE;
net_send_event_to_hostif(conn, NET_EVENT_UDP_START_FAILED);
net_free_socket(socketno);
}else{
conn->state = NETCONN_STATE_CONNECTED;
net_send_event_to_hostif(conn, NET_EVENT_UDP_START);
}
break;
case TLS_NETCONN_TCP:
err = net_tcp_start(conn);
if (err != ERR_OK){
conn->state = NETCONN_STATE_NONE;
net_send_event_to_hostif(conn, NET_EVENT_TCP_CONNECT_FAILED);
net_free_socket(socketno);
}else{
if (!conn->client){
net_send_event_to_hostif(conn, NET_EVENT_TCP_CONNECTED);
}
//conn->state = NETCONN_STATE_CONNECTED;
}
break;
default:
/* Unsupported netconn type, e.g. protocol disabled */
break;
}
tls_mem_free(net_msg);
return;
}
static void do_close_connect(void *ctx)
{
struct tls_net_msg *net_msg = (struct tls_net_msg *)ctx;
struct tls_netconn *conn = NULL;
struct tls_netconn *client_conn;
int socketno = net_msg->skt_no;
int i;
int sktNums[TLS_MAX_SOCKET_NUM] = {-1};// 2*TLS_MAX_NETCONN_NUM
conn = tls_net_get_socket(socketno);
if(conn == NULL || TRUE != conn->used)
{
TLS_DBGPRT_ERR("conn==%x,used=%d\n",conn, conn->used);
tls_mem_free(net_msg);
return;
}
switch (conn->proto) {
case TLS_NETCONN_UDP:
if (conn->pcb.udp != NULL) {
conn->pcb.udp->recv_arg = NULL;
udp_remove(conn->pcb.udp);
conn->pcb.udp = NULL;
}
conn->state = NETCONN_STATE_CLOSED;
break;
case TLS_NETCONN_TCP:
if (!conn->client) {
/* it's a server, close connected client */
i=0;
dl_list_for_each(client_conn, &conn->list, struct tls_netconn, list){
if (client_conn->used) {
client_conn->state = NETCONN_STATE_CLOSED;
sktNums[i++] = client_conn->skt_num;
}
}
while(i-->0)
{
//client_conn = tls_net_get_socket(sktNums[i]);
net_tcp_close_connect(sktNums[i]);
}
}
conn->state = NETCONN_STATE_CLOSED;
net_tcp_close_connect(socketno);
break;
default:
break;
}
net_free_socket(socketno);
tls_mem_free(net_msg);
}
int tls_socket_create(struct tls_socket_desc * skd)
{
struct tls_netconn *conn = NULL;
struct tls_net_msg *net_msg;
err_t err = ERR_OK;
//TLS_DBGPRT_INFO("=====>socket_type=%d, skd->protocol=%d\n", socket_type, skd->protocol);
if ((skd->protocol == SOCKET_PROTO_TCP) || (skd->protocol == SOCKET_PROTO_UDP)) {
conn = net_alloc_socket(NULL);
if (conn) {
conn->client = (skd->cs_mode == SOCKET_CS_MODE_CLIENT);
conn->proto = skd->protocol;
if (conn->client){
IP_SET_TYPE(&skd->ip_addr, IPADDR_TYPE_V4);
ip_addr_copy(conn->addr, skd->ip_addr);
conn->state = NETCONN_STATE_NONE;
}
else {
if(conn->proto == 1)
ip_addr_set(&conn->addr, IP_ADDR_BROADCAST);
else
ip_addr_set(&conn->addr, IP_ADDR_ANY);
conn->state = NETCONN_STATE_WAITING;
}
conn->port = skd->port;
conn->localport = skd->localport;
conn->idle_time = skd->timeout;
conn->skd = skd;
//conn->cmd_mode = cmd_mode;
net_msg = tls_mem_alloc(sizeof(*net_msg));
if (net_msg == NULL) {
net_free_socket(conn->skt_num);
return -1;
}
memset(net_msg, 0, sizeof(*net_msg));
net_msg->skt_no = conn->skt_num;
err = tcpip_callback_with_block(do_create_connect, net_msg, 0);
if (err) {
conn->state = NETCONN_STATE_NONE;
net_free_socket(conn->skt_num);
tls_mem_free(net_msg);
}
} else {
return 0;
}
} else {
err = ERR_VAL;
}
if (conn)
return conn->skt_num;
else
return -1;
}
int tls_socket_get_status(u8 socket, u8 *buf, u32 bufsize)
{
struct tls_skt_status_t *skt_status;
struct tls_skt_status_ext_t *skts_ext;
struct tls_netconn *conn;
struct tls_netconn *client_conn;
struct tls_netconn *server_conn;
int remain_len;
skt_status = (struct tls_skt_status_t *)buf;
if (bufsize < sizeof(struct tls_skt_status_t))
{
TLS_DBGPRT_ERR("\nbufsize=%d\n",bufsize);
return ERR_VAL;
}
if (socket < 1 || socket > 20)
{
TLS_DBGPRT_ERR("\nskt num=%d\n",socket);
return ERR_VAL;
}
memset(buf, 0, bufsize);
conn = tls_net_get_socket(socket);
if(conn == NULL || TRUE != conn->used)
{
TLS_DBGPRT_ERR("conn==%x,used=%d\n",conn, conn->used);
return ERR_VAL;
}
remain_len = bufsize - sizeof(u32);
skts_ext = (struct tls_skt_status_ext_t *)(buf + sizeof(u32));
if(conn == NULL){
skt_status->socket_cnt = 1;
skts_ext->protocol = SOCKET_PROTO_TCP;
skts_ext->status = 0;
skts_ext->socket = socket;
skts_ext->host_ipaddr[0] = 0;
skts_ext->host_ipaddr[1] = 0;
skts_ext->host_ipaddr[2] = 0;
skts_ext->host_ipaddr[3] = 0;
return 0;
}
skts_ext->protocol = (enum tls_socket_protocol)conn->proto;
//TLS_DBGPRT_INFO("conn->client=%d, conn->state=%d, conn->used=%d\n", conn->client, conn->state,conn->used);
if (conn->client) {
skt_status->socket_cnt = 1;
if (conn->used) {
MEMCPY(skts_ext->host_ipaddr, (u8 *)ip_2_ip4(&conn->addr), 4);
// server_conn = dl_list_first(&conn->list, struct tls_netconn, list);
server_conn = get_server_conn(conn);
if(server_conn != NULL){
// TLS_DBGPRT_INFO("server_conn->skt_num = %d\n", server_conn->skt_num);
skts_ext->local_port = server_conn->localport;
}
else
skts_ext->local_port = conn->localport;
skts_ext->remote_port = conn->port;
skts_ext->status = conn->state; /* connected */
skts_ext->socket = conn->skt_num;
} else {
skts_ext->status = conn->state; /* disconnect */
skts_ext->socket = conn->skt_num;
}
//TLS_DBGPRT_INFO("skts_ext->socket=%d, skts_ext->status=%d, conn->state=%d\n", skts_ext->socket, skts_ext->status, conn->state);
} else {
struct tls_ethif * ethif;
ethif = tls_netif_get_ethif();
skt_status->socket_cnt = 1;
if (conn->used) {
skts_ext->status = conn->state; /* listen */
//MEMCPY(skts_ext->host_ipaddr, &conn->addr.addr, 4);
//MEMCPY(skts_ext->host_ipaddr, (char *)&sys->ethif->nif->ip_addr.addr, 4);
//MEMCPY(&conn->addr.addr, (char *)&sys->ethif->nif->ip_addr.addr, 4);
//MEMCPY(skts_ext->host_ipaddr, (char *)&ethif->ip_addr.addr, 4);
MEMCPY(skts_ext->host_ipaddr, (char *)(ip_2_ip4(&ethif->ip_addr)), 4);
if(conn->proto == 1){
skts_ext->remote_port = conn->port;
skts_ext->local_port = conn->localport;
if(skts_ext->local_port==0)
skts_ext->local_port = skts_ext->remote_port;
MEMCPY(skts_ext->host_ipaddr, IP_ADDR_BROADCAST, 4);
}else{
skts_ext->local_port = conn->port;
skts_ext->remote_port = 0;
}
skts_ext->socket = conn->skt_num;
remain_len -= sizeof(struct tls_skt_status_ext_t);
dl_list_for_each(client_conn, &conn->list, struct tls_netconn, list){
if (remain_len < sizeof(struct tls_skt_status_ext_t))
break;
if (client_conn->used) {
skts_ext++;
skts_ext->status = client_conn->state; /* connect */
skt_status->socket_cnt++;
MEMCPY(skts_ext->host_ipaddr, (char *)ip_2_ip4(&client_conn->addr), 4);
skts_ext->local_port = conn->port;
skts_ext->remote_port = client_conn->port;
skts_ext->socket = client_conn->skt_num;
skts_ext->protocol = (enum tls_socket_protocol)client_conn->proto;
remain_len -= sizeof(struct tls_skt_status_ext_t);
}
}
} else {
skts_ext->status = conn->state;
skts_ext->socket = conn->skt_num;
}
}
return 0;
}
struct tls_netconn * tls_net_get_socket(u8 socket)
{
struct tls_netconn *conn = NULL;
if (socket < 1 || socket > TLS_MAX_NETCONN_NUM )//* 2
{
TLS_DBGPRT_ERR("skt num=%d\n", socket);
return NULL;
}
conn = p_net_conn[socket - 1];
//TLS_DBGPRT_INFO("conn->skt_num = %d\n", conn->skt_num);
return conn;
}
int tls_socket_close(u8 socket)
{
struct tls_net_msg *net_msg;
struct tls_netconn *conn;
err_t err;
//TLS_DBGPRT_INFO("socket=%d.\n", socket);
if (socket < 1 || socket > TLS_MAX_NETCONN_NUM)//*2
{
TLS_DBGPRT_ERR("skt num=%d\n", socket);
return -1;
}
conn = tls_net_get_socket(socket);
if(conn == NULL || TRUE != conn->used)
{
TLS_DBGPRT_ERR("conn==%x,used=%d\n",conn, conn->used);
return -1;
}
net_msg = tls_mem_alloc(sizeof(*net_msg));
if (net_msg == NULL) {
TLS_DBGPRT_ERR("\nmem err\n");
return -1;
}
memset(net_msg, 0, sizeof(*net_msg));
net_msg->skt_no = socket;
err = tcpip_callback_with_block(do_close_connect, net_msg, 0);
if (err) {
tls_mem_free(net_msg);
}
return err;
}
static err_t netconn_msg(tcpip_callback_fn function, struct tls_net_msg *net_msg, u8_t block)
{
err_t err = ERR_OK;
struct tls_netconn *conn = NULL;
conn = tls_net_get_socket(net_msg->skt_no);
if(conn == NULL || TRUE != conn->used)
{
TLS_DBGPRT_ERR("netconn_msg conn=%x,used=%d\n",conn, conn->used);
return ERR_ARG;
}
#if 1
err = tcpip_callback_with_block(function, net_msg, block);
if(err)
{
//TLS_DBGPRT_INFO("free net_msg->dataptr=%p\n", net_msg->dataptr);
//tls_mem_free(net_msg->dataptr);
TLS_DBGPRT_INFO("callback end, err=%d\n", err);
// tls_mem_free(net_msg);
return err;
}
#if CONN_SEM_NOT_FREE
sys_arch_sem_wait(&conn_op_completed[net_msg->skt_no - 1], 0);
#else
conn = tls_net_get_socket(net_msg->skt_no);
if(conn != NULL && conn->op_completed != NULL)
{
sys_arch_sem_wait(&conn->op_completed, 0);
conn = tls_net_get_socket(net_msg->skt_no);
if(conn == NULL || TRUE != conn->used)
{
printf("wait error, conn is freeed\n");
}
}
#endif
err = net_msg->err;
return err;
#else
struct tls_net_msg *net_msg_item;
if(conn->current_msg == NULL)
{
conn->current_msg = net_msg;
}
else
{
dl_list_add_tail(&conn->current_msg->list, &net_msg->list);
}
//TLS_DBGPRT_INFO("callback\n");
err = tcpip_callback_with_block(function, conn->current_msg, block);
if(err)
{
TLS_DBGPRT_INFO("callback end, err=%d\n", err);
return err;
}
sys_arch_sem_wait(&conn->op_completed, 0);
//TLS_DBGPRT_INFO("callback end\n");
if(conn->current_msg->err)
return conn->current_msg->err;
dl_list_for_each(net_msg_item, &conn->current_msg->list, struct tls_net_msg, list){
err = tcpip_callback_with_block(function, net_msg_item, block);
if(err)
break;
sys_arch_sem_wait(&conn->op_completed, 0);
if(net_msg_item->err)
break;
dl_list_del(&net_msg_item->list);
tls_mem_free(net_msg_item);
}
if(dl_list_empty(&conn->current_msg->list))
{
tls_mem_free(conn->current_msg);
conn->current_msg = NULL;
}
else
{
tls_mem_free(conn->current_msg);
conn->current_msg = net_msg_item;
}
return ERR_OK;
#endif
}
int tls_socket_udp_sendto(u16 localport, u8 *ip_addr, u16 port, void *pdata, u16 len)
{
struct tls_netconn *conn;
struct tls_net_msg *net_msg = NULL;
struct pbuf *p;
int i;
int err = 0;
bool found = false;
/* find match socket */
for (i = 0; i<TLS_MAX_NETCONN_NUM; i++) {// * 2
conn = tls_net_get_socket(i);
if (conn != NULL
&& conn->used
&& (localport== conn->port)
&& (conn->proto == TLS_NETCONN_UDP)) {
found = true;
break;
}
}
if (!found) {
TLS_DBGPRT_ERR("\nfound=0\n");
err = -1;
goto out;
}
net_msg = tls_mem_alloc(sizeof(struct tls_net_msg));
if(!net_msg)
return ERR_MEM;
net_msg->len = len;
net_msg->dataptr = pdata;
/* udp */
while (1) {
p = pbuf_alloc(PBUF_TRANSPORT, net_msg->len, PBUF_REF);
if (p != NULL) {
break;
} else {
/* delay 1 ticks */
tls_os_time_delay(1);
}
}
p->payload = (void*)net_msg->dataptr;
p->len = p->tot_len = net_msg->len;
net_msg->err = ERR_VAL;/* for debug : catch not set err */
net_msg->p = p;
net_msg->port = port;
net_msg->skt_no = conn->skt_num;
MEMCPY((char *)&(ip_2_ip4(&net_msg->addr)->addr), ip_addr, 4);
IP_SET_TYPE(&net_msg->addr, IPADDR_TYPE_V4);
err = netconn_msg(net_do_send, net_msg, 0);
out:
if( net_msg) /*Who allocates free it*/
tls_mem_free(net_msg);
return err;
}
int tls_socket_send(u8 skt_num, void *pdata, u16 len)
{
struct tls_net_msg net_msg[1] = {0};
struct tls_netconn *conn;
struct tls_netconn *client_conn;
struct pbuf *p;
err_t err = ERR_OK;
u32 socket;
u32 errornum = 0;
socket = skt_num;
dl_list_init(&net_msg->list);
net_msg->len = len;
net_msg->dataptr = pdata;
if (socket < 1 || socket > TLS_MAX_NETCONN_NUM)//*2
{
TLS_DBGPRT_ERR("\nskt num=%d\n",socket);
return ERR_VAL;
}
conn = tls_net_get_socket(socket);
if (conn == NULL || TRUE != conn->used)
{
TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used);
return ERR_VAL;
}
if (conn->proto == TLS_NETCONN_UDP)
{
net_msg->skt_no = skt_num;
net_msg->err = ERR_VAL;/* for debug : catch not set err */
do{
p = pbuf_alloc(PBUF_TRANSPORT, net_msg->len, PBUF_REF);
if (p != NULL) {
break;
} else {
TLS_DBGPRT_INFO("pbuf_alloc err.\n");
return ERR_VAL;
}
}while (0);
p->payload = (void*)net_msg->dataptr;
p->len = p->tot_len = net_msg->len;
net_msg->p = p;
net_msg->port = conn->port;
// ip_addr_set(&net_msg->addr, &conn->addr);
ip_addr_copy(net_msg->addr, conn->addr);
err = netconn_msg(net_do_send, net_msg, 0);
}
else if (conn->proto == TLS_NETCONN_TCP)
{
if (conn->client)
{
net_msg->skt_no = skt_num;
net_msg->err = ERR_VAL;/* for debug : catch not set err */
err = netconn_msg(net_do_write, net_msg, 0);
}
else
{
dl_list_for_each(client_conn, &conn->list, struct tls_netconn, list)
{
//printf("\nclient conn=%x,used==%d, sock num=%d, net conn=%x\n",client_conn, client_conn->used, client_conn->skt_num, p_net_conn[client_conn->skt_num - 1]);
if (client_conn && TRUE == client_conn->used && client_conn == p_net_conn[client_conn->skt_num - 1])
{
net_msg->skt_no = client_conn->skt_num;
net_msg->err = ERR_VAL;/* for debug : catch not set err */
err = netconn_msg(net_do_write, net_msg, 0);
if(err)
{
// TLS_DBGPRT_ERR("\nerr:%d\n",err);
}
}
else
{
struct tls_netconn *conn_tmp;
conn_tmp = tls_net_get_socket(socket);
errornum ++;
if(NULL == conn_tmp || errornum >= 4)
{
TLS_DBGPRT_ERR("\nconn=%x, errnum=%d\n", conn_tmp, errornum);
err = ERR_VAL;
break;
}
}
}
}
}
else
{
err = -1;
}
return err;
}
int tls_net_init()
{
//int i;
memset(p_net_conn, 0, sizeof(struct tls_netconn *) * TLS_MAX_NETCONN_NUM);
return 0;
}
#endif //TLS_CONFIG_SOCKET_RAW