some fixes to recvmsg() and sendmsg()

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20563 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Hugo Santos
2007-04-04 19:17:04 +00:00
parent dae7f8ea46
commit 7245533300
+21 -18
View File
@@ -808,20 +808,21 @@ socket_recvmsg(net_socket *socket, msghdr *header, int flags)
// full datagram so we can cut it here with MSG_TRUNC // full datagram so we can cut it here with MSG_TRUNC
// - returning a NULL buffer when received 0 bytes // - returning a NULL buffer when received 0 bytes
// may not make much sense as we still need the address // may not make much sense as we still need the address
// - gNetBufferModule.read() uses memcpy() instead of user_memcpy
size_t nameLen = header->msg_namelen;
header->msg_namelen = 0; header->msg_namelen = 0;
header->msg_flags = 0; header->msg_flags = 0;
if (buffer == NULL) if (buffer == NULL)
return 0; return 0;
size_t bytesReceived = 0; size_t bufferSize = buffer->size, bytesReceived = 0;
for (i = 0; i < header->msg_iovlen && bytesReceived < buffer->size; i++) { for (i = 0; i < header->msg_iovlen && bytesReceived < bufferSize; i++) {
if (user_memcpy(&tmp, header->msg_iov + i, sizeof(iovec)) != B_OK) if (user_memcpy(&tmp, header->msg_iov + i, sizeof(iovec)) < B_OK)
break; break;
size_t toRead = min_c(buffer->size - bytesReceived, tmp.iov_len); size_t toRead = min_c(bufferSize - bytesReceived, tmp.iov_len);
if (gNetBufferModule.read(buffer, bytesReceived, tmp.iov_base, if (gNetBufferModule.read(buffer, bytesReceived, tmp.iov_base,
toRead) < B_OK) toRead) < B_OK)
break; break;
@@ -829,14 +830,11 @@ socket_recvmsg(net_socket *socket, msghdr *header, int flags)
bytesReceived += toRead; bytesReceived += toRead;
} }
if (bytesReceived == buffer->size) { if (bytesReceived == buffer->size && header->msg_name != NULL) {
if (header->msg_namelen >= buffer->source.ss_len) { header->msg_namelen = min_c(nameLen, buffer->source.ss_len);
memcpy(header->msg_name, &buffer->source, buffer->source.ss_len); memcpy(header->msg_name, &buffer->source, header->msg_namelen);
header->msg_namelen = buffer->source.ss_len;
}
} }
size_t bufferSize = buffer->size;
gNetBufferModule.free(buffer); gNetBufferModule.free(buffer);
if (bytesReceived < bufferSize) if (bytesReceived < bufferSize)
@@ -955,8 +953,16 @@ socket_sendmsg(net_socket *socket, msghdr *header, int flags)
const sockaddr *address = (const sockaddr *)header->msg_name; const sockaddr *address = (const sockaddr *)header->msg_name;
socklen_t addressLength = header->msg_namelen; socklen_t addressLength = header->msg_namelen;
if ((address == NULL || addressLength == 0) && socket->peer.ss_len != 0) { if (addressLength == 0)
// socket is connected, we use that address: address = NULL;
else if (addressLength != 0 && address == NULL)
return B_BAD_VALUE;
if (socket->peer.ss_len != 0) {
if (address != NULL)
return EISCONN;
// socket is connected, we use that address
address = (struct sockaddr *)&socket->peer; address = (struct sockaddr *)&socket->peer;
addressLength = socket->peer.ss_len; addressLength = socket->peer.ss_len;
} }
@@ -964,10 +970,6 @@ socket_sendmsg(net_socket *socket, msghdr *header, int flags)
// don't know where to send to: // don't know where to send to:
return EDESTADDRREQ; return EDESTADDRREQ;
} }
if (socket->peer.ss_len != 0) {
// an address has been given but socket is connected already:
return EISCONN;
}
if (socket->address.ss_len == 0) { if (socket->address.ss_len == 0) {
// try to bind first // try to bind first
@@ -995,8 +997,9 @@ socket_sendmsg(net_socket *socket, msghdr *header, int flags)
length += tmp.iov_len; length += tmp.iov_len;
} }
buffer->flags = flags;
memcpy(&buffer->source, &socket->address, socket->address.ss_len); memcpy(&buffer->source, &socket->address, socket->address.ss_len);
memcpy(&buffer->destination, &socket->peer, socket->peer.ss_len); memcpy(&buffer->destination, address, addressLength);
status_t status = socket->first_info->send_data(socket->first_protocol, status_t status = socket->first_info->send_data(socket->first_protocol,
buffer); buffer);