[ Team LiB ] Previous Section Next Section

23.4 Notifications

As we discussed in Section 9.14, an application can subscribe to seven notifications. Up to now, our application has ignored all events that may occur other than the receipt of new data. The examples in this section give an overview of how to receive and interpret SCTP's notifications of additional transport-layer events. Figure 23.4 shows a function that will display any notification that arrives from the transport. We will also modify our server to enable all events and call this new function when a notification is received. Note that our server is not really using the notification for any specific purpose.

Cast and switch

1415 The function casts the incoming buffer to the overall union type. It dereferences the generic sn_header structure and the generic type sn_type, and switches on this value.

Process association change

1640 If the function finds an association change notification in the buffer, it prints the type of association change that occurred.

Peer address change

4166 If it was a peer address notification, the function prints the address event (after decoding) and the address.

Remote error

6771 If the function finds a remote error, it displays this fact and the association ID on which it occurred. The function does not bother to decode and display the actual error reported by the remote peer. The information is available in the sre_data field of the sctp_remote_error structure.

Figure 23.4 A notifications display utility.

sctp/sctp_displayevents.c

 1 #include    "unp.h"

 2 void
 3 print_notification(char *notify_buf)
 4 {
 5     union sctp_notification *snp;
 6     struct sctp_assoc_change *sac;
 7     struct sctp_paddr_change *spc;
 8     struct sctp_remote_error *sre;
 9     struct sctp_send_failed *ssf;
10     struct sctp_shutdown_event *sse;
11     struct sctp_adaption_event *ae;
12     struct sctp_pdapi_event *pdapi;
13     const char *str;

14     snp = (union sctp_notification *) notify_buf;
15     switch (snp->sn_header.sn_type) {
16     case SCTP_ASSOC_CHANGE:
17        sac = &snp->sn_assoc_change;
18        switch (sac->sac_state) {
19        case SCTP_COMM_UP:
20            str = "COMMUNICATION UP";
21            break;
22        case SCTP_COMM_LOST:
23            str = "COMMUNICATION LOST";
24            break;
25        case SCTP_RESTART:
26            str = "RESTART";
27            break;
28        case SCTP_SHUTDOWN_COMP:
29            str = "SHUTDOWN COMPLETE";
30            break;
31        case SCTP_CANT_STR_ASSOC:
32            str = "CAN'T START ASSOC";
33            break;
34        default:
35            str = "UNKNOWN";
36            break;
37        }                       /* end switch(sac->sac_state) */
38        printf("SCTP_ASSOC_CHANGE: %s, assoc=0x%x\n", str,
39               (uint32_t) sac->sac_assoc_id);
40        break;
41    case SCTP_PEER_ADDR_CHANGE:
42        spc = &snp->sn_paddr_change;
43        switch (spc->spc_state) {
44        case SCTP_ADDR_AVAILABLE:
45            str = "ADDRESS AVAILABLE";
46            break;
47        case SCTP_ADDR_UNREACHABLE:
48            str = "ADDRESS UNREACHABLE";
49            break;
50        case SCTP_ADDR_REMOVED:
51            str = "ADDRESS REMOVED";
52            break;
53        case SCTP_ADDR_ADDED:
54            str = "ADDRESS ADDED";
55            break;
56        case SCTP_ADDR_MADE_PRIM:
57            str = "ADDRESS MADE PRIMARY";
58            break;
59        default:
60            str = "UNKNOWN";
61            break;
62        }                       /* end switch(spc->spc_state) */
63        printf("SCTP_PEER_ADDR_CHANGE: %s, addr=%s, assoc=0x%x\n", str,
64               Sock_ntop((SA *) &spc->spc_aaddr, sizeof(spc->spc_aaddr)),
65               (uint32_t) spc->spc_assoc_id);
66        break;
67    case SCTP_REMOTE_ERROR:
68        sre = &snp->sn_remote_error;
69        printf("SCTP_REMOTE_ERROR: assoc=0x%x error=%d\n",
70               (uint32_t) sre->sre_assoc_id, sre->sre_error);
71        break;
72    case SCTP_SEND_FAILED:
73        ssf = &snp->sn_send_failed;
74        printf("SCTP_SEND_FAILED: assoc=0x%x error=%d\n",
75               (uint32_t) ssf->ssf_assoc_id, ssf->ssf_error);
76        break;
77    case SCTP_ADAPTION_INDICATION:
78        ae = &snp->sn_adaption_event;
79        printf("SCTP_ADAPTION_INDICATION: 0x%x\n",
80               (u_int) ae->sai_adaption_ind);
81        break;
82    case SCTP_PARTIAL_DELIVERY_EVENT:
83        pdapi = &snp->sn_pdapi_event;
84        if (pdapi->pdapi_indication == SCTP_PARTIAL_DELIVERY_ABORTED)
85            printf("SCTP_PARTIAL_DELIEVERY_ABORTED\n");
86        else
87            printf("Unknown SCTP_PARTIAL_DELIVERY_EVENT 0x%x\n",
88                   pdapi->pdapi_indication);
89        break;
90    case SCTP_SHUTDOWN_EVENT:
91        sse = &snp->sn_shutdown_event;
92        printf("SCTP_SHUTDOWN_EVENT: assoc=0x%x\n",
93               (uint32_t) sse->sse_assoc_id);
94        break;
95    default:
96        printf("Unknown notification event type=0x%x\n",
97               snp->sn_header.sn_type);
98    }
99 }

Failed message

7276 If the function decodes a send failed notification, it knows that a message was not sent to the peer. This means that either: (i) the association is coming down, and an association notification will soon follow (if it has not already arrived), or (ii) the server is using the partial reliability extension and a message was not successfully sent (due to constraints placed on the transfer). The data actually sent is available to the function in the ssf_data field (which our function does not examine).

Adaption layer indication

7781 If the function decodes an adaption layer indicator, it displays the 32-bit value passed in the setup message (INIT or INIT-ACK).

Partial delivery notification

8289 If a partial delivery notification arrives, the function announces it. The only event defined as of this writing is that the partial delivery is aborted.

Shutdown notification

9094 If the function decodes this notification, it knows that the peer has issued a graceful shutdown. This notification is usually soon followed by an association change notification when the shutdown sequence completes.

The modification to the server to use our new function can be seen in Figure 23.5.

Figure 23.5 A modified server that uses notifications.

sctp/sctpserv06.c

21     bzero(&evnts, sizeof(evnts));
22     evnts.sctp_data_io_event = 1;
23     evnts.sctp_association_event = 1;
24     evnts.sctp_address_event = 1;
25     evnts.sctp_send_failure_event = 1;
26     evnts.sctp_peer_error_event = 1;
27     evnts.sctp_shutdown_event = 1;
28     evnts.sctp_partial_delivery_event = 1;
29     evnts.sctp_adaption_layer_event = 1;
30     Setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts));

31     Listen(sock_fd, LISTENQ);
32     for ( ; ; ) {
33         len = sizeof(struct sockaddr_in);
34         rd_sz = Sctp_recvmsg(sock_fd, readbuf, sizeof(readbuf),
35                              (SA *) &cliaddr, &len, &sri, &msg_flags);
36         if (msg_flags & MSG_NOTIFICATION) {
37             print_notification(readbuf);
38             continue;
39         }

Set up to receive notifications

2130 Here the server changes the event settings so that it will receive all notifications.

Normal receive code

3135 This section of server code is unchanged.

Handle notification

3639 Here the server checks the msg_flags field. If the server finds that the data is a notification, it calls our display function sctp_print_notification and loops around to read the next message.

Running the Code

We start the client and send one message as follows:


     FreeBSD-lap: ./sctpclient01 10.1.1.5
     [0] Hello
     From str:1 seq:0 (assoc:c99e15a0) : [0] Hello
     Control-D
     FreeBSD-lap:

When receiving the connection, message, and connection termination, our modified server displays each event as it occurs.


     FreeBSD-lap: ./sctpserv06
     SCTP_ADAPTION_INDICATION: 0x504c5253
     SCTP_ASSOC_CHANGE: COMMUNICATION UP, assoc=c99e2680h
     SCTP_SHUTDOWN_EVENT: assoc=c99e2680h
     SCTP_ASSOC_CHANGE: SHUTDOWN COMPLETE, assoc=c99e2680h
     Control-C

As you can see, the server now announces the events as they occur on the transport.

    [ Team LiB ] Previous Section Next Section