00001 #include "headers.h"
00002 #include <algorithm>
00007
00008
00012 WebServer::WebServer() {
00013
00014 pthread_attr_t attr;
00015 pthread_attr_init(&attr);
00016
00017
00018 pthread_create(&m_serverThreadId, &attr, WebServer::run, NULL);
00019
00020
00021 pthread_attr_destroy(&attr);
00022 }
00023
00024
00025 WebServer::~WebServer() {
00026 void* statusp;
00027 pthread_cancel(m_serverThreadId);
00028 pthread_join(m_serverThreadId, &statusp);
00029 }
00030
00031
00032 void*
00033 WebServer::run(void* nothing) {
00034 int serviceNumber;
00035
00036 debug(DEBUG_WS, "WEB SERVER UP");
00037
00038 while (true) {
00039 pthread_testcancel();
00040
00041 serviceNumber = GlobalObjects::instance()->getTransportLayer()->listenAccept();
00042 if (serviceNumber == TransportLayer::DEAD) {
00043 debug(DEBUG_WS, "Transport layer is dead");
00044 return NULL;
00045 }
00046 if (serviceNumber <= 0) {
00047 debug(DEBUG_WS, "SERVER: accepted on bad service number!");
00048 continue;
00049 }
00050
00051
00052
00053 pthread_attr_t attr;
00054 pthread_attr_init(&attr);
00055 pthread_t workerThreadId;
00056
00057 pthread_create(&workerThreadId, &attr, WebServer::handleConnection, &serviceNumber);
00058
00059
00060 pthread_attr_destroy(&attr);
00061 }
00062 }
00063
00064
00065 void*
00066 WebServer::handleConnection(void* arg) {
00067 pthread_detach(pthread_self());
00068 int serviceNumber = *((int*)arg);
00069 const int bufSize = 32768;
00070 vector<char> buf(bufSize);
00071
00072 debug(DEBUG_WS, "HANDLE CONNECTION THREAD");
00073
00074
00075
00076
00077 int bytesRead;
00078 int totalBytesRead = 0;
00079 do {
00080
00081 bytesRead = GlobalObjects::instance()->getTransportLayer()->receive(serviceNumber, (unsigned char*)(&buf[totalBytesRead]), (buf.capacity() - totalBytesRead));
00082 if (bytesRead > 0) {
00083 totalBytesRead += bytesRead;
00084 }
00085
00086
00087 if (bytesRead <= 0) {
00088 debug(DEBUG_CMD, "SERVER: Error reading data");
00089 GlobalObjects::instance()->getTransportLayer()->disconnect(serviceNumber);
00090 return NULL;
00091 }
00092
00093
00094 } while (find(buf.begin(), buf.end(), '\n') == buf.end());
00095
00096
00097 string request(buf.begin(), buf.begin() + totalBytesRead);
00098
00099
00100
00101
00102
00103 SocketAddress serverSocketAddress = getSocketAddressFromHttp(request);
00104
00105
00106 if (serverSocketAddress.getIpAddress().isLanIp() ||
00107 serverSocketAddress.getIpAddress().isLoopback()) {
00108 GlobalObjects::instance()->getTransportLayer()->disconnect(serviceNumber);
00109 return NULL;
00110 }
00111
00112
00113
00114
00115 debug(DEBUG_WS, "Connecting to %s", serverSocketAddress.toCStr());
00116
00117 TcpConnection connection(serverSocketAddress);
00118 int success = connection.connect();
00119
00120
00121 connection.write((unsigned char*)request.data(), request.size());
00122
00123
00124
00125
00126 int totalBytesWritten = 0;
00127 totalBytesRead = 0;
00128 while ((bytesRead = connection.read((unsigned char*)&buf[0], buf.capacity(), 0)) > 0 ) {
00129 totalBytesRead += bytesRead;
00130 int bytesWritten = GlobalObjects::instance()->getTransportLayer()->send(serviceNumber, (unsigned char*)&buf[0], bytesRead);
00131 if (bytesWritten < 0) {
00132 debug(DEBUG_WS, "SERVER: error during transmission");
00133 GlobalObjects::instance()->getTransportLayer()->disconnect(serviceNumber);
00134 return NULL;
00135 }
00136 totalBytesWritten += bytesWritten;
00137
00138
00139
00140
00141
00142 }
00143
00144
00145
00146 connection.close();
00147
00148
00149 if (!GlobalObjects::instance()->getTransportLayer()->disconnect(serviceNumber)) {
00150 debug(DEBUG_WS, "SERVER: Error while attempting to disconnect");
00151 return NULL;
00152 }
00153 debug(DEBUG_WS, "SERVER: disconnect");
00154 return NULL;
00155 }
00156
00157
00161 SocketAddress
00162 WebServer::getSocketAddressFromHttp(string request) {
00163
00164 std::string::size_type urlStartIndex = request.find("http://");
00165
00166
00167 std::string::size_type serverNameStartIndex = urlStartIndex + strlen("http://");
00168 std::string::size_type serverNameEndIndex = request.find_first_of("/:", serverNameStartIndex) - 1;
00169 string serverName = request.substr(serverNameStartIndex, serverNameEndIndex - serverNameStartIndex + 1);
00170
00171 SocketAddress socketAddress;
00172
00173
00174 string serverPortString = "80";
00175 if (request[serverNameEndIndex+1] == ':') {
00176 std::string::size_type portEndIndex = request.find('/', serverNameEndIndex + 1);
00177 serverPortString = request.substr(serverNameEndIndex+1, portEndIndex - serverNameEndIndex + 1);
00178 }
00179
00180 socketAddress.setPort(serverPortString);
00181 socketAddress.setIpAddress(serverName);
00182 return socketAddress;
00183 }
00184