3 /* linker: color.o debug.o */
8 #ifdef _WIN32 /* Windows */
15 #include <netinet/ip.h>
16 #include <netinet/tcp.h>
17 #include <sys/types.h>
18 #include <sys/socket.h>
25 #ifdef _WIN32 /* Windows */
26 typedef SOCKET socket_t
;
33 #define BUFFER_SIZE 4096
39 char *progname
= NULL
;
46 FILE *fid
= ret
? stderr
: stdout
;
47 fprintf (fid
, "usage: %s\n", progname
);
48 fprintf (fid
, " -h : help message\n");
49 fprintf (fid
, " -p : port number (%d)\n", port
);
50 fprintf (fid
, " -v : verbose level (%d)\n", verbose
);
55 /* open listening socket */
57 socket_t
open_listening_socket (int port
)
59 #ifdef _WIN32 /* Windows */
61 WSAStartup (MAKEWORD(2,0), &WSAData
);
62 assert (INVALID_SOCKET
== (socket_t
)-1);
65 VERBOSE (DEBUG
, fprintf (stdout
, "Opening socket\n"));
66 #ifdef _WIN32 /* Windows */
67 socket_t sock
= socket (AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
68 if (sock
== INVALID_SOCKET
)
71 socket_t sock
= socket (PF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
76 struct sockaddr_in addr
= {0};
77 #ifdef _WIN32 /* Windows */
78 addr
.sin_family
= AF_INET
;
80 addr
.sin_family
= PF_INET
;
82 addr
.sin_port
= htons (port
);
83 addr
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
85 VERBOSE (DEBUG
, fprintf (stdout
, "Binding socket\n"));
86 int rc
= bind (sock
, (struct sockaddr
*)&addr
, sizeof (addr
));
87 #ifdef _WIN32 /* Windows */
88 if (rc
== SOCKET_ERROR
) {
89 VERBOSE (ERROR
, fprintf (stderr
, "error: %d\n", WSAGetLastError ()));
90 if (closesocket (sock
) == SOCKET_ERROR
) {
91 VERBOSE (ERROR
, fprintf (stderr
, "error: %d\n", WSAGetLastError ()));
95 VERBOSE (ERROR
, fprintf (stderr
, "error: %d\n", errno
));
101 VERBOSE (DEBUG
, fprintf (stdout
, "Configuring socket\n"));
102 #ifdef _WIN32 /* Windows */
104 fcntl (sock
, F_SETFL
, O_NONBLOCK
);
107 rc
= setsockopt (sock
, IPPROTO_TCP
, TCP_NODELAY
, (char *)&val
, sizeof (val
));
109 VERBOSE (ERROR
, fprintf (stderr
, "%s\n", "setsockopt/TCP_NODELAY"));
110 #ifdef _WIN32 /* Windows */
121 /* close listening socket */
122 void close_listening_socket (socket_t sock
)
124 #ifdef _WIN32 /* Windows */
134 int main (int argc
, char *argv
[])
142 while (progname
[i
] != '\0') {
143 if ((progname
[i
] == '/') || (progname
[i
] == '\\')) {
151 /* argument processing */
154 char *arg
= *(++argv
);
156 VERBOSE (ERROR
, fprintf (stderr
, "%s: invalid option -- '%s'\n", progname
, arg
); usage (1));
162 arg
= (arg
[2]) ? arg
+ 2 : (--argc
> 0) ? *(++argv
) : NULL
;
164 VERBOSE (ERROR
, fprintf (stderr
, "%s: missing port number\n", progname
); usage (1));
169 VERBOSE (ERROR
, fprintf (stderr
, "%s: incorrect port number (%s)\n", progname
, arg
); usage (1));
174 arg
= (arg
[2]) ? arg
+ 2 : (--argc
> 0) ? *(++argv
) : NULL
;
176 VERBOSE (ERROR
, fprintf (stderr
, "%s: missing verbose level\n", progname
); usage (1));
179 verbose
= atoi (arg
);
183 return usage (c
!= 'h');
187 VERBOSE (DEBUG
, fprintf (stdout
, "Initializing socket\n"));
188 socket_t sock
= open_listening_socket (port
);
189 if (sock
== (socket_t
)-1) {
190 VERBOSE (ERROR
, fprintf (stderr
, "Can't open listening socket\n"));
194 VERBOSE (INFO
, fprintf (stdout
, "Listening socket on port %d\n", port
));
197 VERBOSE (DEBUG
, fprintf (stdout
, "Closing socket\n"));
198 close_listening_socket (sock
);
203 // test: webserver.exe -h
204 // test: webserver.exe -h | awk '/usage:/ { rc=1 } END { exit (1-rc) }'
205 // test: webserver.exe -_ 2> /dev/null | wc -l | xargs test 0 =
206 // test: webserver.exe -_ 2>&1 | awk '/usage:/ { rc=1 } END { exit (1-rc) }'
207 // test: webserver.exe error 2>&1 | grep -q 'invalid option'
208 // test: webserver.exe -v 2>&1 | grep -q 'missing verbose level'
209 // test: webserver.exe -p 2>&1 | grep -q 'missing port number'
210 // test: webserver.exe -p -1 2>&1 | grep -q 'incorrect port number'
211 // test: webserver.exe | grep -q 'Listening socket on port 8080'
212 // test: webserver.exe -p 8000 | grep -q 'Listening socket on port 8000'
214 /* vim: set ts=4 sw=4 et: */