Hai:
Find attached example from the draft with this change, i.e. msg_name/
msg_namelen. Kacheong pointed out that we already have a bug to relax
this restriction - bug id 6343091.
Apart from the above change, the only other change is because there
is a typo in our implementation - sctp_adaptation_event is incorrectly
spelt. I have filed bug 6536383 for this.
Let us know if you have any questions.
-venu
On Mon, 19 Mar 2007, Hai Huang wrote:
Thanks. I will try it again.
Hai Huang
Veraz Networks, Inc.
926 Rock Avernue, Suite 20
San Jose, CA 95131
USA
Tel: 408-750-9441
Cell: 510-378-9948
Fax: 408-546-0081
e-mail: [EMAIL PROTECTED]
-----Original Message-----
From: venugopal iyer [mailto:[EMAIL PROTECTED]
Sent: Monday, March 19, 2007 6:26 PM
To: Hai Huang
Cc: [email protected]
Subject: Re: [networking-discuss] Re: Sol 10 SCTP networking questions
and Issues
Hai:
On Mon, 19 Mar 2007, Hai Huang wrote:
I have tried the one-to-many code example in the draft and discovered
that the recvmsg function returns immediately with return value of 0.
What went wrong?
Sorry, I didn't look at the example carefully. I assume you are seeing
"Operation not supported .."? recvmsg() on one-to-many requires the
the msg_name in the msghdr struct to be non-null (and hence, msg_namelen
to be non-zero).
One more question: How to get the association ID as a client? Call
connect first? or call sctp_sendmsg first then using getsockopt to get
the association ID?
You can get the association id by subscribing to the
sctp_association_event.
recvmsg() after connect()/sendmsg() will get the notification after the
association is established and the id can be obtained from the
sctp_assoc_change structure.
-venu
This message posted from opensolaris.org
_______________________________________________
networking-discuss mailing list
[email protected]
#define _XPG4_2
#define __EXTENSIONS__
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/sctp.h>
#include <sys/uio.h>
#define BUFLEN 100
static void
handle_event(void *buf)
{
struct sctp_assoc_change *sac;
struct sctp_send_failed *ssf;
struct sctp_paddr_change *spc;
struct sctp_remote_error *sre;
union sctp_notification *snp;
char addrbuf[INET6_ADDRSTRLEN];
const char *ap;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
snp = buf;
switch (snp->sn_header.sn_type) {
case SCTP_ASSOC_CHANGE:
sac = &snp->sn_assoc_change;
printf("^^^ assoc_change: state=%hu, error=%hu, instr=%hu "
"outstr=%hu\n", sac->sac_state, sac->sac_error,
sac->sac_inbound_streams, sac->sac_outbound_streams);
break;
case SCTP_SEND_FAILED:
ssf = &snp->sn_send_failed;
printf("^^^ sendfailed: len=%hu err=%d\n", ssf->ssf_length,
ssf->ssf_error);
break;
case SCTP_PEER_ADDR_CHANGE:
spc = &snp->sn_paddr_change;
if (spc->spc_aaddr.ss_family == AF_INET) {
sin = (struct sockaddr_in *)&spc->spc_aaddr;
ap = inet_ntop(AF_INET, &sin->sin_addr,
addrbuf, INET6_ADDRSTRLEN);
} else {
sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr;
ap = inet_ntop(AF_INET6, &sin6->sin6_addr,
addrbuf, INET6_ADDRSTRLEN);
}
printf("^^^ intf_change: %s state=%d, error=%d\n", ap,
spc->spc_state, spc->spc_error);
break;
case SCTP_REMOTE_ERROR:
sre = &snp->sn_remote_error;
printf("^^^ remote_error: err=%hu len=%hu\n",
ntohs(sre->sre_error), ntohs(sre->sre_length));
break;
case SCTP_SHUTDOWN_EVENT:
printf("^^^ shutdown event\n");
break;
default:
printf("unknown type: %hu\n", snp->sn_header.sn_type);
break;
}
}
static void *
mysctp_recvmsg(int fd, struct msghdr *msg, void *buf, size_t *buflen,
ssize_t *nrp, size_t cmsglen)
{
ssize_t nr = 0, nnr = 0;
struct iovec iov[1];
*nrp = 0;
iov->iov_base = buf;
iov->iov_len = *buflen;
msg->msg_iov = iov;
msg->msg_iovlen = 1;
for (;;) {
#ifndef MSG_XPG4_2
#define MSG_XPG4_2 0
#endif
msg->msg_flags = MSG_XPG4_2;
msg->msg_controllen = cmsglen;
nnr = recvmsg(fd, msg, 0);
if (nnr <= 0) {
/* EOF or error */
*nrp = nr;
return (NULL);
}
nr += nnr;
if ((msg->msg_flags & MSG_EOR) != 0) {
*nrp = nr;
return (buf);
}
/* Realloc the buffer? */
if (*buflen == (size_t)nr) {
buf = realloc(buf, *buflen * 2);
if (buf == 0) {
fprintf(stderr, "out of memory\n");
exit(1);
}
*buflen *= 2;
}
/* Set the next read offset */
iov->iov_base = (char *)buf + nr;
iov->iov_len = *buflen - nr;
}
}
static void
echo(int fd, int socketModeone_to_many)
{
ssize_t nr;
struct sctp_sndrcvinfo *sri;
struct msghdr msg[1];
struct cmsghdr *cmsg;
char cbuf[sizeof (*cmsg) + sizeof (*sri)];
char *buf;
size_t buflen;
struct iovec iov[1];
size_t cmsglen = sizeof (*cmsg) + sizeof (*sri);
struct sockaddr_in6 from;
socklen_t fromlen = sizeof (struct sockaddr_in6);
/* Allocate the initial data buffer */
buflen = BUFLEN;
if (!(buf = malloc(BUFLEN))) {
fprintf(stderr, "out of memory\n");
exit(1);
}
/* Set up the msghdr structure for receiving */
memset(msg, 0, sizeof (*msg));
msg->msg_control = cbuf;
msg->msg_controllen = cmsglen;
msg->msg_flags = 0;
msg->msg_name = &from;
msg->msg_namelen = fromlen;
cmsg = (struct cmsghdr *)cbuf;
sri = (struct sctp_sndrcvinfo *)(cmsg + 1);
/* Wait for something to echo */
while (buf = mysctp_recvmsg(fd, msg, buf, &buflen, &nr, cmsglen)) {
/* Intercept notifications here */
if (msg->msg_flags & MSG_NOTIFICATION) {
handle_event(buf);
continue;
}
iov->iov_base = buf;
iov->iov_len = nr;
msg->msg_iov = iov;
msg->msg_iovlen = 1;
printf("got %u bytes on stream %hu:\n", nr, sri->sinfo_stream);
write(0, buf, nr);
/* Echo it back */
msg->msg_flags = MSG_XPG4_2;
if (sendmsg(fd, msg, 0) < 0) {
perror("sendmsg");
exit(1);
}
}
if (nr < 0) {
perror("recvmsg");
}
if(socketModeone_to_many == 0)
close(fd);
}
int main()
{
int fd;
int idleTime = 2;
struct sockaddr_in sin[1];
struct sctp_event_subscribe event;
if ((fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)) == -1) {
perror("socket");
exit(1);
}
sin->sin_family = AF_INET;
sin->sin_port = htons(7);
sin->sin_addr.s_addr = INADDR_ANY;
if (bind(fd, (struct sockaddr *)sin, sizeof (*sin)) == -1) {
perror("bind");
exit(1);
}
/* Enable all notifications and events */
event.sctp_data_io_event = 1;
event.sctp_association_event = 1;
event.sctp_address_event = 1;
event.sctp_send_failure_event = 1;
event.sctp_peer_error_event = 1;
event.sctp_shutdown_event = 1;
event.sctp_partial_delivery_event = 1;
event.sctp_adaption_layer_event = 1;
if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) !=
0) {
perror("setevent failed");
exit(1);
}
/*
* Set associations to auto-close in 2 seconds of
* inactivity
*/
if (setsockopt(fd, IPPROTO_SCTP, SCTP_AUTOCLOSE, &idleTime, 4) < 0) {
perror("setsockopt SCTP_AUTOCLOSE");
exit (1);
}
/* Allow new associations to be accepted */
if (listen(fd, 1) < 0) {
perror("listen");
exit(1);
}
/* Wait for new associations */
while(1){
/* Echo back any and all data */
echo(fd,1);
}
}
_______________________________________________
networking-discuss mailing list
[email protected]