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