| 1300 | } |
| 1301 | |
| 1302 | ssize_t |
| 1303 | lwip_recvmsg(int s, struct msghdr *message, int flags) |
| 1304 | { |
| 1305 | struct lwip_sock *sock; |
| 1306 | int i; |
| 1307 | ssize_t buflen; |
| 1308 | |
| 1309 | LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvmsg(%d, message=%p, flags=0x%x)\n", s, (void *)message, flags)); |
| 1310 | LWIP_ERROR("lwip_recvmsg: invalid message pointer", message != NULL, return ERR_ARG;); |
| 1311 | LWIP_ERROR("lwip_recvmsg: unsupported flags", (flags & ~(MSG_PEEK|MSG_DONTWAIT)) == 0, |
| 1312 | set_errno(EOPNOTSUPP); return -1;); |
| 1313 | |
| 1314 | if ((message->msg_iovlen <= 0) || (message->msg_iovlen > IOV_MAX)) { |
| 1315 | set_errno(EMSGSIZE); |
| 1316 | return -1; |
| 1317 | } |
| 1318 | |
| 1319 | sock = get_socket(s); |
| 1320 | if (!sock) { |
| 1321 | return -1; |
| 1322 | } |
| 1323 | |
| 1324 | /* check for valid vectors */ |
| 1325 | buflen = 0; |
| 1326 | for (i = 0; i < message->msg_iovlen; i++) { |
| 1327 | if ((message->msg_iov[i].iov_base == NULL) || ((ssize_t)message->msg_iov[i].iov_len <= 0) || |
| 1328 | ((size_t)(ssize_t)message->msg_iov[i].iov_len != message->msg_iov[i].iov_len) || |
| 1329 | ((ssize_t)(buflen + (ssize_t)message->msg_iov[i].iov_len) <= 0)) { |
| 1330 | sock_set_errno(sock, err_to_errno(ERR_VAL)); |
| 1331 | done_socket(sock); |
| 1332 | return -1; |
| 1333 | } |
| 1334 | buflen = (ssize_t)(buflen + (ssize_t)message->msg_iov[i].iov_len); |
| 1335 | } |
| 1336 | |
| 1337 | if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { |
| 1338 | #if LWIP_TCP |
| 1339 | int recv_flags = flags; |
| 1340 | message->msg_flags = 0; |
| 1341 | /* recv the data */ |
| 1342 | buflen = 0; |
| 1343 | for (i = 0; i < message->msg_iovlen; i++) { |
| 1344 | /* try to receive into this vector's buffer */ |
| 1345 | ssize_t recvd_local = lwip_recv_tcp(sock, message->msg_iov[i].iov_base, message->msg_iov[i].iov_len, recv_flags); |
| 1346 | if (recvd_local > 0) { |
| 1347 | /* sum up received bytes */ |
| 1348 | buflen += recvd_local; |
| 1349 | } |
| 1350 | if ((recvd_local < 0) || (recvd_local < (int)message->msg_iov[i].iov_len) || |
| 1351 | (flags & MSG_PEEK)) { |
| 1352 | /* returned prematurely (or peeking, which might actually be limitated to the first iov) */ |
| 1353 | if (buflen <= 0) { |
| 1354 | /* nothing received at all, propagate the error */ |
| 1355 | buflen = recvd_local; |
| 1356 | } |
| 1357 | break; |
| 1358 | } |
| 1359 | /* pass MSG_DONTWAIT to lwip_recv_tcp() to prevent waiting for more data */ |