UNIX Network Programming Volume 1, Third Edition [Electronic resources] : The Sockets Networking API نسخه متنی

This is a Digital Library

With over 100,000 free electronic resource in Persian, Arabic and English

UNIX Network Programming Volume 1, Third Edition [Electronic resources] : The Sockets Networking API - نسخه متنی

Addison Wesley

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید










23.7 Determining Peer and Local Address Information


Because SCTP is a multihomed protocol, different mechanisms are needed to find out what addresses are in use at both the remote as well as the local endpoints of an association. In this section, we will modify our client to receive the communication up notification. Our client will then use this notification to display the addresses of both the local and remote sides of the association. Figures 23.9 and 23.10 show the modifications to our client code. Figures 23.11 and 23.12 show the new code we add to the client.

Figure 23.9 Client set up for notifications.

sctp/sctpclient04


16 bzero(&evnts, sizeof(evnts));
17 evnts.sctp_data_io_event = 1;
18 evnts.sctp_association_event = 1;
19 Setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts));
20 sctpstr_cli(stdin, sock_fd, (SA *) &servaddr, sizeof(servaddr));


Set events and call echo function


1620 We see a slight change to our client's main routine. The client explicitly subscribes to association change notifications.

We now look at the modifications needed to sctpstr_cli so that it will use our new notification processing routine.

Figure 23.10 sctp_strcli that handles notifications.

sctp/sctp_strcli1.c


21 do {
22 len = sizeof(peeraddr);
23 rd_sz = Sctp_recvmsg(sock_fd, recvline, sizeof(recvline),
24 (SA *) &peeraddr, &len, &sri, &msg_flags);
25 if (msg_flags & MSG_NOTIFICATION)
26 check_notification(sock_fd, recvline, rd_sz);
27 } while (msg_flags & MSG_NOTIFICATION);
28 printf("From str:%d seq:%d (assoc:0x%x):",
29 sri.sinfo_stream, sri.sinfo_ssn, (u_int) sri.sinfo_assoc_id);
30 printf("%.*s", rd_sz, recvline);


Loop waiting for message


2124 Here the client sets up the address length variable and calls the receive function to get the echoed message from the server.


Check for notifications


2526 The client now checks to see if the message it just read is a notification. If it is, the client calls our notification processing routine shown in Figure 23.11.


Loop while waiting for data


27 If the message read was a notification, keep looping until we read actual data.


Display message


2830 Next, the client displays the message and goes back to the top of its processing loop, waiting for user input.

Now let's look at the new function sctp_check_notification, which will display the addresses of both endpoints when an association notification event arrives.

Figure 23.11 Process notifications.

sctp/sctp_check_notify.c


1 #include "unp.h"
2 void
3 check_notification(int sock_fd, char *recvline, int rd_len)
4 {
5 union sctp_notification *snp;
6 struct sctp_assoc_change *sac;
7 struct sockaddr_storage *sal, *sar;
8 int num_rem, num_loc;
9 snp = (union sctp_notification *) recvline;
10 if (snp->sn_header.sn_type == SCTP_ASSOC_CHANGE) {
11 sac = &snp->sn_assoc_change;
12 if ((sac->sac_state == SCTP_COMM_UP) ||
13 (sac->sac_state == SCTP_RESTART)) {
14 num_rem = sctp_getpaddrs(sock_fd, sac->sac_assoc_id, &sar);
15 printf("There are %d remote addresses and they are:\n", num_rem);
16 sctp_print_addresses(sar, num_rem);
17 sctp_freepaddrs(sar);
18 num_loc = sctp_getladdrs(sock_fd, sac->sac_assoc_id, &sal);
19 printf("There are %d local addresses and they are:\n", num_loc);
20 sctp_print_addresses(sal, num_loc);
21 sctp_freeladdrs(sal);
22 }
23 }
24 }


Check if it is notification we want


913 The function casts the receive buffer to our generic notification pointer to find the notification type. If it is the notification the function is interested in, an association change notification, it then tests if the notification is a new or restarted association (SCTP_COMM_UP or SCTP_RESTART). We ignore all other notifications.


Gather and print peer addresses


1417 We call sctp_getpaddrs to gather a list of remote addresses. We then print the number of addresses and use the address printing routine, sctp_print_addresses, shown in Figure 23.12, to display the addresses. When it finishes using the address pointer, the function calls the sctp_freepaddrs function to release the resources allocated by sctp_getpaddrs.


Gather and print local addresses


1821 We call sctp_getladdrs to gather a list of local addresses, plus print the number of addresses and the addresses themselves. After the function finishes using the addresses, it calls the sctp_freeladdrs function to release the resources allocated by sctp_getladdrs.

Finally, we look at one last new function, sctp_print_addresses, which will print a list of addresses in the form that is returned by the sctp_getpaddrs and sctp_getladdrs functions.

Figure 23.12 Print a list of addresses.

sctp/sctp_print_addrs.c


1 #include "unp.h"
2 void
3 sctp_print_addresses(struct sockaddr_storage *addrs, int num)
4 {
5 struct sockaddr_storage *ss;
6 int i, salen;
7 ss = addrs;
8 for (i = 0; i < num; i++) {
9 printf("%s\n", Sock_ntop((SA *) ss, salen));
10 #ifdef HAVE_SOCKADDR_SA_LEN
11 salen = ss->ss_len;
12 #else
13 switch (ss->ss_family) {
14 case AF_INET:
15 salen = sizeof(struct sockaddr_in);
16 break;
17 #ifdef IPV6
18 case AF_INET6:
19 salen = sizeof(struct sockaddr_in6);
20 break;
21 #endif
22 default:
23 err_quit("sctp_print_addresses: unknown AF");
24 break;
25 }
26 #endif
27 ss = (struct sockaddr_storage *) ((char *) ss + salen);
28 }
29 }


Process each address


78 The function loops through each address based on the number of addresses our caller specified.


Print address


9 We print the address using our sock_ntop function. Recall that this prints any socket address structure format the system supports.


Determine address size


1026 The list of addresses is a packed list, not a simple array of sockaddr_storage structures. This is because the sockaddr_storage structure is quite large and it is too wasteful to use in passing addresses back and forth between the kernel and user space. On systems on which the sockaddr structure contains its own length, this is trivial: just extract the length from the current sockaddr_storage structure. On other systems, we choose the length based on the address family and quit with an error if the address family is unknown.


Move address pointer


27 The function now adds the size of the address to the base pointer to move forward through the list of addresses.


Running the Code


We run our modified client against the server as follows:



FreeBSD-lap:

./sctpclient01 10.1.1.5

[0]Hi
There are 2 remote addresses and they are:
10.1.1.5:9877
127.0.0.1:9877
There are 2 local addresses and they are:
10.1.1.5:1025
127.0.0.1:1025
From str:0 seq:0 (assoc:c99e2680):[0]Hi

Control-D
FreeBSD-lap:




/ 450