13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/tools/fetch/http_listen_socket.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <map> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/compiler_specific.h" 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h" 123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/fetch/http_server_request_info.h" 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/fetch/http_server_response_info.h" 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// must run in the IO thread 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHttpListenSocket::HttpListenSocket(SOCKET s, 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpListenSocket::Delegate* delegate) 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : ALLOW_THIS_IN_INITIALIZER_LIST(ListenSocket(s, this)), 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate_(delegate) { 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// must run in the IO thread 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHttpListenSocket::~HttpListenSocket() { 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid HttpListenSocket::Listen() { 2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ListenSocket::Listen(); 2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpListenSocket::Accept() { 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SOCKET conn = ListenSocket::Accept(socket_); 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(conn, ListenSocket::kInvalidSocket); 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (conn == ListenSocket::kInvalidSocket) { 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 37513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<HttpListenSocket> sock( 38513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch new HttpListenSocket(conn, delegate_)); 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // it's up to the delegate to AddRef if it wants to keep it around 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DidAccept(this, sock); 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 443345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickHttpListenSocket* HttpListenSocket::Listen( 453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string& ip, 463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int port, 473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick HttpListenSocket::Delegate* delegate) { 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SOCKET s = ListenSocket::Listen(ip, port); 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (s == ListenSocket::kInvalidSocket) { 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO (ibrar): error handling 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpListenSocket *serv = new HttpListenSocket(s, delegate); 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott serv->Listen(); 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return serv; 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// HTTP Request Parser 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This HTTP request parser uses a simple state machine to quickly parse 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// through the headers. The parser is not 100% complete, as it is designed 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// for use in this simple test driver. 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Known issues: 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - does not handle whitespace on first HTTP line correctly. Expects 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// a single space between the method/url and url/protocol. 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Input character types. 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottenum header_parse_inputs { 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott INPUT_SPACE, 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott INPUT_CR, 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott INPUT_LF, 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott INPUT_COLON, 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott INPUT_DEFAULT, 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MAX_INPUTS 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Parser states. 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottenum header_parse_states { 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ST_METHOD, // Receiving the method 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ST_URL, // Receiving the URL 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ST_PROTO, // Receiving the protocol 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ST_HEADER, // Starting a Request Header 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ST_NAME, // Receiving a request header name 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ST_SEPARATOR, // Receiving the separator between header name and value 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ST_VALUE, // Receiving a request header value 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ST_DONE, // Parsing is complete and successful 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ST_ERR, // Parsing encountered invalid syntax. 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MAX_STATES 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// State transition table 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint parser_state[MAX_STATES][MAX_INPUTS] = { 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* METHOD */ { ST_URL, ST_ERR, ST_ERR, ST_ERR, ST_METHOD }, 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* URL */ { ST_PROTO, ST_ERR, ST_ERR, ST_URL, ST_URL }, 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* PROTOCOL */ { ST_ERR, ST_HEADER, ST_NAME, ST_ERR, ST_PROTO }, 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* HEADER */ { ST_ERR, ST_ERR, ST_NAME, ST_ERR, ST_ERR }, 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* NAME */ { ST_SEPARATOR, ST_DONE, ST_ERR, ST_SEPARATOR, ST_NAME }, 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* SEPARATOR */ { ST_SEPARATOR, ST_ERR, ST_ERR, ST_SEPARATOR, ST_VALUE }, 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* VALUE */ { ST_VALUE, ST_HEADER, ST_NAME, ST_VALUE, ST_VALUE }, 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* DONE */ { ST_DONE, ST_DONE, ST_DONE, ST_DONE, ST_DONE }, 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* ERR */ { ST_ERR, ST_ERR, ST_ERR, ST_ERR, ST_ERR } 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Convert an input character to the parser's input token. 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint charToInput(char ch) { 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch(ch) { 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ' ': 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return INPUT_SPACE; 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case '\r': 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return INPUT_CR; 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case '\n': 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return INPUT_LF; 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ':': 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return INPUT_COLON; 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return INPUT_DEFAULT; 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHttpServerRequestInfo* HttpListenSocket::ParseHeaders() { 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int pos = 0; 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int data_len = recv_data_.length(); 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int state = ST_METHOD; 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpServerRequestInfo* info = new HttpServerRequestInfo(); 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string buffer; 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string header_name; 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string header_value; 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (pos < data_len) { 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char ch = recv_data_[pos++]; 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int input = charToInput(ch); 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int next_state = parser_state[state][input]; 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool transition = (next_state != state); 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (transition) { 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Do any actions based on state transitions. 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (state) { 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ST_METHOD: 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott info->method = buffer; 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buffer.clear(); 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ST_URL: 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott info->url = GURL(buffer); 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buffer.clear(); 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ST_PROTO: 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(mbelshe): Deal better with parsing protocol. 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(buffer == "HTTP/1.1"); 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buffer.clear(); 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ST_NAME: 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott header_name = buffer; 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buffer.clear(); 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ST_VALUE: 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott header_value = buffer; 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(mbelshe): Deal better with duplicate headers 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(info->headers.find(header_name) == info->headers.end()); 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott info->headers[header_name] = header_value; 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buffer.clear(); 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott state = next_state; 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Do any actions based on current state 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (state) { 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ST_METHOD: 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ST_URL: 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ST_PROTO: 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ST_VALUE: 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ST_NAME: 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buffer.append(&ch, 1); 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ST_DONE: 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott recv_data_ = recv_data_.substr(pos); 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return info; 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ST_ERR: 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete info; 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // No more characters, but we haven't finished parsing yet. 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete info; 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpListenSocket::DidAccept(ListenSocket* server, 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ListenSocket* connection) { 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott connection->AddRef(); 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpListenSocket::DidRead(ListenSocket* connection, 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* data, 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int len) { 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch recv_data_.append(data, len); 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (recv_data_.length()) { 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpServerRequestInfo* request = ParseHeaders(); 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!request) 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate_->OnRequest(this, request); 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete request; 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpListenSocket::DidClose(ListenSocket* sock) { 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sock->Release(); 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Convert the numeric status code to a string. 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// e.g. 200 -> "200 OK" 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string ServerStatus(int code) { 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch(code) { 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 200: 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return std::string("200 OK"); 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(mbelshe): handle other codes. 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED(); 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return std::string(); 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpListenSocket::Respond(HttpServerResponseInfo* info, 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string& data) { 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string response; 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // status line 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response = info->protocol + " "; 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response += ServerStatus(info->status); 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response += "\r\n"; 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // standard headers 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (info->content_type.length()) 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response += "Content-type: " + info->content_type + "\r\n"; 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (info->content_length > 0) 2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick response += "Content-length: " + base::IntToString(info->content_length) + 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "\r\n"; 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (info->connection_close) 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response += "Connection: close\r\n"; 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(mbelshe): support additional headers 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // End of headers 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response += "\r\n"; 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Add data 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response += data; 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Write it all out. 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott this->Send(response, false); 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 253