}
/**
- * Receive data (in form of a netbuf containing a packet buffer) from a netconn
+ * Receive data: actual implementation that doesn't care whether pbuf or netbuf
+ * is received
*
* @param conn the netconn from which to receive data
- * @param new_buf pointer where a new netbuf is stored when received data
+ * @param new_buf pointer where a new pbuf/netbuf is stored when received data
* @return ERR_OK if data has been received, an error code otherwise (timeout,
* memory error or another error)
*/
-err_t
-netconn_recv(struct netconn *conn, struct netbuf **new_buf)
+static err_t
+netconn_recv_data(struct netconn *conn, void **new_buf)
{
struct api_msg msg;
- struct netbuf *buf = NULL;
- struct pbuf *p;
+ void *buf = NULL;
u16_t len;
err_t err;
return err;
}
- if (conn->type == NETCONN_TCP) {
-#if LWIP_TCP
- /* This is not a listening netconn, since recvmbox is set */
-
- buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
- if (buf == NULL) {
- NETCONN_SET_SAFE_ERR(conn, ERR_MEM);
- return ERR_MEM;
- }
-
#if LWIP_SO_RCVTIMEO
- if (sys_arch_mbox_fetch(&conn->recvmbox, (void **)&p, conn->recv_timeout)==SYS_ARCH_TIMEOUT) {
- memp_free(MEMP_NETBUF, buf);
- NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT);
- return ERR_TIMEOUT;
- }
+ if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
+ NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT);
+ return ERR_TIMEOUT;
+ }
#else
- sys_arch_mbox_fetch(&conn->recvmbox, (void **)&p, 0);
+ sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0);
#endif /* LWIP_SO_RCVTIMEO*/
- if (p != NULL) {
- len = p->tot_len;
- SYS_ARCH_DEC(conn->recv_avail, len);
- } else {
- /* This means the connection has been closed */
- len = 0;
- }
-
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
-
- /* If we are closed, we indicate that we no longer wish to use the socket */
- if (p == NULL) {
- memp_free(MEMP_NETBUF, buf);
- /* Avoid to lose any previous error code */
- NETCONN_SET_SAFE_ERR(conn, ERR_CLSD);
- return ERR_CLSD;
- }
-
- buf->p = p;
- buf->ptr = p;
- buf->port = 0;
- buf->addr = NULL;
-
+#if LWIP_TCP
+ if (conn->type == NETCONN_TCP) {
if (!netconn_get_noautorecved(conn) || (buf == NULL)) {
/* Let the stack know that we have taken the data. */
/* TODO: Speedup: Don't block and wait for the answer here
msg.function = do_recv;
msg.msg.conn = conn;
if (buf != NULL) {
- msg.msg.msg.r.len = buf->p->tot_len;
+ msg.msg.msg.r.len = ((struct pbuf *)buf)->tot_len;
} else {
msg.msg.msg.r.len = 1;
}
/* don't care for the return value of do_recv */
TCPIP_APIMSG(&msg);
}
+
+ /* If we are closed, we indicate that we no longer wish to use the socket */
+ if (buf == NULL) {
+ API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
+ /* Avoid to lose any previous error code */
+ NETCONN_SET_SAFE_ERR(conn, ERR_CLSD);
+ return ERR_CLSD;
+ }
+ len = ((struct pbuf *)buf)->tot_len;
+ }
#endif /* LWIP_TCP */
- } else {
+#if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
+ else
+#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
#if (LWIP_UDP || LWIP_RAW)
-#if LWIP_SO_RCVTIMEO
- if (sys_arch_mbox_fetch(&conn->recvmbox, (void **)&buf, conn->recv_timeout)==SYS_ARCH_TIMEOUT) {
- NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT);
- return ERR_TIMEOUT;
- }
-#else
- sys_arch_mbox_fetch(&conn->recvmbox, (void **)&buf, 0);
-#endif /* LWIP_SO_RCVTIMEO*/
+ {
LWIP_ASSERT("buf != NULL", buf != NULL);
-
- SYS_ARCH_DEC(conn->recv_avail, buf->p->tot_len);
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len);
-#endif /* (LWIP_UDP || LWIP_RAW) */
+ len = netbuf_len((struct netbuf *)buf);
}
- LWIP_ASSERT("buf != NULL", buf != NULL);
+#endif /* (LWIP_UDP || LWIP_RAW) */
+
+ SYS_ARCH_DEC(conn->recv_avail, len);
+ /* Register event with callback */
+ API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
- LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p\n", (void *)buf));
+ LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len));
*new_buf = buf;
/* don't set conn->last_err: it's only ERR_OK, anyway */
return ERR_OK;
}
+/**
+ * Receive data (in form of a pbuf) from a TCP netconn
+ *
+ * @param conn the netconn from which to receive data
+ * @param new_buf pointer where a new pbuf is stored when received data
+ * @return ERR_OK if data has been received, an error code otherwise (timeout,
+ * memory error or another error)
+ * ERR_ARG if conn is not a TCP netconn
+ */
+err_t
+netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf)
+{
+ LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) &&
+ netconn_type(conn) == NETCONN_TCP, return ERR_ARG;);
+
+ return netconn_recv_data(conn, new_buf);
+}
+
+/**
+ * Receive data (in form of a netbuf containing a packet buffer) from a netconn
+ *
+ * @param conn the netconn from which to receive data
+ * @param new_buf pointer where a new netbuf is stored when received data
+ * @return ERR_OK if data has been received, an error code otherwise (timeout,
+ * memory error or another error)
+ */
+err_t
+netconn_recv(struct netconn *conn, struct netbuf **new_buf)
+{
+ struct netbuf *buf = NULL;
+ err_t err;
+
+ LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
+ *new_buf = NULL;
+ LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
+ LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
+
+ if (conn->type == NETCONN_TCP) {
+#if LWIP_TCP
+ struct pbuf *p = NULL;
+ /* This is not a listening netconn, since recvmbox is set */
+
+ buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
+ if (buf == NULL) {
+ NETCONN_SET_SAFE_ERR(conn, ERR_MEM);
+ return ERR_MEM;
+ }
+
+ err = netconn_recv_data(conn, &p);
+ if (err != ERR_OK) {
+ memp_free(MEMP_NETBUF, buf);
+ return err;
+ }
+ LWIP_ASSERT("p != NULL", p != NULL);
+
+ buf->p = p;
+ buf->ptr = p;
+ buf->port = 0;
+ buf->addr = NULL;
+ *new_buf = buf;
+ /* don't set conn->last_err: it's only ERR_OK, anyway */
+ return ERR_OK;
+#endif /* LWIP_TCP */
+ } else {
+#if (LWIP_UDP || LWIP_RAW)
+ return netconn_recv_data(conn, new_buf);
+#endif /* (LWIP_UDP || LWIP_RAW) */
+ }
+}
+
/**
* TCP: update the receive window: by calling this, the application
* tells the stack that it has processed data and is able to accept
#include "lwip/raw.h"
#include "lwip/udp.h"
#include "lwip/tcpip.h"
+#include "lwip/pbuf.h"
#include <string.h>
/** sockets currently are built on netconns, each socket has one netconn */
struct netconn *conn;
/** data that was left from the previous read */
- struct netbuf *lastdata;
+ void *lastdata;
/** offset in the data that was left from the previous read */
u16_t lastoffset;
/** number of times data was received, set by event_callback(),
* delete before!
*
* @param sock the socket to free
+ * @param is_tcp != 0 for TCP sockets, used to free lastdata
*/
static void
-free_socket(struct lwip_sock *sock)
+free_socket(struct lwip_sock *sock, int is_tcp)
{
- struct netbuf *lastdata;
+ void *lastdata;
SYS_ARCH_DECL_PROTECT(lev);
lastdata = sock->lastdata;
SYS_ARCH_UNPROTECT(lev);
if (lastdata != NULL) {
- netbuf_delete(lastdata);
+ if (is_tcp) {
+ pbuf_free((struct pbuf *)lastdata);
+ } else {
+ netbuf_delete((struct netbuf *)lastdata);
+ }
}
}
lwip_close(int s)
{
struct lwip_sock *sock;
+ int is_tcp = 0;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
return -1;
}
+ if(sock->conn != NULL) {
+ is_tcp = netconn_type(sock->conn) == NETCONN_TCP;
+ } else {
+ LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL);
+ }
+
netconn_delete(sock->conn);
- free_socket(sock);
+ free_socket(sock, is_tcp);
set_errno(0);
return 0;
}
struct sockaddr *from, socklen_t *fromlen)
{
struct lwip_sock *sock;
- struct netbuf *buf;
- u16_t buflen, copylen;
- int off = 0;
- ip_addr_t *addr;
- u16_t port;
- u8_t done = 0;
- err_t err;
+ void *buf = NULL;
+ struct pbuf *p;
+ u16_t buflen, copylen;
+ int off = 0;
+ ip_addr_t *addr;
+ u16_t port;
+ u8_t done = 0;
+ err_t err;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags));
sock = get_socket(s);
return -1;
do {
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", (void*)sock->lastdata));
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata));
/* Check if there is data left from the last recv operation. */
if (sock->lastdata) {
buf = sock->lastdata;
/* No data was left from the previous operation, so we try to get
some from the network. */
- err = netconn_recv(sock->conn, &buf);
+ if (netconn_type(sock->conn) == NETCONN_TCP) {
+ err = netconn_recv_tcp_pbuf(sock->conn, &(struct pbuf *)buf);
+ } else {
+ err = netconn_recv(sock->conn, &(struct netbuf *)buf);
+ }
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n",
- err, (void*)buf));
+ err, buf));
if (err != ERR_OK) {
if (off > 0) {
sock->lastdata = buf;
}
- buflen = netbuf_len(buf);
+ if (netconn_type(sock->conn) == NETCONN_TCP) {
+ p = (struct pbuf *)buf;
+ } else {
+ p = ((struct netbuf *)buf)->p;
+ }
+ buflen = p->tot_len;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n",
buflen, len, off, sock->lastoffset));
/* copy the contents of the received buffer into
the supplied memory pointer mem */
- netbuf_copy_partial(buf, (u8_t*)mem + off, copylen, sock->lastoffset);
+ pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset);
off += copylen;
LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
len -= copylen;
if ( (len <= 0) ||
- (buf->p->flags & PBUF_FLAG_PUSH) ||
+ (p->flags & PBUF_FLAG_PUSH) ||
(sock->rcvevent <= 0) ||
((flags & MSG_PEEK)!=0)) {
done = 1;
addr = &fromaddr;
netconn_getaddr(sock->conn, addr, &port, 0);
} else {
- addr = netbuf_fromaddr(buf);
- port = netbuf_fromport(buf);
+ addr = netbuf_fromaddr((struct netbuf *)buf);
+ port = netbuf_fromport((struct netbuf *)buf);
}
memset(&sin, 0, sizeof(sin));
addr = &fromaddr;
netconn_getaddr(sock->conn, addr, &port, 0);
} else {
- addr = netbuf_fromaddr(buf);
- port = netbuf_fromport(buf);
+ addr = netbuf_fromaddr((struct netbuf *)buf);
+ port = netbuf_fromport((struct netbuf *)buf);
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) {
sock->lastdata = buf;
sock->lastoffset += copylen;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", (void*)buf));
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf));
} else {
sock->lastdata = NULL;
sock->lastoffset = 0;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", (void*)buf));
- netbuf_delete(buf);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf));
+ if (netconn_type(sock->conn) == NETCONN_TCP) {
+ pbuf_free((struct pbuf *)buf);
+ } else {
+ netbuf_delete((struct netbuf *)buf);
+ }
}
}
} while (!done);
/* Check if there is data left from the last recv operation. /maq 041215 */
if (sock->lastdata) {
- buflen = netbuf_len(sock->lastdata);
+ struct pbuf *p = (struct pbuf *)sock->lastdata;
+ if (netconn_type(sock->conn) != NETCONN_TCP) {
+ p = ((struct netbuf *)p)->p;
+ }
+ buflen = p->tot_len;
buflen -= sock->lastoffset;
*((u16_t*)argp) += buflen;