15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/* 25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * libjingle 35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Copyright 2011, Google Inc. 45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Redistribution and use in source and binary forms, with or without 65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * modification, are permitted provided that the following conditions are met: 75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * this list of conditions and the following disclaimer. 105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * this list of conditions and the following disclaimer in the documentation 125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * and/or other materials provided with the distribution. 135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 3. The name of the author may not be used to endorse or promote products 145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * derived from this software without specific prior written permission. 155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org */ 275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifndef TALK_EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_ 295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#define TALK_EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_ 305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#pragma once 315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef WIN32 335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <winsock2.h> 345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtypedef int socklen_t; 355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#else 365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <netinet/in.h> 375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <sys/select.h> 385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <sys/socket.h> 395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#define closesocket close 405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <string> 435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifndef SOCKET_ERROR 455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#define SOCKET_ERROR (-1) 465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifndef INVALID_SOCKET 495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#define INVALID_SOCKET static_cast<int>(~0) 505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass SocketBase { 535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketBase() : socket_(INVALID_SOCKET) { } 555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org explicit SocketBase(int socket) : socket_(socket) { } 565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ~SocketBase() { Close(); } 575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int socket() const { return socket_; } 595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool valid() const { return socket_ != INVALID_SOCKET; } 605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool Create(); 625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void Close(); 635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org protected: 655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int socket_; 665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Represents an HTTP server socket. 695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass DataSocket : public SocketBase { 705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enum RequestMethod { 725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org INVALID, 735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org GET, 745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org POST, 755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org OPTIONS, 765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org }; 775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org explicit DataSocket(int socket) 795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org : SocketBase(socket), 805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org method_(INVALID), 815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org content_length_(0) { 825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ~DataSocket() { 855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org static const char kCrossOriginAllowHeaders[]; 885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool headers_received() const { return method_ != INVALID; } 905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org RequestMethod method() const { return method_; } 925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& request_path() const { return request_path_; } 945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::string request_arguments() const; 955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& data() const { return data_; } 975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& content_type() const { return content_type_; } 995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t content_length() const { return content_length_; } 1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool request_received() const { 1035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return headers_received() && (method_ != POST || data_received()); 1045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool data_received() const { 1075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return method_ != POST || data_.length() >= content_length_; 1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Checks if the request path (minus arguments) matches a given path. 1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool PathEquals(const char* path) const; 1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Called when we have received some data from clients. 1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Returns false if an error occurred. 1155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool OnDataAvailable(bool* close_socket); 1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Send a raw buffer of bytes. 1185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool Send(const std::string& data) const; 1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Send an HTTP response. The |status| should start with a valid HTTP 1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // response code, followed by a string. E.g. "200 OK". 1225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // If |connection_close| is set to true, an extra "Connection: close" HTTP 1235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // header will be included. |content_type| is the mime content type, not 1245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // including the "Content-Type: " string. 1255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // |extra_headers| should be either empty or a list of headers where each 1265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // header terminates with "\r\n". 1275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // |data| is the body of the message. It's length will be specified via 1285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // a "Content-Length" header. 1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool Send(const std::string& status, bool connection_close, 1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& content_type, 1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& extra_headers, const std::string& data) const; 1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Clears all held state and prepares the socket for receiving a new request. 1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void Clear(); 1355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org protected: 1375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // A fairly relaxed HTTP header parser. Parses the method, path and 1385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // content length (POST only) of a request. 1395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Returns true if a valid request was received and no errors occurred. 1405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool ParseHeaders(); 1415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Figures out whether the request is a GET or POST and what path is 1435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // being requested. 1445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool ParseMethodAndPath(const char* begin, size_t len); 1455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Determines the length of the body and it's mime type. 1475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool ParseContentLengthAndType(const char* headers, size_t length); 1485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org protected: 1505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org RequestMethod method_; 1515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t content_length_; 1525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::string content_type_; 1535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::string request_path_; 1545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::string request_headers_; 1555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::string data_; 1565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 1575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// The server socket. Accepts connections and generates DataSocket instances 1595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// for each new connection. 1605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass ListeningSocket : public SocketBase { 1615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 1625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ListeningSocket() {} 1635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool Listen(unsigned short port); 1655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org DataSocket* Accept() const; 1665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 1675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif // TALK_EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_ 169