Connecting Tech Pros Worldwide Help | Site Map

migrating recvmsg() to recvfrom()

 
LinkBack Thread Tools Search this Thread
  #1  
Old July 22nd, 2005, 04:44 PM
Wim Deprez
Guest
 
Posts: n/a
Default migrating recvmsg() to recvfrom()

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




  #2  
Old July 22nd, 2005, 04:51 PM
Wim Deprez
Guest
 
Posts: n/a
Default Re: migrating recvmsg() to recvfrom()

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[i].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[i].iov_base);
memcpy(
msg->msg_iov[i].iov_base,
tmp,
MIN(msg->msg_iov[i].iov_len,left2move)
);
left2move -= msg->msg_iov[i].iov_len;
tmp += msg->msg_iov[i].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[i].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[i].iov_base);
memcpy(
tmp,
msg->msg_iov[i].iov_base,
MIN(msg->msg_iov[i].iov_len,left2move));
left2move -= msg->msg_iov[i].iov_len;
tmp += msg->msg_iov[i].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


-------------------------
Many thanks to Lev Walkin
 

Bookmarks

Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

Popular Articles

What is Bytes?

We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights. Get the best answers to your questions from over 220,989 network members.