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