/* simple_httpd.C
* -- Copyright (C) 2003 by Herbert Straub
*
* Permission is granted to use at your own risk and distribute this software
* in source and binary forms provided the above copyright notice and this
* paragraph are preserved on all copies. This software is provided "as is"
* with no express or implied warranty.
*/
/*
* This little program implements a very simple http server (only for
* testing purposes). It usess: iosockinet, sockbuf, Fork.
*/
#include <config.h>
#include <socket++/fork.h>
#include <socket++/sockinet.h>
#include <sys/stat.h>
#include <unistd.h>
#include <iostream>
#include <fstream>
#ifdef HAVE_SSTREAM
#include <sstream>
#else
#include <strstream>
#endif
using namespace std;
int process_request (iosockinet *sock);
void get_filesize (const char *name, string &buffer);
int main (int argc, char **argv)
{
sockinetbuf sin (sockbuf::sock_stream);
Fork *pF;
sin.bind ();
cout << "localhost = " << sin.localhost() << endl;
cout << "localport = " << sin.localport() << endl;
sin.listen ();
for (;;) {
iosockinet *sock;
sock = new iosockinet (sin.accept ());
sockaddr_in *remote_sock = sock->rdbuf()->peeraddr().addr_in();
cout << "socksockaddr_in.addr() = " << remote_sock << endl;
cout << "port: " << ntohs(remote_sock->sin_port) << endl;
cout << "addr: " << hex << inet_ntoa(remote_sock->sin_addr) << endl;
cout << "peerhost: " << sock->rdbuf()->peerhost() << endl;
pF = new Fork (0, 1);
if (pF->is_child ()) {
sock->rdbuf()->keepalive (1);
process_request (sock);
return (0);
}
}
}
int process_request (iosockinet *sock)
{
string buffer;
string filename;
ifstream file;
try {
while (1) {
getline (*sock, buffer);
buffer[buffer.length()-1] = '\n';
cout << "buffer: " << buffer << endl;
if (sock->eof())
break;
// g++ < 3.0 : strncmp !!
if (strncmp (buffer.c_str(), "quit", 4) == 0)
//if (buffer.compare (0, 4, "quit") == 0)
break;
if (buffer.length() == 0)
break;
if (buffer[0] == '\n')
break;
// g++ < 3.0 : strncmp !!
if (strncmp (buffer.c_str(), "GET", 4) == 0)
//if (buffer.compare (0, 4, "GET") == 0)
filename.assign (buffer, 4, buffer.rfind (" HTTP")-3);
}
}
catch (sockerr s) {
cout << "catched " << endl;
goto END;
}
//filename.insert (0, ".");
filename.replace (filename.length()-1, 1, "");
cout << "Filename: " << filename << endl;
file.open (filename.c_str());
if (file.bad() || !file.is_open() || !file.good()) {
cout << "Error opening file: " << filename << endl;
goto END;
}
*sock << "HTTP/1.1 200 OK\r\n";
*sock << "Server: socket++ Testserver\r\n";
get_filesize (filename.c_str(), buffer);
*sock << "Content-Length: " << buffer << "\r\n";
*sock << "Connection: close\r\n";
*sock << "Content-Type: plain/text; charset=iso-8859-1\r\n";
*sock << "\r\n";
sock->flush();
try {
for (getline(file, buffer); !file.eof(); getline(file,buffer)) {
cout << "Sending Buffer: " << buffer << endl;
*sock << buffer << "\r\n";
}
sock->flush();
}
catch (sockerr e) {
cout << "Catched sockerr" << endl;
}
file.close ();
END:
try {
sock->rdbuf()->shutdown(sockbuf::shut_readwrite);
}
catch (...)
{
// if the client break the connection, then
// the shutdown method throws sockerr
}
delete sock;
return 0;
}
void get_filesize (const char *name, string &buffer)
{
struct stat buf;
#ifdef HAVE_SSTREAM
stringstream sb;
#else
strstream sb;
#endif
if (stat (name, &buf) == -1)
buf.st_size = 0;
sb << buf.st_size;
buffer = sb.rdbuf()->str();
}
syntax highlighted by Code2HTML, v. 0.9.1