Added except set support in select (patch #6860)

This commit is contained in:
goldsimon 2010-01-29 23:05:33 +00:00
parent 9c41e1eea3
commit 855dcadf7a
4 changed files with 42 additions and 11 deletions

View File

@ -19,6 +19,10 @@ HISTORY
++ New features:
2010-01-29: Simon Goldschmidt (patch by Laura Garrett)
* api.h, api_msg.c, sockets.c: Added except set support in select
(patch #6860)
2010-01-29: Simon Goldschmidt (patch by Laura Garrett)
* api.h, sockets.h, err.h, api_lib.c, api_msg.c, sockets.c, err.c:
Add non-blocking support for connect (partly from patch #6860),

View File

@ -330,7 +330,7 @@ err_tcp(void *arg, err_t err)
conn->pcb.tcp = NULL;
/* no check since this is always fatal */
/* no check since this is always fatal! */
SYS_ARCH_PROTECT(lev);
conn->last_err = err;
SYS_ARCH_UNPROTECT(lev);
@ -339,18 +339,25 @@ err_tcp(void *arg, err_t err)
old_state = conn->state;
conn->state = NETCONN_NONE;
/* Notify the user layer about a connection error. Used to signal
select. */
API_EVENT(conn, NETCONN_EVT_ERROR, 0);
/* Try to release selects pending on 'read' or 'write', too.
They will get an error if they actually try to read or write. */
API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
/* pass NULL-message to recvmbox to wake up pending recv */
if (conn->recvmbox != SYS_MBOX_NULL) {
/* Register event with callback */
API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
/* use trypot to preven deadlock */
/* use trypost to prevent deadlock */
sys_mbox_trypost(conn->recvmbox, NULL);
}
/* pass NULL-message to acceptmbox to wake up pending accept */
if (conn->acceptmbox != SYS_MBOX_NULL) {
/* Register event with callback */
API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
/* use trypot to preven deadlock */
/* use trypost to preven deadlock */
sys_mbox_trypost(conn->acceptmbox, NULL);
}
if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) ||
(old_state == NETCONN_CONNECT)) {
/* calling do_writemore/do_close_internal is not necessary
@ -721,8 +728,9 @@ do_close_internal(struct netconn *conn)
conn->state = NETCONN_NONE;
/* Set back some callback pointers as conn is going away */
conn->pcb.tcp = NULL;
/* @todo: this lets select make the socket readable and writable,
which is wrong! errfd instead? */
/* Trigger select() in socket layer. Make sure everybody notices activity
on the connection, error first! */
API_EVENT(conn, NETCONN_EVT_ERROR, 0);
API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
/* wake up the application task */

View File

@ -70,6 +70,8 @@ struct lwip_socket {
/** number of times data was ACKed (free send buffer), set by event_callback(),
tested by select */
u16_t sendevent;
/** error happened for this socket, set by event_callback(), tested by select */
u16_t errevent;
/** last error that occurred on this socket */
int err;
};
@ -227,6 +229,7 @@ alloc_socket(struct netconn *newconn)
sockets[i].rcvevent = 0;
/* TCP sendbuf is empty, but not connected yet, so not yet writable */
sockets[i].sendevent = (newconn->type == NETCONN_TCP ? 0 : 1);
sockets[i].errevent = 0;
sockets[i].err = 0;
sys_sem_signal(socksem);
return i;
@ -872,10 +875,19 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
nready++;
}
}
if (FD_ISSET(i, exceptset)) {
/* See if netconn of this socket had an error */
p_sock = get_socket(i);
if (p_sock && p_sock->errevent) {
FD_SET(i, &lexceptset);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i));
nready++;
}
}
}
*readset = lreadset;
*writeset = lwriteset;
FD_ZERO(exceptset);
*exceptset = lexceptset;
return nready;
}
@ -1087,6 +1099,9 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
case NETCONN_EVT_SENDMINUS:
sock->sendevent = 0;
break;
case NETCONN_EVT_ERROR:
sock->errevent = 1;
break;
default:
LWIP_ASSERT("unknown event", 0);
break;
@ -1111,6 +1126,9 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
if (scb->writeset && FD_ISSET(s, scb->writeset))
if (sock->sendevent)
break;
if (scb->exceptset && FD_ISSET(s, scb->exceptset))
if (sock->errevent != 0)
break;
}
}
if (scb) {

View File

@ -89,7 +89,8 @@ enum netconn_evt {
NETCONN_EVT_RCVPLUS,
NETCONN_EVT_RCVMINUS,
NETCONN_EVT_SENDPLUS,
NETCONN_EVT_SENDMINUS
NETCONN_EVT_SENDMINUS,
NETCONN_EVT_ERROR
};
#if LWIP_IGMP