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

# User Rev Content
1 Douglas Thrift 164 // Smersh
2     //
3     // Douglas Thrift
4     //
5     // $Id$
6    
7     #include "Daemon.hpp"
8    
9 Douglas Thrift 175 string Daemon::crlf("\r\n");
10    
11 Douglas Thrift 173 void Daemon::serve(int port, bool fork, Daemon* self)
12 Douglas Thrift 164 {
13 Douglas Thrift 174 api::TcpSocket server;
14 Douglas Thrift 172
15 Douglas Thrift 174 server.Create();
16     server.SetAddress(api::InternetAddress(api::InternetAddress::Any, port));
17    
18 Douglas Thrift 172 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 Douglas Thrift 174 server.Listen(50);
34 Douglas Thrift 173
35     while (true)
36     {
37 Douglas Thrift 174 api::TcpSocket* client(new api::TcpSocket());
38 Douglas Thrift 173
39 Douglas Thrift 174 server.Accept(*client);
40    
41     api::Thread thread(etl::BindAll(&Daemon::handle, self, client));
42 Douglas Thrift 173 }
43 Douglas Thrift 164 }
44    
45 Douglas Thrift 175 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 Douglas Thrift 174 int Daemon::handle(api::TcpSocket* client)
175 Douglas Thrift 164 {
176 Douglas Thrift 174 ios::InputOutputStreamBufAdapter adapter(*client);
177 Douglas Thrift 175 iostream sio(&adapter);
178     Environment env;
179     stringstream post;
180     ostringstream log;
181     Status code(request(sio, env, post, log));
182 Douglas Thrift 174
183 Douglas Thrift 175 status(sio, code);
184 Douglas Thrift 174
185 Douglas Thrift 175 log << code << ' ' << 0 << " \"" << env.get("HTTP_REFERER") << "\" \""
186     << env.get("HTTP_USER_AGENT") << '"';
187    
188     if (debug) cerr << "log = " << log.str() << '\n';
189    
190 Douglas Thrift 174 delete client;
191 Douglas Thrift 164 }

Properties

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