15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/*
25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * libjingle
35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Copyright 2011, Google Inc.
45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Redistribution and use in source and binary forms, with or without
65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * modification, are permitted provided that the following conditions are met:
75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     this list of conditions and the following disclaimer.
105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     this list of conditions and the following disclaimer in the documentation
125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     and/or other materials provided with the distribution.
135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  3. The name of the author may not be used to endorse or promote products
145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     derived from this software without specific prior written permission.
155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org */
275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/examples/peerconnection/server/data_socket.h"
295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
30b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org#include <ctype.h>
315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <stdio.h>
325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <stdlib.h>
335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <string.h>
345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#if defined(POSIX)
355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <unistd.h>
365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif
375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/examples/peerconnection/server/utils.h"
395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const char kHeaderTerminator[] = "\r\n\r\n";
415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const int kHeaderTerminatorLength = sizeof(kHeaderTerminator) - 1;
425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// static
445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char DataSocket::kCrossOriginAllowHeaders[] =
455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    "Access-Control-Allow-Origin: *\r\n"
465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    "Access-Control-Allow-Credentials: true\r\n"
475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    "Access-Control-Allow-Methods: POST, GET, OPTIONS\r\n"
485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    "Access-Control-Allow-Headers: Content-Type, "
495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        "Content-Length, Connection, Cache-Control\r\n"
505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    "Access-Control-Expose-Headers: Content-Length, X-Peer-Id\r\n";
515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#if defined(WIN32)
535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass WinsockInitializer {
545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  static WinsockInitializer singleton;
555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  WinsockInitializer() {
575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    WSADATA data;
585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    WSAStartup(MAKEWORD(1, 0), &data);
595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public:
625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ~WinsockInitializer() { WSACleanup(); }
635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org};
645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgWinsockInitializer WinsockInitializer::singleton;
655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif
665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org//
685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// SocketBase
695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org//
705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool SocketBase::Create() {
725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  assert(!valid());
735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  socket_ = ::socket(AF_INET, SOCK_STREAM, 0);
745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return valid();
755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid SocketBase::Close() {
785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (socket_ != INVALID_SOCKET) {
795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    closesocket(socket_);
805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    socket_ = INVALID_SOCKET;
815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org//
855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// DataSocket
865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org//
875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstd::string DataSocket::request_arguments() const {
895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  size_t args = request_path_.find('?');
905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (args != std::string::npos)
915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return request_path_.substr(args + 1);
925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return "";
935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool DataSocket::PathEquals(const char* path) const {
965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  assert(path);
975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  size_t args = request_path_.find('?');
985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (args != std::string::npos)
995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return request_path_.substr(0, args).compare(path) == 0;
1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return request_path_.compare(path) == 0;
1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool DataSocket::OnDataAvailable(bool* close_socket) {
1045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  assert(valid());
1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  char buffer[0xfff] = {0};
1065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int bytes = recv(socket_, buffer, sizeof(buffer), 0);
1075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (bytes == SOCKET_ERROR || bytes == 0) {
1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    *close_socket = true;
1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  *close_socket = false;
1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  bool ret = true;
1155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (headers_received()) {
1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (method_ != POST) {
1175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // unexpectedly received data.
1185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ret = false;
1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    } else {
1205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      data_.append(buffer, bytes);
1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
1235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    request_headers_.append(buffer, bytes);
1245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    size_t found = request_headers_.find(kHeaderTerminator);
1255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (found != std::string::npos) {
1265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      data_ = request_headers_.substr(found + kHeaderTerminatorLength);
1275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      request_headers_.resize(found + kHeaderTerminatorLength);
1285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ret = ParseHeaders();
1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return ret;
1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool DataSocket::Send(const std::string& data) const {
135b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org  return send(socket_, data.data(), static_cast<int>(data.length()), 0) !=
136b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org      SOCKET_ERROR;
1375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool DataSocket::Send(const std::string& status, bool connection_close,
1405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      const std::string& content_type,
1415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      const std::string& extra_headers,
1425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      const std::string& data) const {
1435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  assert(valid());
1445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  assert(!status.empty());
1455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::string buffer("HTTP/1.1 " + status + "\r\n");
1465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  buffer += "Server: PeerConnectionTestServer/0.1\r\n"
1485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org            "Cache-Control: no-cache\r\n";
1495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (connection_close)
1515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    buffer += "Connection: close\r\n";
1525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!content_type.empty())
1545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    buffer += "Content-Type: " + content_type + "\r\n";
1555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
156b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org  buffer += "Content-Length: " + int2str(static_cast<int>(data.size())) +
157b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org            "\r\n";
1585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!extra_headers.empty()) {
1605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    buffer += extra_headers;
1615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Extra headers are assumed to have a separator per header.
1625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  buffer += kCrossOriginAllowHeaders;
1655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  buffer += "\r\n";
1675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  buffer += data;
1685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return Send(buffer);
1705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid DataSocket::Clear() {
1735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  method_ = INVALID;
1745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  content_length_ = 0;
1755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  content_type_.clear();
1765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  request_path_.clear();
1775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  request_headers_.clear();
1785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  data_.clear();
1795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool DataSocket::ParseHeaders() {
1825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  assert(!request_headers_.empty());
1835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  assert(method_ == INVALID);
1845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  size_t i = request_headers_.find("\r\n");
1855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (i == std::string::npos)
1865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
1875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!ParseMethodAndPath(request_headers_.data(), i))
1895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
1905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  assert(method_ != INVALID);
1925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  assert(!request_path_.empty());
1935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (method_ == POST) {
1955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const char* headers = request_headers_.data() + i + 2;
1965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    size_t len = request_headers_.length() - i - 2;
1975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!ParseContentLengthAndType(headers, len))
1985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return false;
1995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
2025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool DataSocket::ParseMethodAndPath(const char* begin, size_t len) {
2055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  struct {
2065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const char* method_name;
2075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    size_t method_name_len;
2085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    RequestMethod id;
2095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } supported_methods[] = {
2105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    { "GET", 3, GET },
2115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    { "POST", 4, POST },
2125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    { "OPTIONS", 7, OPTIONS },
2135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  };
2145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const char* path = NULL;
2165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (size_t i = 0; i < ARRAYSIZE(supported_methods); ++i) {
2175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (len > supported_methods[i].method_name_len &&
2185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        isspace(begin[supported_methods[i].method_name_len]) &&
2195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        strncmp(begin, supported_methods[i].method_name,
2205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                supported_methods[i].method_name_len) == 0) {
2215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      method_ = supported_methods[i].id;
2225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      path = begin + supported_methods[i].method_name_len;
2235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
2245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
2255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const char* end = begin + len;
2285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!path || path >= end)
2295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
2305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ++path;
2325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  begin = path;
2335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  while (!isspace(*path) && path < end)
2345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ++path;
2355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  request_path_.assign(begin, path - begin);
2375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
2395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool DataSocket::ParseContentLengthAndType(const char* headers, size_t length) {
2425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  assert(content_length_ == 0);
2435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  assert(content_type_.empty());
2445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const char* end = headers + length;
2465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  while (headers && headers < end) {
2475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!isspace(headers[0])) {
2485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      static const char kContentLength[] = "Content-Length:";
2495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      static const char kContentType[] = "Content-Type:";
2505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if ((headers + ARRAYSIZE(kContentLength)) < end &&
2515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          strncmp(headers, kContentLength,
2525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                  ARRAYSIZE(kContentLength) - 1) == 0) {
2535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        headers += ARRAYSIZE(kContentLength) - 1;
2545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        while (headers[0] == ' ')
2555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          ++headers;
2565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        content_length_ = atoi(headers);
2575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      } else if ((headers + ARRAYSIZE(kContentType)) < end &&
2585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                 strncmp(headers, kContentType,
2595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                         ARRAYSIZE(kContentType) - 1) == 0) {
2605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        headers += ARRAYSIZE(kContentType) - 1;
2615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        while (headers[0] == ' ')
2625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          ++headers;
2635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        const char* type_end = strstr(headers, "\r\n");
2645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        if (type_end == NULL)
2655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          type_end = end;
2665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        content_type_.assign(headers, type_end);
2675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
2685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    } else {
2695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ++headers;
2705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
2715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    headers = strstr(headers, "\r\n");
2725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (headers)
2735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      headers += 2;
2745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return !content_type_.empty() && content_length_ != 0;
2775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org//
2805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// ListeningSocket
2815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org//
2825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool ListeningSocket::Listen(unsigned short port) {
2845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  assert(valid());
2855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int enabled = 1;
2865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
2875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      reinterpret_cast<const char*>(&enabled), sizeof(enabled));
2885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  struct sockaddr_in addr = {0};
2895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  addr.sin_family = AF_INET;
2905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  addr.sin_addr.s_addr = htonl(INADDR_ANY);
2915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  addr.sin_port = htons(port);
2925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (bind(socket_, reinterpret_cast<const sockaddr*>(&addr),
2935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org           sizeof(addr)) == SOCKET_ERROR) {
2945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    printf("bind failed\n");
2955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
2965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return listen(socket_, 5) != SOCKET_ERROR;
2985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgDataSocket* ListeningSocket::Accept() const {
3015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  assert(valid());
3025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  struct sockaddr_in addr = {0};
3035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  socklen_t size = sizeof(addr);
3045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int client = accept(socket_, reinterpret_cast<sockaddr*>(&addr), &size);
3055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (client == INVALID_SOCKET)
3065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
3075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return new DataSocket(client);
3095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
310