int lwip_send(int s, void *data, int size, unsigned int flags) { struct lwip_socket *sock; struct netbuf *buf; err_t err; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%d, flags=0x%x)\n", s, data, size, flags)); sock = get_socket(s); if (!sock) { set_errno(EBADF); return -1; } switch (netconn_type(sock->conn)) { case NETCONN_RAW: case NETCONN_UDP: case NETCONN_UDPLITE: case NETCONN_UDPNOCHKSUM: /* create a buffer */ buf = netbuf_new(); if (!buf) { LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ENOBUFS\n", s)); sock_set_errno(sock, ENOBUFS); return -1; } /* make the buffer point to the data that should be sent */ netbuf_ref(buf, data, size); /* send the data */ err = netconn_send(sock->conn, buf); /* deallocated the buffer */ netbuf_delete(buf); break; case NETCONN_TCP: err = netconn_write(sock->conn, data, size, NETCONN_COPY); break; default: err = ERR_ARG; break; } if (err != ERR_OK) { LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d\n", s, err)); sock_set_errno(sock, err_to_errno(err)); return -1; } LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ok size=%d\n", s, size)); sock_set_errno(sock, 0); return size; }
int lwip_recvfrom(int s, void *mem, int len, unsigned int flags, struct sockaddr *from, socklen_t *fromlen) { struct lwip_socket *sock; struct netbuf *buf; u16_t buflen, copylen; struct ip_addr *addr; u16_t port; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags)); sock = get_socket(s); if (!sock) { set_errno(EBADF); return -1; } /* Check if there is data left from the last recv operation. */ if (sock->lastdata) { buf = sock->lastdata; } else { /* If this is non-blocking call, then check first */ if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) && !sock->rcvevent) { LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); sock_set_errno(sock, EWOULDBLOCK); return -1; } /* No data was left from the previous operation, so we try to get some from the network. */ buf = netconn_recv(sock->conn); if (!buf) { /* We should really do some error checking here. */ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s)); sock_set_errno(sock, 0); return 0; } } buflen = netbuf_len(buf); buflen -= sock->lastoffset; if (len > buflen) { copylen = buflen; } else { copylen = len; } /* copy the contents of the received buffer into the supplied memory pointer mem */ netbuf_copy_partial(buf, mem, copylen, sock->lastoffset); /* Check to see from where the data was. */ if (from && fromlen) { struct sockaddr_in sin; addr = netbuf_fromaddr(buf); port = netbuf_fromport(buf); memset(&sin, 0, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_port = htons(port); sin.sin_addr.s_addr = addr->addr; if (*fromlen > sizeof(sin)) *fromlen = sizeof(sin); memcpy(from, &sin, *fromlen); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); ip_addr_debug_print(SOCKETS_DEBUG, addr); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen)); } else { #if SOCKETS_DEBUG addr = netbuf_fromaddr(buf); port = netbuf_fromport(buf); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); ip_addr_debug_print(SOCKETS_DEBUG, addr); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen)); #endif } /* If this is a TCP socket, check if there is data left in the buffer. If so, it should be saved in the sock structure for next time around. */ if (netconn_type(sock->conn) == NETCONN_TCP && buflen - copylen > 0) { sock->lastdata = buf; sock->lastoffset += copylen; } else { sock->lastdata = NULL; sock->lastoffset = 0; netbuf_delete(buf); } sock_set_errno(sock, 0); return copylen; }
int recvfrom(int s, void *mem, int len, unsigned int flags, struct sockaddr *from, socklen_t *fromlen) { struct lwip_socket *sock; struct skbuff *buf; u16_t buflen, copylen, off = 0; struct ip_addr *addr; u16_t port; u8_t done = 0; sock = get_socket(s); if (!sock) return -1; do { /* Check if there is data left from the last recv operation. */ if (sock->lastdata) { buf = sock->lastdata; } else { /* If this is non-blocking call, then check first */ if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) && !sock->rcvevent) { return -1; } /* No data was left from the previous operation, so we try to get some from the network. */ sock->lastdata = buf = netconn_recv(sock->conn); if (!buf) { /* We should really do some error checking here. */ return 0; } } buflen = netbuf_len(buf); buflen -= sock->lastoffset; if (len > buflen) { copylen = buflen; } else { copylen = len; } /* copy the contents of the received buffer into the supplied memory pointer mem */ netbuf_copy_partial(buf, (u8_t*)mem + off, copylen, sock->lastoffset); off += copylen; if (netconn_type(sock->conn) == NETCONN_TCP) { len -= copylen; if ( (len <= 0) || (buf->p->flags & PBUF_FLAG_PUSH) || !sock->rcvevent) { done = 1; } } else { done = 1; } /* If we don't peek the incoming message... */ if ((flags & MSG_PEEK)==0) { /* If this is a TCP socket, check if there is data left in the buffer. If so, it should be saved in the sock structure for next time around. */ if ((sock->conn->type == NETCONN_TCP) && (buflen - copylen > 0)) { sock->lastdata = buf; sock->lastoffset += copylen; } else { sock->lastdata = NULL; sock->lastoffset = 0; netbuf_delete(buf); } } else { done = 1; } } while (!done); /* Check to see from where the data was.*/ if (from && fromlen) { struct sockaddr_in sin; if (netconn_type(sock->conn) == NETCONN_TCP) { addr = (struct ip_addr*)&(sin.sin_addr.s_addr); netconn_getaddr(sock->conn, addr, &port, 0); } else { addr = netbuf_fromaddr(buf); port = netbuf_fromport(buf); } memset(&sin, 0, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_port = htons(port); sin.sin_addr.s_addr = addr->addr; if (*fromlen > sizeof(sin)) *fromlen = sizeof(sin); SMEMCPY(from, &sin, *fromlen); } return off; }