net_socket: make recvfrom() use recvmsg() and sendto() use sendmsg() for code reusal
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20565 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -40,6 +40,8 @@ struct net_socket_private : net_socket {
|
|||||||
|
|
||||||
void socket_delete(net_socket *socket);
|
void socket_delete(net_socket *socket);
|
||||||
int socket_bind(net_socket *socket, const struct sockaddr *address, socklen_t addressLength);
|
int socket_bind(net_socket *socket, const struct sockaddr *address, socklen_t addressLength);
|
||||||
|
ssize_t socket_recvmsg(net_socket *, msghdr *header, int flags);
|
||||||
|
ssize_t socket_sendmsg(net_socket *, msghdr *header, int flags);
|
||||||
|
|
||||||
struct list sSocketList;
|
struct list sSocketList;
|
||||||
benaphore sSocketLock;
|
benaphore sSocketLock;
|
||||||
@@ -757,26 +759,20 @@ ssize_t
|
|||||||
socket_recvfrom(net_socket *socket, void *data, size_t length, int flags,
|
socket_recvfrom(net_socket *socket, void *data, size_t length, int flags,
|
||||||
struct sockaddr *address, socklen_t *_addressLength)
|
struct sockaddr *address, socklen_t *_addressLength)
|
||||||
{
|
{
|
||||||
net_buffer *buffer;
|
iovec iov = { data, length };
|
||||||
status_t status = socket->first_info->read_data(
|
msghdr header;
|
||||||
socket->first_protocol, length, flags, &buffer);
|
|
||||||
if (status < B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
// if 0 bytes we're received, no buffer will be created
|
memset(&header, 0, sizeof(header));
|
||||||
if (buffer == NULL)
|
header.msg_name = (char *)address;
|
||||||
return 0;
|
header.msg_iov = &iov;
|
||||||
|
header.msg_iovlen = 1;
|
||||||
|
|
||||||
ssize_t bytesReceived = buffer->size;
|
if (_addressLength != NULL)
|
||||||
gNetBufferModule.read(buffer, 0, data, bytesReceived);
|
header.msg_namelen = *_addressLength;
|
||||||
|
|
||||||
// copy source address
|
ssize_t bytesReceived = socket_recvmsg(socket, &header, flags);
|
||||||
if (address != NULL && *_addressLength > 0) {
|
if (_addressLength != NULL)
|
||||||
*_addressLength = min_c(buffer->source.ss_len, *_addressLength);
|
*_addressLength = header.msg_namelen;
|
||||||
memcpy(address, &buffer->source, *_addressLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
gNetBufferModule.free(buffer);
|
|
||||||
|
|
||||||
return bytesReceived;
|
return bytesReceived;
|
||||||
}
|
}
|
||||||
@@ -830,7 +826,7 @@ socket_recvmsg(net_socket *socket, msghdr *header, int flags)
|
|||||||
bytesReceived += toRead;
|
bytesReceived += toRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytesReceived == buffer->size && header->msg_name != NULL) {
|
if (bytesReceived == bufferSize && header->msg_name != NULL) {
|
||||||
header->msg_namelen = min_c(nameLen, buffer->source.ss_len);
|
header->msg_namelen = min_c(nameLen, buffer->source.ss_len);
|
||||||
memcpy(header->msg_name, &buffer->source, header->msg_namelen);
|
memcpy(header->msg_name, &buffer->source, header->msg_namelen);
|
||||||
}
|
}
|
||||||
@@ -894,60 +890,20 @@ ssize_t
|
|||||||
socket_sendto(net_socket *socket, const void *data, size_t length, int flags,
|
socket_sendto(net_socket *socket, const void *data, size_t length, int flags,
|
||||||
const struct sockaddr *address, socklen_t addressLength)
|
const struct sockaddr *address, socklen_t addressLength)
|
||||||
{
|
{
|
||||||
if ((address == NULL || addressLength == 0) && socket->peer.ss_len != 0) {
|
iovec iov = { (void *)data, length };
|
||||||
// socket is connected, we use that address:
|
msghdr header;
|
||||||
address = (struct sockaddr *)&socket->peer;
|
|
||||||
addressLength = socket->peer.ss_len;
|
|
||||||
}
|
|
||||||
if (address == NULL || addressLength == 0) {
|
|
||||||
// don't know where to send to:
|
|
||||||
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) {
|
memset(&header, 0, sizeof(header));
|
||||||
// try to bind first
|
header.msg_name = (char *)address;
|
||||||
status_t status = socket_bind(socket, NULL, 0);
|
header.msg_namelen = addressLength;
|
||||||
if (status < B_OK)
|
header.msg_iov = &iov;
|
||||||
return status;
|
header.msg_iovlen = 1;
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: useful, maybe even computed header space!
|
return socket_sendmsg(socket, &header, flags);
|
||||||
net_buffer *buffer = gNetBufferModule.create(256);
|
|
||||||
if (buffer == NULL)
|
|
||||||
return ENOBUFS;
|
|
||||||
|
|
||||||
// copy data into buffer
|
|
||||||
if (gNetBufferModule.append(buffer, data, length) < B_OK) {
|
|
||||||
gNetBufferModule.free(buffer);
|
|
||||||
return ENOBUFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer->flags = flags;
|
|
||||||
memcpy(&buffer->source, &socket->address, socket->address.ss_len);
|
|
||||||
memcpy(&buffer->destination, address, addressLength);
|
|
||||||
|
|
||||||
status_t status = socket->first_info->send_data(socket->first_protocol,
|
|
||||||
buffer);
|
|
||||||
if (status < B_OK) {
|
|
||||||
size_t size = buffer->size;
|
|
||||||
gNetBufferModule.free(buffer);
|
|
||||||
|
|
||||||
if (size != length && (status == B_INTERRUPTED || status == B_WOULD_BLOCK)) {
|
|
||||||
// this appears to be a partial write
|
|
||||||
return length - size;
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
ssize_t
|
||||||
socket_sendmsg(net_socket *socket, msghdr *header, int flags)
|
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;
|
||||||
|
|||||||
Reference in New Issue
Block a user