00001 #include <signal.h>
00002 #include "sstuff.hh"
00003 #include <vector>
00004 #include "mtasker.hh"
00005 #include "misc.hh"
00006
00007
00009 struct WSEvent
00010 {
00011 enum {Read,Write} what;
00012 Socket *who;
00013 };
00014
00015
00016 bool operator<(const WSEvent &a, const WSEvent &b)
00017 {
00018 if(a.what<b.what)
00019 return true;
00020 if(a.what>b.what)
00021 return false;
00022
00023 if(a.who<b.who)
00024 return true;
00025 return false;
00026 }
00027
00028
00029 MTasker<WSEvent> MT;
00030
00031
00033 class BufferedIO
00034 {
00035 public:
00036 BufferedIO(Socket *sock)
00037 {
00038 d_buffer=new char[1024];
00039 d_socket=sock;
00040 d_pos=d_available=0;
00041 }
00042 ~BufferedIO()
00043 {
00044 delete[] d_buffer;
00045 }
00046 void writeLine(const string &line)
00047 {
00048 write(line.c_str(),line.size());
00049 }
00050 void write(const char *buf, unsigned int toWrite)
00051 {
00052 int written=0;
00053 int res=0;
00054 WSEvent ws;
00055 ws.who=d_socket;
00056 ws.what=WSEvent::Write;
00057
00058 do {
00059 res=d_socket->tryWrite(buf+written,toWrite);
00060 if(!res) {
00061 MT.waitEvent(ws);
00062 continue;
00063 }
00064
00065 written+=res;
00066 toWrite-=res;
00067 }while(toWrite);
00068 }
00069
00070 int getchar()
00071 {
00072 if(d_pos==d_available) {
00073
00074
00075 WSEvent ws;
00076 ws.who=d_socket;
00077 ws.what=WSEvent::Read;
00078 if(!MT.waitEvent(ws,0,5))
00079 throw NetworkError("Timeout!");
00080
00081 int res=d_socket->read(d_buffer,1024);
00082 if(!res)
00083 return -1;
00084 d_available=res;
00085 d_pos=0;
00086 }
00087
00088 return d_buffer[d_pos++];
00089 }
00090
00091 void readLine(string &line)
00092 {
00093 line.clear();
00094 int c;
00095 for(;;) {
00096 c=getchar();
00097 if(c==-1)
00098 break;
00099 line.append(1,(char)c);
00100 if(c=='\n')
00101 break;
00102 }
00103 }
00104
00105 private:
00106 char *d_buffer;
00107 Socket *d_socket;
00108 size_t d_pos, d_available;
00109 };
00110
00111
00112
00113
00114 void connection(void *p)
00115 {
00116 Socket *client=(Socket *)p;
00117 int chunksize=65000;
00118
00119 vector<string> words;
00120 BufferedIO bio(client);
00121
00122 try {
00123 string line;
00124 bio.readLine(line);
00125 stringtok(words,line," \t\r\n");
00126 if(words.size()<2) {
00127 cerr<<"Malformed GET line"<<endl;
00128 delete client;
00129 return;
00130 }
00131 string fname=words[1];
00132 if(fname=="/" || fname.find("../")!=string::npos)
00133 fname="index.html";
00134
00135 cout<<"["<<MT.getTid()<<"] Request for file '"<<fname<<"'"; cout.flush();
00136
00137 do {
00138 bio.readLine(line);
00139 }while(line!="\r\n");
00140
00141 FILE *fp=fopen(("./"+fname).c_str(),"r");
00142 if(!fp) {
00143 cout<<". Sending 404, not there"<<endl;
00144 bio.writeLine("HTTP/1.1 404 OK\r\n"
00145 "Server: MTasker\r\n"
00146 "Connection: close\r\n"
00147 "Content-Type: text/html; charset=iso-8859-1\r\n\r\n");
00148
00149 bio.writeLine("<H1>MTasker webserver</H1>\r\n");
00150 bio.writeLine("File '"+fname+"' is missing\r\n");
00151 }
00152 else {
00153 cout<<". Serving"; cout.flush();
00154 bio.writeLine("HTTP/1.1 200 OK\r\n"
00155 "Server: MTasker\r\n"
00156 "Connection: close\r\n"
00157 "Content-Type: text/html; charset=iso-8859-1\r\n\r\n");
00158
00159 vector<char>buffer(chunksize);
00160 int len;
00161 try {
00162 while((len=fread(&buffer[0],1,chunksize,fp))) {
00163 bio.write(&buffer[0],len);
00164 }
00165 }
00166 catch(...) {
00167 fclose(fp);
00168 throw;
00169 }
00170 fclose(fp);
00171 cout<<". Done"<<endl;
00172 }
00173 }
00174 catch(NetworkError &ne) {
00175 cerr<<"Fatal error in connection thread: "<<ne<<endl;
00176 }
00177 delete client;
00178 }
00179
00180 int main(int argc, char **argv)
00181 {
00182 signal(SIGPIPE,SIG_IGN);
00183 try {
00184 Socket s(InterNetwork, Stream);
00185 IPEndpoint ep;
00186 ep.address.byte=0;
00187 ep.port=8000;
00188 s.bind(ep);
00189 s.listen();
00190 s.setNonBlocking();
00191 cerr<<"Bound to local port "<<ep.port<<endl;
00192
00193 vector<WSEvent> waitevents;
00194 vector<Socket *>readers, writers,errors;
00195 Socket* newClient=0;
00196
00197 for(;;) {
00198 while(MT.schedule());
00199
00200 SelectSocketMultiplex mult;
00201 mult.addReader(&s);
00202 MT.getEvents(waitevents);
00203
00204
00205 for(vector<WSEvent>::const_iterator i=waitevents.begin();i!=waitevents.end();++i)
00206 if(i->what==WSEvent::Write)
00207 mult.addWriter(i->who);
00208 else if(i->what==WSEvent::Read)
00209 mult.addReader(i->who);
00210
00211
00212 mult.run(readers,writers,errors);
00213
00214 if(count(readers.begin(),readers.end(),&s)==1 && (newClient=s.accept())) {
00215 newClient->setNonBlocking();
00216 MT.makeThread(connection,(void *)newClient);
00217 }
00218
00219 WSEvent ws;
00220
00221
00222 ws.what=WSEvent::Read;
00223 for(vector<Socket *>::iterator i=readers.begin();i<readers.end();++i) {
00224 if(*i==&s)
00225 continue;
00226 ws.who=*i;
00227 MT.sendEvent(ws);
00228 }
00229
00230 ws.what=WSEvent::Write;
00231 for(vector<Socket *>::iterator i=writers.begin();i<writers.end();++i) {
00232 ws.who=*i;
00233 MT.sendEvent(ws);
00234 }
00235 }
00236 }
00237 catch(NetworkError &ne) {
00238 cerr<<"Fatal error: "<<ne<<endl;
00239 }
00240 catch(exception &e) {
00241 cerr<<"STL Exception: "<<e.what()<<endl;
00242 }
00243 }
00244