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]

Reply via email to