adamc@116
|
1 #include <stdio.h>
|
adamc@116
|
2
|
adamc@116
|
3 #include <string.h>
|
adamc@116
|
4 #include <sys/types.h>
|
adamc@116
|
5 #include <sys/socket.h>
|
adamc@116
|
6 #include <netinet/in.h>
|
adamc@116
|
7
|
adamc@117
|
8 #include "lacweb.h"
|
adamc@117
|
9
|
adamc@116
|
10 int lw_port = 8080;
|
adamc@116
|
11 int lw_backlog = 10;
|
adamc@116
|
12 int lw_bufsize = 1024;
|
adamc@116
|
13
|
adamc@117
|
14 void lw_handle(lw_context, char*);
|
adamc@116
|
15
|
adamc@116
|
16 static void worker(int sock) {
|
adamc@116
|
17 char buf[lw_bufsize+1], *back = buf, *s;
|
adamc@116
|
18
|
adamc@116
|
19 while (1) {
|
adamc@116
|
20 int r = recv(sock, back, lw_bufsize - (back - buf), 0);
|
adamc@116
|
21
|
adamc@116
|
22 if (r < 0) {
|
adamc@116
|
23 fprintf(stderr, "Recv failed\n");
|
adamc@116
|
24 close(sock);
|
adamc@116
|
25 return;
|
adamc@116
|
26 }
|
adamc@116
|
27
|
adamc@116
|
28 if (r == 0) {
|
adamc@116
|
29 printf("Connection closed.\n");
|
adamc@116
|
30 close(sock);
|
adamc@116
|
31 return;
|
adamc@116
|
32 }
|
adamc@116
|
33
|
adamc@116
|
34 printf("Received %d bytes.\n", r);
|
adamc@116
|
35
|
adamc@116
|
36 back += r;
|
adamc@116
|
37 *back = 0;
|
adamc@116
|
38
|
adamc@116
|
39 if (s = strstr(buf, "\r\n\r\n")) {
|
adamc@116
|
40 char *cmd, *path;
|
adamc@117
|
41 lw_context ctx;
|
adamc@116
|
42
|
adamc@116
|
43 *s = 0;
|
adamc@116
|
44
|
adamc@117
|
45 if (!(s = strstr(buf, "\r\n"))) {
|
adamc@116
|
46 fprintf(stderr, "No newline in buf\n");
|
adamc@116
|
47 close(sock);
|
adamc@116
|
48 return;
|
adamc@116
|
49 }
|
adamc@116
|
50
|
adamc@116
|
51 *s = 0;
|
adamc@116
|
52 cmd = s = buf;
|
adamc@116
|
53
|
adamc@116
|
54 if (!strsep(&s, " ")) {
|
adamc@116
|
55 fprintf(stderr, "No first space in HTTP command\n");
|
adamc@116
|
56 close(sock);
|
adamc@116
|
57 return;
|
adamc@116
|
58 }
|
adamc@116
|
59
|
adamc@116
|
60 if (strcmp(cmd, "GET")) {
|
adamc@116
|
61 fprintf(stderr, "Not ready for non-get command: %s\n", cmd);
|
adamc@116
|
62 close(sock);
|
adamc@116
|
63 return;
|
adamc@116
|
64 }
|
adamc@116
|
65
|
adamc@116
|
66 path = s;
|
adamc@116
|
67 if (!strsep(&s, " ")) {
|
adamc@116
|
68 fprintf(stderr, "No second space in HTTP command\n");
|
adamc@116
|
69 close(sock);
|
adamc@116
|
70 return;
|
adamc@116
|
71 }
|
adamc@116
|
72
|
adamc@116
|
73 printf("Serving URI %s....\n", path);
|
adamc@117
|
74
|
adamc@117
|
75 ctx = lw_init(1024);
|
adamc@117
|
76 lw_write (ctx, "HTTP/1.1 200 OK\r\n");
|
adamc@117
|
77 lw_write(ctx, "Content-type: text/html\r\n\r\n");
|
adamc@117
|
78 lw_write(ctx, "<html>");
|
adamc@117
|
79 lw_handle(ctx, path);
|
adamc@117
|
80 lw_write(ctx, "</html>");
|
adamc@117
|
81
|
adamc@117
|
82 lw_send(ctx, sock);
|
adamc@116
|
83
|
adamc@116
|
84 printf("Done with client.\n\n");
|
adamc@116
|
85 close(sock);
|
adamc@116
|
86 return;
|
adamc@116
|
87 }
|
adamc@116
|
88 }
|
adamc@116
|
89 }
|
adamc@102
|
90
|
adamc@102
|
91 int main() {
|
adamc@116
|
92 // The skeleton for this function comes from Beej's sockets tutorial.
|
adamc@116
|
93 int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
|
adamc@116
|
94 struct sockaddr_in my_addr;
|
adamc@116
|
95 struct sockaddr_in their_addr; // connector's address information
|
adamc@116
|
96 int sin_size, yes = 1;
|
adamc@116
|
97
|
adamc@116
|
98 sockfd = socket(PF_INET, SOCK_STREAM, 0); // do some error checking!
|
adamc@116
|
99
|
adamc@116
|
100 if (sockfd < 0) {
|
adamc@116
|
101 fprintf(stderr, "Listener socket creation failed\n");
|
adamc@116
|
102 return 1;
|
adamc@116
|
103 }
|
adamc@116
|
104
|
adamc@116
|
105 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0) {
|
adamc@116
|
106 fprintf(stderr, "Listener socket option setting failed\n");
|
adamc@116
|
107 return 1;
|
adamc@116
|
108 }
|
adamc@116
|
109
|
adamc@116
|
110 my_addr.sin_family = AF_INET; // host byte order
|
adamc@116
|
111 my_addr.sin_port = htons(lw_port); // short, network byte order
|
adamc@116
|
112 my_addr.sin_addr.s_addr = INADDR_ANY; // auto-fill with my IP
|
adamc@116
|
113 memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero);
|
adamc@116
|
114
|
adamc@116
|
115 if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) < 0) {
|
adamc@116
|
116 fprintf(stderr, "Listener socket bind failed\n");
|
adamc@116
|
117 return 1;
|
adamc@116
|
118 }
|
adamc@116
|
119
|
adamc@116
|
120 if (listen(sockfd, lw_backlog) < 0) {
|
adamc@116
|
121 fprintf(stderr, "Socket listen failed\n");
|
adamc@116
|
122 return 1;
|
adamc@116
|
123 }
|
adamc@116
|
124
|
adamc@116
|
125 sin_size = sizeof their_addr;
|
adamc@116
|
126
|
adamc@116
|
127 printf("Listening on port %d....\n", lw_port);
|
adamc@116
|
128
|
adamc@116
|
129 while (1) {
|
adamc@116
|
130 new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
|
adamc@116
|
131
|
adamc@116
|
132 if (new_fd < 0) {
|
adamc@116
|
133 fprintf(stderr, "Socket accept failed\n");
|
adamc@116
|
134 return 1;
|
adamc@116
|
135 }
|
adamc@116
|
136
|
adamc@116
|
137 printf("Accepted connection.\n");
|
adamc@116
|
138 worker(new_fd);
|
adamc@116
|
139 }
|
adamc@102
|
140 }
|