1 //==========================================================================
5 // Simple TCP 'server' test - using getaddrinfo()
7 //==========================================================================
8 //####BSDCOPYRIGHTBEGIN####
10 // -------------------------------------------
12 // Portions of this software may have been derived from OpenBSD or other sources,
13 // and are covered by the appropriate copyright disclaimers included herein.
15 // -------------------------------------------
17 //####BSDCOPYRIGHTEND####
18 //==========================================================================
19 //#####DESCRIPTIONBEGIN####
22 // Contributors: gthomas
28 //####DESCRIPTIONEND####
30 //==========================================================================
31 // Network server test code
36 #ifndef CYGPKG_LIBC_STDIO
37 #define perror(s) diag_printf(#s ": %s\n", strerror(errno))
40 #define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000)
41 static char stack[STACK_SIZE];
42 static cyg_thread thread_data;
43 static cyg_handle_t thread_handle;
57 server_test(struct bootp *bp)
59 int sock_indx, i, s, socks[MAXSOCK], client, client_len;
60 struct sockaddr client_addr;
61 char buf[256], addr_buf[256];
62 char host_addr_buf[256], host_port_buf[32];
64 fd_set in_fds, src_fds;
67 struct addrinfo *ai, *addrs, hints;
70 bzero(&hints, sizeof(hints));
71 hints.ai_family = PF_UNSPEC;
72 hints.ai_socktype = SOCK_STREAM;
73 hints.ai_flags = AI_PASSIVE;
74 if ((err = getaddrinfo(NULL, "7734", &hints, &addrs)) != EAI_NONE) {
75 diag_printf("can't getaddrinfo(): %s\n", gai_strerror(err));
76 pexit("getaddrinfo failed");
78 sock_indx = 0; last_sock = -1;
81 _inet_ntop(ai->ai_addr, addr_buf, sizeof(addr_buf));
82 diag_printf("Family: %d, Socket: %d, Addr: %s\n", ai->ai_family, ai->ai_socktype, addr_buf);
83 s = socket(ai->ai_family, ai->ai_socktype, 0);
85 pexit("stream socket");
87 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
88 pexit("setsockopt SO_REUSEADDR");
90 if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one))) {
91 pexit("setsockopt SO_REUSEPORT");
93 if(bind(s, ai->ai_addr, ai->ai_addr->sa_len) < 0) {
97 socks[sock_indx++] = s;
98 if (sock_indx >= MAXSOCK) {
99 pexit("Too many address types");
102 if (s > last_sock) last_sock = s;
105 // Wait for some activity on one of the ports
107 for (s = 0; s < sock_indx; s++) {
108 FD_SET(socks[s], &src_fds);
110 num = select(last_sock+1, &src_fds, 0, 0, 0);
112 // There are 'num' sockets ready to connect
113 for (i = 0; i < sock_indx; i++) {
115 if (FD_ISSET(s, &src_fds)) {
116 client_len = sizeof(client_addr);
117 if ((client = accept(s, (struct sockaddr *)&client_addr, &client_len)) < 0) {
120 client_len = sizeof(client_addr);
121 getpeername(client, &client_addr, &client_len);
122 if (getnameinfo (&client_addr, client_len,
123 host_addr_buf, sizeof(host_addr_buf),
124 host_port_buf, sizeof(host_port_buf),
125 NI_NUMERIC) == EAI_NONE) {
126 diag_printf("connection from %s(%s)\n", host_addr_buf, host_port_buf);
127 diag_sprintf(buf, "Hello %s(%s)\n", host_addr_buf, host_port_buf);
129 _inet_ntop(&client_addr, addr_buf, sizeof(addr_buf));
130 diag_printf("connection from %s(%d)\n", addr_buf, _inet_port(&client_addr));
131 diag_sprintf(buf, "Hello %s(%d)\n", addr_buf, _inet_port(&client_addr));
133 write(client, buf, strlen(buf));
137 FD_SET(client, &in_fds);
138 num = select(client+1, &in_fds, 0, 0, &tv);
140 len = read(client, buf, sizeof(buf)-1);
141 buf[len-1] = '\0'; // Trim \n
142 diag_printf("buf = '%s'\n", buf);
143 } else if (num == 0) {
144 diag_printf("No reply - timed out\n");
152 diag_printf("select returned: %d\n", num);
159 net_test(cyg_addrword_t param)
161 diag_printf("Start SERVER test\n");
162 init_all_network_interfaces();
163 #ifdef CYGHWR_NET_DRIVER_ETH0
165 server_test(ð0_bootp_data);
174 // Create a main thread, so we can run the scheduler and have time 'pass'
175 cyg_thread_create(10, // Priority - just a number
177 0, // entry parameter
178 "Network test", // Name
181 &thread_handle, // Handle
182 &thread_data // Thread data structure
184 cyg_thread_resume(thread_handle); // Start it
185 cyg_scheduler_start();