1/* 2 * Copyright 2011 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#ifndef WEBRTC_EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_ 12#define WEBRTC_EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_ 13#pragma once 14 15#ifdef WIN32 16#include <winsock2.h> 17typedef int socklen_t; 18typedef SOCKET NativeSocket; 19#else 20#include <netinet/in.h> 21#include <sys/select.h> 22#include <sys/socket.h> 23#define closesocket close 24typedef int NativeSocket; 25 26#ifndef SOCKET_ERROR 27#define SOCKET_ERROR (-1) 28#endif 29 30#ifndef INVALID_SOCKET 31#define INVALID_SOCKET static_cast<NativeSocket>(-1) 32#endif 33#endif 34 35#include <string> 36 37class SocketBase { 38 public: 39 SocketBase() : socket_(INVALID_SOCKET) { } 40 explicit SocketBase(NativeSocket socket) : socket_(socket) { } 41 ~SocketBase() { Close(); } 42 43 NativeSocket socket() const { return socket_; } 44 bool valid() const { return socket_ != INVALID_SOCKET; } 45 46 bool Create(); 47 void Close(); 48 49 protected: 50 NativeSocket socket_; 51}; 52 53// Represents an HTTP server socket. 54class DataSocket : public SocketBase { 55 public: 56 enum RequestMethod { 57 INVALID, 58 GET, 59 POST, 60 OPTIONS, 61 }; 62 63 explicit DataSocket(NativeSocket socket) 64 : SocketBase(socket), 65 method_(INVALID), 66 content_length_(0) { 67 } 68 69 ~DataSocket() { 70 } 71 72 static const char kCrossOriginAllowHeaders[]; 73 74 bool headers_received() const { return method_ != INVALID; } 75 76 RequestMethod method() const { return method_; } 77 78 const std::string& request_path() const { return request_path_; } 79 std::string request_arguments() const; 80 81 const std::string& data() const { return data_; } 82 83 const std::string& content_type() const { return content_type_; } 84 85 size_t content_length() const { return content_length_; } 86 87 bool request_received() const { 88 return headers_received() && (method_ != POST || data_received()); 89 } 90 91 bool data_received() const { 92 return method_ != POST || data_.length() >= content_length_; 93 } 94 95 // Checks if the request path (minus arguments) matches a given path. 96 bool PathEquals(const char* path) const; 97 98 // Called when we have received some data from clients. 99 // Returns false if an error occurred. 100 bool OnDataAvailable(bool* close_socket); 101 102 // Send a raw buffer of bytes. 103 bool Send(const std::string& data) const; 104 105 // Send an HTTP response. The |status| should start with a valid HTTP 106 // response code, followed by a string. E.g. "200 OK". 107 // If |connection_close| is set to true, an extra "Connection: close" HTTP 108 // header will be included. |content_type| is the mime content type, not 109 // including the "Content-Type: " string. 110 // |extra_headers| should be either empty or a list of headers where each 111 // header terminates with "\r\n". 112 // |data| is the body of the message. It's length will be specified via 113 // a "Content-Length" header. 114 bool Send(const std::string& status, bool connection_close, 115 const std::string& content_type, 116 const std::string& extra_headers, const std::string& data) const; 117 118 // Clears all held state and prepares the socket for receiving a new request. 119 void Clear(); 120 121 protected: 122 // A fairly relaxed HTTP header parser. Parses the method, path and 123 // content length (POST only) of a request. 124 // Returns true if a valid request was received and no errors occurred. 125 bool ParseHeaders(); 126 127 // Figures out whether the request is a GET or POST and what path is 128 // being requested. 129 bool ParseMethodAndPath(const char* begin, size_t len); 130 131 // Determines the length of the body and it's mime type. 132 bool ParseContentLengthAndType(const char* headers, size_t length); 133 134 protected: 135 RequestMethod method_; 136 size_t content_length_; 137 std::string content_type_; 138 std::string request_path_; 139 std::string request_headers_; 140 std::string data_; 141}; 142 143// The server socket. Accepts connections and generates DataSocket instances 144// for each new connection. 145class ListeningSocket : public SocketBase { 146 public: 147 ListeningSocket() {} 148 149 bool Listen(unsigned short port); 150 DataSocket* Accept() const; 151}; 152 153#endif // WEBRTC_EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_ 154