1 | #include <stdio.h> |
---|
2 | #include <sys/file.h> |
---|
3 | #include <sys/types.h> |
---|
4 | #ifdef __Lynx__ |
---|
5 | #include <socket.h> |
---|
6 | #else |
---|
7 | #include <sys/socket.h> |
---|
8 | #endif |
---|
9 | #include <net/if.h> |
---|
10 | #include <sys/ioctl.h> |
---|
11 | #include <netinet/in.h> |
---|
12 | #include <arpa/inet.h> |
---|
13 | #include <netdb.h> |
---|
14 | #include <errno.h> |
---|
15 | #include <stdlib.h> |
---|
16 | #include <inttypes.h> |
---|
17 | #include <string.h> |
---|
18 | |
---|
19 | |
---|
20 | #include "mcast_params.h" |
---|
21 | |
---|
22 | #define ROUTERS_TO_HOP 10 // Keep my traffic in the same subnet |
---|
23 | |
---|
24 | |
---|
25 | static struct sockaddr_in addr; |
---|
26 | static int so; |
---|
27 | static char mhost[100]; |
---|
28 | static unsigned long hostaddr; |
---|
29 | |
---|
30 | int msend(char *buf, int num) |
---|
31 | { |
---|
32 | bzero(&addr, sizeof(addr)); |
---|
33 | addr.sin_family = AF_INET; |
---|
34 | addr.sin_port = htons((u_short)MCAST_PORT); |
---|
35 | addr.sin_addr.s_addr = inet_addr(MCAST_ADDR); |
---|
36 | if (sendto(so, buf, num, 0, (struct sockaddr *)&addr, sizeof(addr)) < 0) { |
---|
37 | if (errno != EAGAIN) |
---|
38 | perror("sendto"); |
---|
39 | return 0; |
---|
40 | } |
---|
41 | return 1; |
---|
42 | } |
---|
43 | |
---|
44 | |
---|
45 | int mrecv(char *buf, int num) |
---|
46 | { |
---|
47 | socklen_t i; |
---|
48 | int n; |
---|
49 | |
---|
50 | bzero(&addr, sizeof(addr)); |
---|
51 | addr.sin_family = AF_INET; |
---|
52 | addr.sin_port = htons((u_short)MCAST_PORT); |
---|
53 | addr.sin_addr.s_addr = inet_addr(MCAST_ADDR); |
---|
54 | |
---|
55 | |
---|
56 | i = sizeof(addr); |
---|
57 | if ((n = recvfrom(so, buf, num, 0, (struct sockaddr *)&addr, &i)) == -1) { |
---|
58 | if (errno != EAGAIN) |
---|
59 | perror("recvfrom"); |
---|
60 | return 0; |
---|
61 | } |
---|
62 | return n; |
---|
63 | } |
---|
64 | |
---|
65 | |
---|
66 | #if defined(__rtems__) |
---|
67 | int mcast_main(int ac, char **av) |
---|
68 | #else |
---|
69 | int main(int ac, char **av) |
---|
70 | #endif |
---|
71 | { |
---|
72 | int yes=1; |
---|
73 | char line[1024]; |
---|
74 | struct ip_mreq imr; |
---|
75 | struct hostent *h; |
---|
76 | unsigned char mttl; |
---|
77 | int mlen; |
---|
78 | unsigned long long i, j, k; |
---|
79 | |
---|
80 | |
---|
81 | if (ac > 1) mlen = atoi(av[1]); |
---|
82 | else mlen = 0; |
---|
83 | |
---|
84 | if ((gethostname(mhost, 100) < 0)) { // Get the my hostname |
---|
85 | perror("gethostname"); |
---|
86 | exit(1); |
---|
87 | } |
---|
88 | printf( "Hostname: %s\n", ((mhost) ? mhost : "NULL") ); |
---|
89 | if (!(h = gethostbyname(mhost))) { // Get host entry |
---|
90 | perror("gethostbyname"); |
---|
91 | exit(1); |
---|
92 | } |
---|
93 | |
---|
94 | printf( "host=0x%08x\n", *(unsigned int *)h->h_addr ); |
---|
95 | |
---|
96 | |
---|
97 | printf( "Creating socket\n" ); |
---|
98 | if ((so = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { |
---|
99 | perror("socket"); |
---|
100 | exit(1); |
---|
101 | } |
---|
102 | |
---|
103 | printf( "Setting SO_REUSEADDR\n" ); |
---|
104 | if (setsockopt(so, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { |
---|
105 | perror("setsockopt, reuse"); |
---|
106 | exit(1); |
---|
107 | } |
---|
108 | |
---|
109 | printf( "Binding\n" ); |
---|
110 | // Bind to port and address. |
---|
111 | bzero(&addr, sizeof(addr)); |
---|
112 | addr.sin_family = AF_INET; |
---|
113 | addr.sin_port = htons((u_short)MCAST_PORT); |
---|
114 | addr.sin_addr.s_addr = INADDR_ANY; |
---|
115 | if (bind(so, (struct sockaddr *)&addr, sizeof(addr)) < 0) { |
---|
116 | perror("bind"); |
---|
117 | exit(1); |
---|
118 | } |
---|
119 | |
---|
120 | printf( "Performing IP_MULTICAST_TTL\n" ); |
---|
121 | mttl = ROUTERS_TO_HOP + 1; // ttl should be atleast one. |
---|
122 | if (setsockopt(so, IPPROTO_IP, IP_MULTICAST_TTL, &mttl, sizeof(mttl)) < 0) { |
---|
123 | perror("setsockopt, ttl" ); |
---|
124 | exit(1); |
---|
125 | } |
---|
126 | hostaddr = *(unsigned int *)h->h_addr; |
---|
127 | imr.imr_interface.s_addr = htonl(INADDR_ANY); |
---|
128 | // For some reason, this doesn't seem to work. I suspect it is because |
---|
129 | // the /etc/hosts included with this demo must match the IP of the |
---|
130 | // network interface you want to use. I couldn't get this to work |
---|
131 | // so gave up. INADDR_ANY seems to reliably find the NIC. --joel |
---|
132 | // imr.imr_interface.s_addr = hostaddr; |
---|
133 | imr.imr_multiaddr.s_addr = inet_addr(MCAST_ADDR); |
---|
134 | |
---|
135 | printf( "Performing IP_ADD_MEMBERSHIP\n" ); |
---|
136 | if (setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr)) < 0) { |
---|
137 | perror( "can't join group" ); |
---|
138 | close(so); |
---|
139 | exit(1); |
---|
140 | } |
---|
141 | |
---|
142 | fcntl(so, F_SETFL, FNDELAY); |
---|
143 | j = k = 0; |
---|
144 | for(i = 1; 1; i++) { |
---|
145 | int x; |
---|
146 | if (i == 0) j++; |
---|
147 | if (j == 0) k++; |
---|
148 | sleep(1); |
---|
149 | sprintf(line, |
---|
150 | "%s i %" PRId64 ", j %" PRId64 ", k %" PRId64 "", mhost, i, j, k); |
---|
151 | msend(line, strlen(line)+ mlen); |
---|
152 | while ((x = mrecv(line, 500)) > 0) { |
---|
153 | if (addr.sin_addr.s_addr != hostaddr) { |
---|
154 | line[x] = 0; |
---|
155 | printf("Raddr %s recv %s\n", inet_ntoa(addr.sin_addr), line); |
---|
156 | } |
---|
157 | } |
---|
158 | } |
---|
159 | } |
---|