/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "backends/networking/sdl_net/getclienthandler.h" #include "common/textconsole.h" namespace Networking { GetClientHandler::GetClientHandler(Common::SeekableReadStream *stream): _responseCode(200), _headersPrepared(false), _stream(stream), _buffer(new byte[CLIENT_HANDLER_BUFFER_SIZE]) {} GetClientHandler::~GetClientHandler() { delete _stream; delete[] _buffer; } const char *GetClientHandler::responseMessage(long responseCode) { switch (responseCode) { case 100: return "Continue"; case 101: return "Switching Protocols"; case 102: return "Processing"; case 200: return "OK"; case 201: return "Created"; case 202: return "Accepted"; case 203: return "Non-Authoritative Information"; case 204: return "No Content"; case 205: return "Reset Content"; case 206: return "Partial Content"; case 207: return "Multi-Status"; case 226: return "IM Used"; case 300: return "Multiple Choices"; case 301: return "Moved Permanently"; case 302: return "Moved Temporarily"; //case 302: return "Found"; case 303: return "See Other"; case 304: return "Not Modified"; case 305: return "Use Proxy"; case 306: return "RESERVED"; case 307: return "Temporary Redirect"; case 400: return "Bad Request"; case 401: return "Unauthorized"; case 402: return "Payment Required"; case 403: return "Forbidden"; case 404: return "Not Found"; case 405: return "Method Not Allowed"; case 406: return "Not Acceptable"; case 407: return "Proxy Authentication Required"; case 408: return "Request Timeout"; case 409: return "Conflict"; case 410: return "Gone"; case 411: return "Length Required"; case 412: return "Precondition Failed"; case 413: return "Request Entity Too Large"; case 414: return "Request-URI Too Large"; case 415: return "Unsupported Media Type"; case 416: return "Requested Range Not Satisfiable"; case 417: return "Expectation Failed"; case 422: return "Unprocessable Entity"; case 423: return "Locked"; case 424: return "Failed Dependency"; case 425: return "Unordered Collection"; case 426: return "Upgrade Required"; case 428: return "Precondition Required"; case 429: return "Too Many Requests"; case 431: return "Request Header Fields Too Large"; case 434: return "Requested Host Unavailable"; case 449: return "Retry With"; case 451: return "Unavailable For Legal Reasons"; case 500: return "Internal Server Error"; case 501: return "Not Implemented"; case 502: return "Bad Gateway"; case 503: return "Service Unavailable"; case 504: return "Gateway Timeout"; case 505: return "HTTP Version Not Supported"; case 506: return "Variant Also Negotiates"; case 507: return "Insufficient Storage"; case 508: return "Loop Detected"; case 509: return "Bandwidth Limit Exceeded"; case 510: return "Not Extended"; case 511: return "Network Authentication Required"; } return "Unknown"; } void GetClientHandler::prepareHeaders() { if (!_specialHeaders.contains("Content-Type")) setHeader("Content-Type", "text/html"); if (!_specialHeaders.contains("Content-Length") && _stream) setHeader("Content-Length", Common::String::format("%u", _stream->size())); _headers = Common::String::format("HTTP/1.1 %ld %s\r\n", _responseCode, responseMessage(_responseCode)); for (Common::HashMap::iterator i = _specialHeaders.begin(); i != _specialHeaders.end(); ++i) _headers += i->_key + ": " + i->_value + "\r\n"; _headers += "\r\n"; _headersPrepared = true; } void GetClientHandler::handle(Client *client) { if (!client) return; if (!_headersPrepared) prepareHeaders(); uint32 readBytes; // send headers first if (_headers.size() > 0) { readBytes = _headers.size(); if (readBytes > CLIENT_HANDLER_BUFFER_SIZE) readBytes = CLIENT_HANDLER_BUFFER_SIZE; memcpy(_buffer, _headers.c_str(), readBytes); _headers.erase(0, readBytes); } else { if (!_stream) { client->close(); return; } readBytes = _stream->read(_buffer, CLIENT_HANDLER_BUFFER_SIZE); } if (readBytes != 0) if (client->send(_buffer, readBytes) != readBytes) { warning("GetClientHandler: unable to send all bytes to the client"); client->close(); return; } // we're done here! if (_stream->eos()) client->close(); } void GetClientHandler::setHeader(Common::String name, Common::String value) { _specialHeaders[name] = value; } void GetClientHandler::setResponseCode(long code) { _responseCode = code; } } // End of namespace Networking