migrating recvmsg() to recvfrom()

W

Wim Deprez

Hi group,

I am trying to port a reliable multicast framework for UNIX to Win32 and so
far so good, but I stumbled on the next problem:

in the original code, the programmers use the recvmsg() function and as far
as I know, there is no Windows-version of this function. So I guess I will
have to translate it to a recvfrom(), but that gives some problems.

First of all, in the man pages I read the following:

<man recvfrom>
int recvfrom(int s, void *buf, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen);

int recvmsg(int s, struct msghdr *msg, int flags);

DESCRIPTION

[...]

The recvmsg call uses a msghdr structure to minimize the
number of directly supplied parameters. This structure
has the following form, as defined in <sys/socket.h>:

struct msghdr {
void * msg_name; /* optional address */
socklen_t msg_namelen; /* size of address */
struct iovec * msg_iov; /* scatter/gather array */
size_t msg_iovlen; /* # elements in msg_iov */
void * msg_control; /* ancillary data, see below
*/
socklen_t msg_controllen; /* ancillary data buffer len
*/
int msg_flags; /* flags on received message
*/
};

[...]

The messages are of the form:

struct cmsghdr {
socklen_t cmsg_len; /* data byte count, including hdr
*/
int cmsg_level; /* originating protocol */
int cmsg_type; /* protocol-specific type */
/* followed by
u_char cmsg_data[]; */
};

Ancillary data should only be accessed by the macros
defined in cmsg(3).

[...]

</man recvfrom>


So how do I translate it then?

if the original code is

bytes_read=recvmsg(sd, &msg, 0);

I think it should be the following:

bytes_read=recvmsg(sd, &msg.msg_control->cmsg_data,
&msg.msg_control->cmsg_len, 0, (sockaddr *)&msg.msn_name,&msg.msg_namelen);

anyone has got an idea if my way of thinking is ok here? imho, the framework
is poorly organized, so I don't find a direct way to test it for only this
purpose.

but in for example Cygwin, there is no "msg_control" in the msghdr-struct.
(/usr/include/cygwin/socket.h)

Due to absence of experience with msghdr, I have no idea if my translation
can work and I am looking for a second opinion or other ideas.

Many kind greetings and thanks in advance,

--wim
 
W

Wim Deprez

Hi Group,

guess I found a solution, I'll post it right here just for the
threads-sake:

if you want to port a *nix-program that uses the recvmsg() and
sendmsg()-functions, you can migrate them by using the following code:

ssize_t fake_recvmsg(int sd, struct msghdr *msg, int flags)
{
ssize_t bytes_read;
size_t expected_recv_size;
ssize_t left2move;
char *tmp_buf;
char *tmp;
int i;

assert(msg->msg_iov);

expected_recv_size = 0;
for(i = 0; i < msg->msg_iovlen; i++)
expected_recv_size += msg->msg_iov.iov_len;
tmp_buf = malloc(expected_recv_size);
if(!tmp_buf)
return -1;

left2move = bytes_read = recvfrom(sd,
tmp_buf,
expected_recv_size,
flags,
(struct sockaddr *)msg->msg_name,
&msg->msg_namelen
);

for(tmp = tmp_buf, i = 0; i < msg->msg_iovlen; i++)
{
if(left2move <= 0) break;
assert(msg->msg_iov.iov_base);
memcpy(
msg->msg_iov.iov_base,
tmp,
MIN(msg->msg_iov.iov_len,left2move)
);
left2move -= msg->msg_iov.iov_len;
tmp += msg->msg_iov.iov_len;
}

free(tmp_buf);

return bytes_read;
}



and




ssize_t fake_sendmsg(int sd, struct msghdr *msg, int flags)
{
ssize_t bytes_send;
size_t expected_send_size;
size_t left2move;
char *tmp_buf;
char *tmp;
int i;

assert(msg->msg_iov);

expected_send_size = 0;
for(i = 0; i < msg->msg_iovlen; i++)
expected_send_size += msg->msg_iov.iov_len;
tmp_buf = malloc(expected_send_size);
if(!tmp_buf)
return -1;

for(tmp = tmp_buf, left2move = expected_send_size, i = 0; i <
msg->msg_iovlen; i++)
{
if(left2move <= 0) break;
assert(msg->msg_iov.iov_base);
memcpy(
tmp,
msg->msg_iov.iov_base,
MIN(msg->msg_iov.iov_len,left2move));
left2move -= msg->msg_iov.iov_len;
tmp += msg->msg_iov.iov_len;
}

bytes_send = sendto(sd,
tmp_buf,
expected_send_size,
flags,
(struct sockaddr *)msg->msg_name,
msg->msg_namelen
);

free(tmp_buf);

return bytes_send;
}


greetings and have a nice Sunday-evening,

--wim
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top