128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org/* 2a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis * Copyright 2011 The WebRTC Project Authors. All rights reserved. 328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 4a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis * Use of this source code is governed by a BSD-style license 5a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis * that can be found in the LICENSE file in the root of the source 6a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis * tree. An additional intellectual property rights grant can be found 7a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis * in the file PATENTS. All contributing project authors may 8a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis * be found in the AUTHORS file in the root of the source tree. 928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org */ 1028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 1170625e5bf3c91c57bf704d380bcc9df86575f08ajbauch#ifndef WEBRTC_EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_ 1270625e5bf3c91c57bf704d380bcc9df86575f08ajbauch#define WEBRTC_EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_ 1328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#pragma once 1428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 1528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#ifdef WIN32 1628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <winsock2.h> 1728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgtypedef int socklen_t; 182c13f659c7013d4ce9dc123708b6a2d9a9ccdb2btommi@webrtc.orgtypedef SOCKET NativeSocket; 1928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#else 2028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <netinet/in.h> 2128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <sys/select.h> 2228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <sys/socket.h> 2328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#define closesocket close 242c13f659c7013d4ce9dc123708b6a2d9a9ccdb2btommi@webrtc.orgtypedef int NativeSocket; 2528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 2628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#ifndef SOCKET_ERROR 2728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#define SOCKET_ERROR (-1) 2828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#endif 2928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#ifndef INVALID_SOCKET 312c13f659c7013d4ce9dc123708b6a2d9a9ccdb2btommi@webrtc.org#define INVALID_SOCKET static_cast<NativeSocket>(-1) 3228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#endif 332c13f659c7013d4ce9dc123708b6a2d9a9ccdb2btommi@webrtc.org#endif 342c13f659c7013d4ce9dc123708b6a2d9a9ccdb2btommi@webrtc.org 352c13f659c7013d4ce9dc123708b6a2d9a9ccdb2btommi@webrtc.org#include <string> 3628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgclass SocketBase { 3828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org public: 3928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SocketBase() : socket_(INVALID_SOCKET) { } 402c13f659c7013d4ce9dc123708b6a2d9a9ccdb2btommi@webrtc.org explicit SocketBase(NativeSocket socket) : socket_(socket) { } 4128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ~SocketBase() { Close(); } 4228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 432c13f659c7013d4ce9dc123708b6a2d9a9ccdb2btommi@webrtc.org NativeSocket socket() const { return socket_; } 4428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool valid() const { return socket_ != INVALID_SOCKET; } 4528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 4628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool Create(); 4728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org void Close(); 4828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 4928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org protected: 502c13f659c7013d4ce9dc123708b6a2d9a9ccdb2btommi@webrtc.org NativeSocket socket_; 5128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 5228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 5328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Represents an HTTP server socket. 5428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgclass DataSocket : public SocketBase { 5528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org public: 5628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org enum RequestMethod { 5728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org INVALID, 5828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org GET, 5928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org POST, 6028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org OPTIONS, 6128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org }; 6228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 632c13f659c7013d4ce9dc123708b6a2d9a9ccdb2btommi@webrtc.org explicit DataSocket(NativeSocket socket) 6428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org : SocketBase(socket), 6528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org method_(INVALID), 6628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org content_length_(0) { 6728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 6828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 6928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ~DataSocket() { 7028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 7128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 7228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org static const char kCrossOriginAllowHeaders[]; 7328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 7428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool headers_received() const { return method_ != INVALID; } 7528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 7628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org RequestMethod method() const { return method_; } 7728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 7828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const std::string& request_path() const { return request_path_; } 7928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string request_arguments() const; 8028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 8128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const std::string& data() const { return data_; } 8228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 8328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const std::string& content_type() const { return content_type_; } 8428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 8528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org size_t content_length() const { return content_length_; } 8628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 8728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool request_received() const { 8828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return headers_received() && (method_ != POST || data_received()); 8928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 9028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 9128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool data_received() const { 9228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return method_ != POST || data_.length() >= content_length_; 9328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 9428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 9528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Checks if the request path (minus arguments) matches a given path. 9628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool PathEquals(const char* path) const; 9728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 9828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Called when we have received some data from clients. 9928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Returns false if an error occurred. 10028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool OnDataAvailable(bool* close_socket); 10128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 10228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Send a raw buffer of bytes. 10328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool Send(const std::string& data) const; 10428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 10528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Send an HTTP response. The |status| should start with a valid HTTP 10628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // response code, followed by a string. E.g. "200 OK". 10728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // If |connection_close| is set to true, an extra "Connection: close" HTTP 10828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // header will be included. |content_type| is the mime content type, not 10928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // including the "Content-Type: " string. 11028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // |extra_headers| should be either empty or a list of headers where each 11128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // header terminates with "\r\n". 11228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // |data| is the body of the message. It's length will be specified via 11328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // a "Content-Length" header. 11428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool Send(const std::string& status, bool connection_close, 11528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const std::string& content_type, 11628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const std::string& extra_headers, const std::string& data) const; 11728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 11828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Clears all held state and prepares the socket for receiving a new request. 11928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org void Clear(); 12028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 12128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org protected: 12228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // A fairly relaxed HTTP header parser. Parses the method, path and 12328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // content length (POST only) of a request. 12428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Returns true if a valid request was received and no errors occurred. 12528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool ParseHeaders(); 12628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 12728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Figures out whether the request is a GET or POST and what path is 12828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // being requested. 12928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool ParseMethodAndPath(const char* begin, size_t len); 13028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 13128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Determines the length of the body and it's mime type. 13228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool ParseContentLengthAndType(const char* headers, size_t length); 13328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 13428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org protected: 13528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org RequestMethod method_; 13628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org size_t content_length_; 13728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string content_type_; 13828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string request_path_; 13928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string request_headers_; 14028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string data_; 14128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 14228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 14328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// The server socket. Accepts connections and generates DataSocket instances 14428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// for each new connection. 14528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgclass ListeningSocket : public SocketBase { 14628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org public: 14728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ListeningSocket() {} 14828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 14928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool Listen(unsigned short port); 15028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org DataSocket* Accept() const; 15128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 15228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 15370625e5bf3c91c57bf704d380bcc9df86575f08ajbauch#endif // WEBRTC_EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_ 154