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> 17 typedef int socklen_t; 18 typedef SOCKET NativeSocket; 19 #else 20 #include <netinet/in.h> 21 #include <sys/select.h> 22 #include <sys/socket.h> 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 #include <string> 36 37 class SocketBase { 38 public: SocketBase()39 SocketBase() : socket_(INVALID_SOCKET) { } SocketBase(NativeSocket socket)40 explicit SocketBase(NativeSocket socket) : socket_(socket) { } ~SocketBase()41 ~SocketBase() { Close(); } 42 socket()43 NativeSocket socket() const { return socket_; } valid()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 DataSocket(NativeSocket socket)63 explicit DataSocket(NativeSocket socket) 64 : SocketBase(socket), 65 method_(INVALID), 66 content_length_(0) { 67 } 68 ~DataSocket()69 ~DataSocket() { 70 } 71 72 static const char kCrossOriginAllowHeaders[]; 73 headers_received()74 bool headers_received() const { return method_ != INVALID; } 75 method()76 RequestMethod method() const { return method_; } 77 request_path()78 const std::string& request_path() const { return request_path_; } 79 std::string request_arguments() const; 80 data()81 const std::string& data() const { return data_; } 82 content_type()83 const std::string& content_type() const { return content_type_; } 84 content_length()85 size_t content_length() const { return content_length_; } 86 request_received()87 bool request_received() const { 88 return headers_received() && (method_ != POST || data_received()); 89 } 90 data_received()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. 145 class ListeningSocket : public SocketBase { 146 public: ListeningSocket()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