📄 api_msg.c
字号:
{
#if LWIP_UDP
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
udp_disconnect(msg->conn->pcb.udp);
}
#endif /* LWIP_UDP */
TCPIP_APIMSG_ACK(msg);
}
/**
* Set a TCP pcb contained in a netconn into listen mode
* Called from netconn_listen.
*
* @param msg the api_msg_msg pointing to the connection
*/
void
do_listen(struct api_msg_msg *msg)
{
#if LWIP_TCP
if (!ERR_IS_FATAL(msg->conn->err)) {
if (msg->conn->pcb.tcp != NULL) {
if (msg->conn->type == NETCONN_TCP) {
if (msg->conn->pcb.tcp->state == CLOSED) {
#if TCP_LISTEN_BACKLOG
struct tcp_pcb* lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
#else /* TCP_LISTEN_BACKLOG */
struct tcp_pcb* lpcb = tcp_listen(msg->conn->pcb.tcp);
#endif /* TCP_LISTEN_BACKLOG */
if (lpcb == NULL) {
msg->conn->err = ERR_MEM;
} else {
/* delete the recvmbox and allocate the acceptmbox */
if (msg->conn->recvmbox != SYS_MBOX_NULL) {
/** @todo: should we drain the recvmbox here? */
sys_mbox_free(msg->conn->recvmbox);
msg->conn->recvmbox = SYS_MBOX_NULL;
}
if (msg->conn->acceptmbox == SYS_MBOX_NULL) {
if ((msg->conn->acceptmbox = sys_mbox_new(DEFAULT_ACCEPTMBOX_SIZE)) == SYS_MBOX_NULL) {
msg->conn->err = ERR_MEM;
}
}
if (msg->conn->err == ERR_OK) {
msg->conn->state = NETCONN_LISTEN;
msg->conn->pcb.tcp = lpcb;
tcp_arg(msg->conn->pcb.tcp, msg->conn);
tcp_accept(msg->conn->pcb.tcp, accept_function);
}
}
} else {
msg->conn->err = ERR_CONN;
}
}
}
}
#endif /* LWIP_TCP */
TCPIP_APIMSG_ACK(msg);
}
/**
* Send some data on a RAW or UDP pcb contained in a netconn
* Called from netconn_send
*
* @param msg the api_msg_msg pointing to the connection
*/
void
do_send(struct api_msg_msg *msg)
{
if (!ERR_IS_FATAL(msg->conn->err)) {
if (msg->conn->pcb.tcp != NULL) {
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
case NETCONN_RAW:
if (msg->msg.b->addr == NULL) {
msg->conn->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p);
} else {
msg->conn->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, msg->msg.b->addr);
}
break;
#endif
#if LWIP_UDP
case NETCONN_UDP:
if (msg->msg.b->addr == NULL) {
msg->conn->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p);
} else {
msg->conn->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, msg->msg.b->addr, msg->msg.b->port);
}
break;
#endif /* LWIP_UDP */
default:
break;
}
}
}
TCPIP_APIMSG_ACK(msg);
}
/**
* Indicate data has been received from a TCP pcb contained in a netconn
* Called from netconn_recv
*
* @param msg the api_msg_msg pointing to the connection
*/
void
do_recv(struct api_msg_msg *msg)
{
#if LWIP_TCP
if (!ERR_IS_FATAL(msg->conn->err)) {
if (msg->conn->pcb.tcp != NULL) {
if (msg->conn->type == NETCONN_TCP) {
#if TCP_LISTEN_BACKLOG
if (msg->conn->pcb.tcp->state == LISTEN) {
tcp_accepted(msg->conn->pcb.tcp);
} else
#endif /* TCP_LISTEN_BACKLOG */
{
tcp_recved(msg->conn->pcb.tcp, msg->msg.r.len);
}
}
}
}
#endif /* LWIP_TCP */
TCPIP_APIMSG_ACK(msg);
}
#if LWIP_TCP
/**
* See if more data needs to be written from a previous call to netconn_write.
* Called initially from do_write. If the first call can't send all data
* (because of low memory or empty send-buffer), this function is called again
* from sent_tcp() or poll_tcp() to send more data. If all data is sent, the
* blocking application thread (waiting in netconn_write) is released.
*
* @param conn netconn (that is currently in state NETCONN_WRITE) to process
* @return ERR_OK
* ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished
*/
static err_t
do_writemore(struct netconn *conn)
{
err_t err;
void *dataptr;
u16_t len, available;
u8_t write_finished = 0;
size_t diff;
LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE));
dataptr = (u8_t*)conn->write_msg->msg.w.dataptr + conn->write_offset;
diff = conn->write_msg->msg.w.len - conn->write_offset;
if (diff > 0xffffUL) { /* max_u16_t */
len = 0xffff;
#if LWIP_TCPIP_CORE_LOCKING
conn->write_delayed = 1;
#endif
} 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 LWIP_TCPIP_CORE_LOCKING
conn->write_delayed = 1;
#endif
}
err = tcp_write(conn->pcb.tcp, dataptr, len, conn->write_msg->msg.w.apiflags);
LWIP_ASSERT("do_writemore: invalid length!", ((conn->write_offset + len) <= conn->write_msg->msg.w.len));
if (err == ERR_OK) {
conn->write_offset += len;
if (conn->write_offset == conn->write_msg->msg.w.len) {
/* everything was written */
write_finished = 1;
conn->write_msg = NULL;
conn->write_offset = 0;
/* API_EVENT might call tcp_tmr, so reset conn->state now */
conn->state = NETCONN_NONE;
}
err = tcp_output_nagle(conn->pcb.tcp);
conn->err = err;
if ((err == ERR_OK) && (tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT)) {
API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);
}
} else if (err == ERR_MEM) {
/* 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_enqueue returned ERR_MEM, try tcp_output anyway */
err = tcp_output(conn->pcb.tcp);
#if LWIP_TCPIP_CORE_LOCKING
conn->write_delayed = 1;
#endif
} else {
/* On errors != ERR_MEM, we don't try writing any more but return
the error to the application thread. */
conn->err = err;
write_finished = 1;
}
if (write_finished) {
/* everything was written: set back connection state
and back to application task */
conn->state = NETCONN_NONE;
#if LWIP_TCPIP_CORE_LOCKING
if (conn->write_delayed != 0)
#endif
{
sys_sem_signal(conn->op_completed);
}
}
#if LWIP_TCPIP_CORE_LOCKING
else
return ERR_MEM;
#endif
return ERR_OK;
}
#endif /* LWIP_TCP */
/**
* Send some data on a TCP pcb contained in a netconn
* Called from netconn_write
*
* @param msg the api_msg_msg pointing to the connection
*/
void
do_write(struct api_msg_msg *msg)
{
if (!ERR_IS_FATAL(msg->conn->err)) {
if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) {
#if LWIP_TCP
msg->conn->state = NETCONN_WRITE;
/* set all the variables used by do_writemore */
LWIP_ASSERT("already writing", msg->conn->write_msg == NULL &&
msg->conn->write_offset == 0);
msg->conn->write_msg = msg;
msg->conn->write_offset = 0;
#if LWIP_TCPIP_CORE_LOCKING
msg->conn->write_delayed = 0;
if (do_writemore(msg->conn) != ERR_OK) {
LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE);
UNLOCK_TCPIP_CORE();
sys_arch_sem_wait(msg->conn->op_completed, 0);
LOCK_TCPIP_CORE();
LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE);
}
#else
do_writemore(msg->conn);
#endif
/* for both cases: if do_writemore was called, don't ACK the APIMSG! */
return;
#endif /* LWIP_TCP */
#if (LWIP_UDP || LWIP_RAW)
} else {
msg->conn->err = ERR_VAL;
#endif /* (LWIP_UDP || LWIP_RAW) */
}
}
TCPIP_APIMSG_ACK(msg);
}
/**
* Return a connection's local or remote address
* Called from netconn_getaddr
*
* @param msg the api_msg_msg pointing to the connection
*/
void
do_getaddr(struct api_msg_msg *msg)
{
if (msg->conn->pcb.ip != NULL) {
*(msg->msg.ad.ipaddr) = (msg->msg.ad.local?msg->conn->pcb.ip->local_ip:msg->conn->pcb.ip->remote_ip);
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
case NETCONN_RAW:
if (msg->msg.ad.local) {
*(msg->msg.ad.port) = msg->conn->pcb.raw->protocol;
} else {
/* return an error as connecting is only a helper for upper layers */
msg->conn->err = ERR_CONN;
}
break;
#endif /* LWIP_RAW */
#if LWIP_UDP
case NETCONN_UDP:
if (msg->msg.ad.local) {
*(msg->msg.ad.port) = msg->conn->pcb.udp->local_port;
} else {
if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) {
msg->conn->err = ERR_CONN;
} else {
*(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port;
}
}
break;
#endif /* LWIP_UDP */
#if LWIP_TCP
case NETCONN_TCP:
*(msg->msg.ad.port) = (msg->msg.ad.local?msg->conn->pcb.tcp->local_port:msg->conn->pcb.tcp->remote_port);
break;
#endif /* LWIP_TCP */
}
} else {
msg->conn->err = ERR_CONN;
}
TCPIP_APIMSG_ACK(msg);
}
/**
* Close a TCP pcb contained in a netconn
* Called from netconn_close
*
* @param msg the api_msg_msg pointing to the connection
*/
void
do_close(struct api_msg_msg *msg)
{
#if LWIP_TCP
if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) {
msg->conn->state = NETCONN_CLOSE;
do_close_internal(msg->conn);
/* for tcp netconns, do_close_internal ACKs the message */
} else
#endif /* LWIP_TCP */
{
msg->conn->err = ERR_VAL;
TCPIP_APIMSG_ACK(msg);
}
}
#if LWIP_IGMP
/**
* Join multicast groups for UDP netconns.
* Called from netconn_join_leave_group
*
* @param msg the api_msg_msg pointing to the connection
*/
void
do_join_leave_group(struct api_msg_msg *msg)
{
if (!ERR_IS_FATAL(msg->conn->err)) {
if (msg->conn->pcb.tcp != NULL) {
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
#if LWIP_UDP
if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
msg->conn->err = igmp_joingroup(msg->msg.jl.interface, msg->msg.jl.multiaddr);
} else {
msg->conn->err = igmp_leavegroup(msg->msg.jl.interface, msg->msg.jl.multiaddr);
}
#endif /* LWIP_UDP */
#if (LWIP_TCP || LWIP_RAW)
} else {
msg->conn->err = ERR_VAL;
#endif /* (LWIP_TCP || LWIP_RAW) */
}
}
}
TCPIP_APIMSG_ACK(msg);
}
#endif /* LWIP_IGMP */
#if LWIP_DNS
/**
* Callback function that is called when DNS name is resolved
* (or on timeout). A waiting application thread is waked up by
* signaling the semaphore.
*/
static void
do_dns_found(const char *name, struct ip_addr *ipaddr, void *arg)
{
struct dns_api_msg *msg = (struct dns_api_msg*)arg;
LWIP_ASSERT("DNS response for wrong host name", strcmp(msg->name, name) == 0);
if (ipaddr == NULL) {
/* timeout or memory error */
*msg->err = ERR_VAL;
} else {
/* address was resolved */
*msg->err = ERR_OK;
*msg->addr = *ipaddr;
}
/* wake up the application task waiting in netconn_gethostbyname */
sys_sem_signal(msg->sem);
}
/**
* Execute a DNS query
* Called from netconn_gethostbyname
*
* @param arg the dns_api_msg pointing to the query
*/
void
do_gethostbyname(void *arg)
{
struct dns_api_msg *msg = (struct dns_api_msg*)arg;
*msg->err = dns_gethostbyname(msg->name, msg->addr, do_dns_found, msg);
if (*msg->err != ERR_INPROGRESS) {
/* on error or immediate success, wake up the application
* task waiting in netconn_gethostbyname */
sys_sem_signal(msg->sem);
}
}
#endif /* LWIP_DNS */
#endif /* LWIP_NETCONN */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -