data_socket.h (4450B)
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 EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_ 12 #define EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_ 13 14 #include <cstddef> 15 #include <string> 16 17 18 #ifdef WIN32 19 #include <winsock2.h> 20 typedef int socklen_t; 21 typedef SOCKET NativeSocket; 22 #else 23 #define closesocket close 24 typedef 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 class SocketBase { 36 public: 37 SocketBase() : socket_(INVALID_SOCKET) {} 38 explicit SocketBase(NativeSocket socket) : socket_(socket) {} 39 SocketBase(SocketBase& other) = delete; 40 SocketBase& operator=(const SocketBase& other) = delete; 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. 54 class 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), method_(INVALID), content_length_(0) {} 65 66 ~DataSocket() {} 67 68 static const char kCrossOriginAllowHeaders[]; 69 70 bool headers_received() const { return method_ != INVALID; } 71 72 RequestMethod method() const { return method_; } 73 74 const std::string& request_path() const { return request_path_; } 75 std::string request_arguments() const; 76 77 const std::string& data() const { return data_; } 78 79 const std::string& content_type() const { return content_type_; } 80 81 size_t content_length() const { return content_length_; } 82 83 bool request_received() const { 84 return headers_received() && (method_ != POST || data_received()); 85 } 86 87 bool data_received() const { 88 return method_ != POST || data_.length() >= content_length_; 89 } 90 91 // Checks if the request path (minus arguments) matches a given path. 92 bool PathEquals(const char* path) const; 93 94 // Called when we have received some data from clients. 95 // Returns false if an error occurred. 96 bool OnDataAvailable(bool* close_socket); 97 98 // Send a raw buffer of bytes. 99 bool Send(const std::string& data) const; 100 101 // Send an HTTP response. The `status` should start with a valid HTTP 102 // response code, followed by a string. E.g. "200 OK". 103 // If `connection_close` is set to true, an extra "Connection: close" HTTP 104 // header will be included. `content_type` is the mime content type, not 105 // including the "Content-Type: " string. 106 // `extra_headers` should be either empty or a list of headers where each 107 // header terminates with "\r\n". 108 // `data` is the body of the message. It's length will be specified via 109 // a "Content-Length" header. 110 bool Send(const std::string& status, 111 bool connection_close, 112 const std::string& content_type, 113 const std::string& extra_headers, 114 const std::string& data) const; 115 116 // Clears all held state and prepares the socket for receiving a new request. 117 void Clear(); 118 119 protected: 120 // A fairly relaxed HTTP header parser. Parses the method, path and 121 // content length (POST only) of a request. 122 // Returns true if a valid request was received and no errors occurred. 123 bool ParseHeaders(); 124 125 // Figures out whether the request is a GET or POST and what path is 126 // being requested. 127 bool ParseMethodAndPath(const char* begin, size_t len); 128 129 // Determines the length of the body and it's mime type. 130 bool ParseContentLengthAndType(const char* headers, size_t length); 131 132 protected: 133 RequestMethod method_; 134 size_t content_length_; 135 std::string content_type_; 136 std::string request_path_; 137 std::string request_headers_; 138 std::string data_; 139 }; 140 141 // The server socket. Accepts connections and generates DataSocket instances 142 // for each new connection. 143 class ListeningSocket : public SocketBase { 144 public: 145 ListeningSocket() {} 146 147 bool Listen(unsigned short port); 148 DataSocket* Accept() const; 149 }; 150 151 #endif // EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_