ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/Smersh/Daemon.cpp
(Generate patch)

Comparing Smersh/Daemon.cpp (file contents):
Revision 173 by Douglas Thrift, 2004-06-21T03:15:47-07:00 vs.
Revision 175 by Douglas Thrift, 2004-06-25T01:10:49-07:00

# Line 6 | Line 6
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 <        // bind
13 >        api::TcpSocket server;
14 >
15 >        server.Create();
16 >        server.SetAddress(api::InternetAddress(api::InternetAddress::Any, port));
17  
18          if (fork)
19          {
# Line 25 | Line 30 | void Daemon::serve(int port, bool fork,
30                  }
31          }
32  
33 <        // listen
33 >        server.Listen(50);
34  
35          while (true)
36          {
37 <                // accept
37 >                api::TcpSocket* client(new api::TcpSocket());
38 >
39 >                server.Accept(*client);
40  
41 <                self->handle(); // thread
41 >                api::Thread thread(etl::BindAll(&Daemon::handle, self, client));
42          }
43   }
44  
45 < int Daemon::handle()
45 > Daemon::Status Daemon::request(istream& sin, Environment& env, ostream& post,
46 >        ostream& log)
47   {
48 <        //
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   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines