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