SCTP Discussions

Text archives Help


Re: [SCTP-Discussion] Problem trying to use multi-stream


Chronological Thread 
  • From: Thomas Dreibholz <dreibh AT exp-math.uni-essen.de>
  • To: "Oon Heok Kee" <oonheokkee78 AT hotmail.com>, discussion AT sctp.de
  • Subject: Re: [SCTP-Discussion] Problem trying to use multi-stream
  • Date: Fri Aug 30 11:52:00 2002
  • List-id: SCTP Discussions <discussion.sctp.de>
  • Organization: University of Essen, Institute for Experimental Mathematics

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Am Freitag, 30. August 2002 08:04 schrieb Oon Heok Kee:
> Hi,
>
> Thanks to Thomas, there is now some results with the multi-stream
> function in my small program. But something weird is happening, because
> after doing the modifications that Thomas suggested, I need to comment off
> the whole part that initialises the sctp_initmsg struct, otherwise I'll get
> a segmentation fault. When it's commented away, there is then 59115
> outbound and 41317 inbound streams initialised. (I checked this on
> Ethereal.) Can anyone please tell me what's wrong?

You have to use malloc() to allocate memory for your sctp_initmsg structure.
In the source code below, the pointer sim points to a random value. When you
try to set a value of this structure, you will get a segmentation fault. If
commented out, your system seems to read random values from somewhere. In
your case 59115 outbound and 41317 inbound streams.

A very useful tool for debugging such and many other memory-releated problems
is the Open Source memory debugger Valgrind:
http://developer.kde.org/~sewardj/

Simplest solution to the sctp_initmsg problem: Do not use a pointer, create
the strucure directly on the stack. Then, it will be automatically removed
when the function (main() in this case) is complete, making a free() call
unnecessary.

Example:
struct sctp_initmsg sim;
...
sim.sinit_num_ostreams = OUTSTREAM;
sim.sinit_max_instreams = INSTREAM;
sim.sinit_max_attempts = 3;
sim.sinit_max_init_timeo = 30;
if(ext_setsockopt(sock, IPPROTO_SCTP, SCTP_INITMSG, &sim, sizeof(sim)) < 0) {
...
Now, take care to use &sim and sizeof(sim) instead of sim and sizeof(*sim)
for the ext_setsockopt call.


> Just to confirm the optname parameter in ext_setsockopt(), should it be
> SCTP_INIT, or SCTP_INITMSG?

SCTP_INITMSG.


> I have attached the modified code below so that it might be clearer for
> everyone. Thanks a million!!! :)
>
>
> Oon, Heok Kee
> National University of Singapore
>
> *********************************************************************
> /* Echo Client Example */
>
> /* SCTP client */
>
> /* Compile this file with "gcc -o sctp_client sctp_client.c -Wall
> -lsctpsocket -lsctp -lglib -lstdc++ -lpthread". */
>
> #include <stdio.h> /* for printf() and fprintf() */
> #include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
> #include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
> #include <stdlib.h> /* for atoi() */
> #include <string.h> /* for memset() */
> #include <unistd.h> /* for close() */
> #include <sys/types.h>
> #include <sys/time.h>
> #include <ext_socket.h>
> #include <net/route.h>
> #include <net/if.h>
> #include <netinet/in.h>
> #include <sctp.h>
>
> #define RCVBUFSIZE 16 /* Size of receive buffer */
> #define OUTSTREAM 3 /* Number of out-bound streams */
> #define INSTREAM 2 /* Number of in-bound streams */
>
>
> void DieWithError(char *errorMessage)
> {
> perror(errorMessage);
> exit(1);
> }
>
>
> int main(int argc, char *argv[])
> {
> int sock; /* Socket descriptor */
> struct sockaddr_in echoServAddr;/* Echo server address */
> unsigned short echoServPort; /* Echo server port */
> char *servIP; /* Server IP address (dotted quad) */
> char *echoString; /* String to send to echo server */
> char echoBuffer[RCVBUFSIZE]; /* Buffer for echo string */
> unsigned int echoStringLen; /* Length of string to echo */
> int bytesRcvd, totalBytesRcvd; /* Bytes read in single recv() and
> total bytes read */
> ssize_t nr;
> struct sctp_initmsg *sim;
> struct sctp_sndrcvinfo *sinfo;
> struct msghdr msg[1];
> struct cmsghdr *cmsg;
> struct iovec iov[1];
> char cbuf[sizeof(*cmsg) + sizeof(*sinfo)];
> char *testbuf;
>
> /* Test for correct number of arguments */
> if ((argc < 3) || (argc > 4))
> {
> fprintf(stderr, "Usage: %s <Server IP> <Echo Word> [<Echo
> Port>]\n", argv[0]);
> exit(1);
> }
>
> servIP = argv[1]; /* First arg: server IP address (dotted quad) */
>
> echoString = argv[2]; /* Second arg: string to echo */
>
> if (argc == 4)
> echoServPort = atoi(argv[3]); /* Use given port, if any */
> else
> /* 7 is the well-known port for the echo service */
> echoServPort = 7;
>
> printf("\nCreating socket... ");
> /* Create a reliable, stream socket using TCP */
> if ((sock = ext_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) < 0)
> {
> DieWithError("socket() failed");
> exit(1);
> }
> printf("Socket created.\n\n");
>
> /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
>
> sim->sinit_num_ostreams = OUTSTREAM;
> sim->sinit_max_instreams = INSTREAM;
> sim->sinit_max_attempts = 3;
> sim->sinit_max_init_timeo = 30;
>
>
>
> /* Setting socket options */
> if (ext_setsockopt(sock, IPPROTO_SCTP, SCTP_INITMSG, sim,
> sizeof(*sim)) < 0)
> {
> DieWithError("setsockopt() failed");
> exit(1);
> }
>
>
> /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
>
>
> memset(msg, 0, sizeof(*msg));
> msg->msg_control = cbuf;
> msg->msg_controllen = sizeof(struct cmsghdr) + sizeof(struct
> sctp_sndrcvinfo);
> msg->msg_flags = 0;
>
> iov->iov_base = testbuf;
> iov->iov_len = nr;
>
> msg->msg_iov = iov;
> msg->msg_iovlen = 1;
>
> cmsg = (struct cmsghdr *)cbuf;
> sinfo = (struct sctp_sndrcvinfo *)(cmsg + 1);
>
> cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(struct
> sctp_sndrcvinfo);
> cmsg->cmsg_level = IPPROTO_SCTP;
> cmsg->cmsg_type = SCTP_INITMSG;
>
> sinfo->sinfo_assoc_id = 0;
> sinfo->sinfo_stream = 0; /* streamNumber */
> sinfo->sinfo_flags = 0;
> sinfo->sinfo_ppid = 0; /* ppid */
> sinfo->sinfo_context = (uint32_t)NULL;
> sinfo->sinfo_timetolive = (unsigned int)-1;
>
> /* Construct the server address structure */
> /* Zero out structure */
> memset(&echoServAddr, 0, sizeof(echoServAddr));
>
> echoServAddr.sin_family = AF_INET; /* Internet address family */
>
> /* Server IP address */
> echoServAddr.sin_addr.s_addr = inet_addr(servIP);
>
> echoServAddr.sin_port = htons(echoServPort); /* Server port */
>
> printf("Connecting to server at %s:%u ... ", servIP, echoServPort);
> /* Establish the connection to the echo server */
> if (ext_connect(sock, (struct sockaddr *) &echoServAddr,
> sizeof(echoServAddr)) < 0)
> DieWithError("connect() failed");
> printf("Connected.\n\n");
>
> echoStringLen = strlen(echoString); /* Determine input length */
>
> printf("Sending message \"%s\" to server... ", echoString);
> /* Send the string to the server */
> if (ext_sendmsg(sock, msg, MSG_UNORDERED))
> DieWithError("send() sent a diff. num. of bytes than
> expected");
> printf("Message sent.\n\n");
>
> /* Receive the same string back from the server */
> totalBytesRcvd = 0;
>
> printf("Receiving echo from server... ");
> printf("Received: "); /* Setup to print the echoed string */
>
> while (totalBytesRcvd < echoStringLen)
> {
> /* Receive up to the buffer size (minus 1 to leave space
> for a null terminator) bytes from the sender */
> if ((bytesRcvd = ext_recv(sock, echoBuffer, RCVBUFSIZE - 1,
> 0)) <= 0)
> DieWithError("recv() failed or conn. closed
> prematurely");
>
> totalBytesRcvd += bytesRcvd; /* Keep tally of total bytes
> */
>
> echoBuffer[bytesRcvd] = '\0'; /* Terminate the string! */
>
> printf(echoBuffer); /* Print the echo buffer */
> }
>
> printf("\n\n"); /* Print a final linefeed */
>
> ext_close(sock);
>
> exit(0);
> }
>
>
> ***************************************************************************
>*
>
>
>
> ----Original Message Follows----
> From: Thomas Dreibholz
> <dreibh AT exp-math.uni-essen.de>
> To: "Oon Heok Kee"
> <oonheokkee78 AT hotmail.com>,
>
> discussion AT sctp.de
> Subject: Re: [SCTP-Discussion] Problem trying to use multi-stream
> Date: Thu, 29 Aug 2002 15:15:55 +0200
>
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Am Donnerstag, 29. August 2002 14:18 schrieb Oon Heok Kee:
> > Hi,
> >
> > I'm trying to write an echo program using TCP-style sockets in C and
> > getting the program to use multi-stream instead of the default single
> > stream. Problem is, I've read <draft-ietf-tsvwg-sctpsocket-04.txt> about
>
> 5
>
> > times over, gone through sctpterminal.cc and sctpmultiserver.cc
> > examples, and I still don't understand how to initiate a multi-stream
> > socket.
> >
> > I've been trying at it for the past week but with no results, which
> > is why I'm attaching my codes below, hoping that someone can point out
>
> what's
>
> > wrong. My problem primary lies at the spot marked by "%%%". I don't know
> > how to use sendmsg() because of all the struct msghdr and cmsghdr stated
>
> in
>
> > the draft and initiating it.
>
> You can see socket_programs/idexampletcp.c and
> socket_programs/idexampleudp.c
> for a running example of the ext_recvmsg() case. These are the sources of
> the
> examples in the draft.
>
> The ext_sendmsg() case is quite similar:
>
> /* Set up the msghdr structure for receiving */
> memset(msg, 0, sizeof (*msg));
> msg->msg_control = cbuf;
> msg->msg_controllen = sizeof(struct cmsghdr) + sizeof(struct
> sctp_sndrcvinfo);
>
> msg_control contains a buffer with control information for the send call.
> In our case, we only have to write sctp_sndrcvinfo and a cmsghdr header
> into this buffer (see below).
>
> msg->msg_flags = 0;
>
> No flags.
>
> iov->iov_base = buf;
> iov->iov_len = nr;
> msg->msg_iov = iov;
> msg->msg_iovlen = 1;
>
> You can specify multiple buffers of user data to send by one send call as a
> single chunk. The data will be concatenated to the chunk in sequential
> order.
> In our case, we only have one buffer "buf" with "nr" bytes. Therefore, the
> array iov has only one entry: (buf, nr). msg->msg_iov gets the pointer to
> this array, the number of entries is 1.
>
> cmsg = (struct cmsghdr *)cbuf;
> sinfo = (struct sctp_sndrcvinfo *)(cmsg + 1);
>
> The control buffer now must contain a header for each control structure
> (only
> sctp_sendrcvinfo in our case). In the C++ examples, this is realized by the
> method addHeaderFirst() of the SocketMessage template:
>
> cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(struct
> sctp_sndrcvinfo);
> cmsg->cmsg_level = IPPROTO_SCTP;
> cmsg->cmsg_type = SCTP_INITMSG;
>
> Now, we can set the sctp_sndrcvinfo data:
>
> sinfo->sinfo_assoc_id = 0;
> sinfo->sinfo_stream = streamNumber;
> sinfo->sinfo_flags = 0;
> sinfo->sinfo_ppid = ppid;
> sinfo->sinfo_context = NULL;
> sinfo->sinfo_timetolive = (unsigned int)-1;
>
> > Perhaps someone can also point out some of the important points that
> > I should note when coding the echo server program.
>
> There is an error in:
> "if (ext_setsockopt(IPPROTO_SCTP, SCTP_INITMSG, sim, sizeof(*sim)) > 0)"
> ext_setsockopt() has 5, not 4 parameters. You must give the socket FD as
> first parameter; the same as you have to do for setsockopt(). Try
> "if (ext_setsockopt(sock,IPPROTO_SCTP, SCTP_INITMSG, sim, sizeof(*sim)) >
> 0)"
> and setting the stream parameters should work.
> Normally, your C compiler should at least print out a warning when it is
> tried to use a function with too few parameters or wrong datatypes given.
> Recommendation: Turn on all warnings; for gcc, the option -Wall does this.
>
>
> _________________________________________________________________
> Send and receive Hotmail on your mobile device: http://mobile.msn.com
>
> _______________________________________________
> discussion mailing list
> discussion AT sctp.de
> http://www.sctp.de/mailman/listinfo/discussion


Best regards
- --
=======================================================================
Dipl.-Inform. Thomas Dreibholz

University of Essen, Room ES210
Inst. for Experimental Mathematics Ellernstraße 29
Computer Networking Technology Group D-45326 Essen/Germany
- -----------------------------------------------------------------------
E-Mail:
dreibh AT exp-math.uni-essen.de
Homepage: http://www.exp-math.uni-essen.de/~dreibh
=======================================================================
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQE9b0JU32BbsHYPLWURAmo5AKCiEVnqKbGWWm6RYBxbDrXsOL70WQCglo33
/UGqR53ub56cjjLq06Swa3k=
=XKJT
-----END PGP SIGNATURE-----




Archive powered by MHonArc 2.6.19+.

Top of page