ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/Smersh/Daemon.cpp
Revision: 175
Committed: 2004-06-25T01:10:49-07:00 (20 years, 11 months ago) by Douglas Thrift
File size: 3546 byte(s)
Log Message:
Arg, I wish it worked better.

File Contents

# Content
1 // Smersh
2 //
3 // Douglas Thrift
4 //
5 // $Id$
6
7 #include "Daemon.hpp"
8
9 string Daemon::crlf("\r\n");
10
11 void Daemon::serve(int port, bool fork, Daemon* self)
12 {
13 api::TcpSocket server;
14
15 server.Create();
16 server.SetAddress(api::InternetAddress(api::InternetAddress::Any, port));
17
18 if (fork)
19 {
20 switch (::fork())
21 {
22 case -1:
23 cerr << program << ": fork()\n";
24
25 exit(1);
26 case 0:
27 break;
28 default:
29 return;
30 }
31 }
32
33 server.Listen(50);
34
35 while (true)
36 {
37 api::TcpSocket* client(new api::TcpSocket());
38
39 server.Accept(*client);
40
41 api::Thread thread(etl::BindAll(&Daemon::handle, self, client));
42 }
43 }
44
45 Daemon::Status Daemon::request(istream& sin, Environment& env, ostream& post,
46 ostream& log)
47 {
48 string line;
49 Matcher request("^([A-Z]+) .*(\\?.+)? HTTP/(\\d+)\\.(\\d+)$");
50
51 getline(sin, line);
52
53 log << '"' << line << "\" ";
54
55 if (line == request)
56 {
57 if (lexical_cast<unsigned>(request[request.size() > 4 ? 3 : 2]) > 1)
58 return version;
59
60 Matcher matcher;
61
62 if (request[1] != matcher("^GET|HEAD|POST$")) return notImplemented;
63
64 env.set("REQUEST_METHOD", matcher[0]);
65
66 if (request.size() > 4) env.set("QUERY_STRING", request[2].substr(1));
67
68 do
69 {
70 getline(sin, line);
71
72 if (line.empty()) break;
73
74 istringstream input(line);
75 string name, value;
76
77 ::getline(input, name, ':');
78 getline(input, value);
79
80 for (char next(sin.peek()); next == ' ' || next == '\t'; next =
81 sin.peek())
82 {
83 getline(sin, line);
84
85 value += ' ' + line;
86 }
87
88 matcher("^\\s*?(.+)\\s*?$");
89
90 if (name == "Content-Length")
91 {
92 if (value == matcher) env.set("CONTENT_LENGTH", matcher[1]);
93 }
94 else if (name == "Content-Type")
95 {
96 if (value == matcher) env.set("CONTENT_TYPE", matcher[1]);
97 }
98 else if (name == "Referer")
99 {
100 if (value == matcher) env.set("HTTP_REFERER", matcher[1]);
101 }
102 else if (name == "User-Agent")
103 {
104 if (value == matcher) env.set("HTTP_USER_AGENT", matcher[1]);
105 }
106
107 cerr << name << ':' << value << '\n';
108 }
109 while (sin.good());
110
111 if (request[0] == "POST")
112 {
113 string contentLength(env.get("CONTENT_LENGTH"));
114
115 if (env.get("CONTENT_TYPE") != "application/x-www-form-urlencoded")
116 return mediaType;
117 if (contentLength.empty()) return lengthRequired;
118
119 streamsize length(lexical_cast<streamsize>(contentLength));
120 char* content(new char[length]);
121
122 sin.read(content, length);
123 post.write(content, length);
124
125 delete [] content;
126 }
127
128 return ok;
129 }
130
131 return notFound;
132 }
133
134 void Daemon::status(ostream& sout, Status status)
135 {
136 sout << "HTTP/1.1 " << status << ' ';
137
138 switch (status)
139 {
140 case ok:
141 sout << "OK";
142 break;
143 case found:
144 sout << "Found";
145 break;
146 case seeOther:
147 sout << "See Other";
148 break;
149 case bad:
150 sout << "Bad Request";
151 break;
152 case notFound:
153 sout << "Not Found";
154 break;
155 case lengthRequired:
156 sout << "Length Required";
157 break;
158 case mediaType:
159 sout << "Unsupported Media Type";
160 break;
161 case error:
162 sout << "Internal Server Error";
163 break;
164 case notImplemented:
165 sout << "Not Implemented";
166 break;
167 case version:
168 sout << "HTTP Version not supported";
169 }
170
171 sout << crlf;
172 }
173
174 int Daemon::handle(api::TcpSocket* client)
175 {
176 ios::InputOutputStreamBufAdapter adapter(*client);
177 iostream sio(&adapter);
178 Environment env;
179 stringstream post;
180 ostringstream log;
181 Status code(request(sio, env, post, log));
182
183 status(sio, code);
184
185 log << code << ' ' << 0 << " \"" << env.get("HTTP_REFERER") << "\" \""
186 << env.get("HTTP_USER_AGENT") << '"';
187
188 if (debug) cerr << "log = " << log.str() << '\n';
189
190 delete client;
191 }

Properties

Name Value
svn:eol-style native
svn:keywords Id