blob: 6bafa830a9e7c339e22cdd0f6b59e27d4ef9976c [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
Donald E Curtisa8736442015-08-05 15:48:13 -07002 * Copyright 2011 The WebRTC Project Authors. All rights reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
Donald E Curtisa8736442015-08-05 15:48:13 -07004 * 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.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_
12#define EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_
henrike@webrtc.org28e20752013-07-10 00:45:36 +000013
14#ifdef WIN32
15#include <winsock2.h>
16typedef int socklen_t;
tommi@webrtc.org2c13f652014-11-28 10:37:31 +000017typedef SOCKET NativeSocket;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000018#else
19#include <netinet/in.h>
20#include <sys/select.h>
21#include <sys/socket.h>
22#define closesocket close
tommi@webrtc.org2c13f652014-11-28 10:37:31 +000023typedef int NativeSocket;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000024
25#ifndef SOCKET_ERROR
26#define SOCKET_ERROR (-1)
27#endif
28
29#ifndef INVALID_SOCKET
tommi@webrtc.org2c13f652014-11-28 10:37:31 +000030#define INVALID_SOCKET static_cast<NativeSocket>(-1)
henrike@webrtc.org28e20752013-07-10 00:45:36 +000031#endif
tommi@webrtc.org2c13f652014-11-28 10:37:31 +000032#endif
33
34#include <string>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000035
36class SocketBase {
37 public:
38 SocketBase() : socket_(INVALID_SOCKET) { }
tommi@webrtc.org2c13f652014-11-28 10:37:31 +000039 explicit SocketBase(NativeSocket socket) : socket_(socket) { }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000040 ~SocketBase() { Close(); }
41
tommi@webrtc.org2c13f652014-11-28 10:37:31 +000042 NativeSocket socket() const { return socket_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000043 bool valid() const { return socket_ != INVALID_SOCKET; }
44
45 bool Create();
46 void Close();
47
48 protected:
tommi@webrtc.org2c13f652014-11-28 10:37:31 +000049 NativeSocket socket_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000050};
51
52// Represents an HTTP server socket.
53class DataSocket : public SocketBase {
54 public:
55 enum RequestMethod {
56 INVALID,
57 GET,
58 POST,
59 OPTIONS,
60 };
61
tommi@webrtc.org2c13f652014-11-28 10:37:31 +000062 explicit DataSocket(NativeSocket socket)
henrike@webrtc.org28e20752013-07-10 00:45:36 +000063 : SocketBase(socket),
64 method_(INVALID),
65 content_length_(0) {
66 }
67
68 ~DataSocket() {
69 }
70
71 static const char kCrossOriginAllowHeaders[];
72
73 bool headers_received() const { return method_ != INVALID; }
74
75 RequestMethod method() const { return method_; }
76
77 const std::string& request_path() const { return request_path_; }
78 std::string request_arguments() const;
79
80 const std::string& data() const { return data_; }
81
82 const std::string& content_type() const { return content_type_; }
83
84 size_t content_length() const { return content_length_; }
85
86 bool request_received() const {
87 return headers_received() && (method_ != POST || data_received());
88 }
89
90 bool data_received() const {
91 return method_ != POST || data_.length() >= content_length_;
92 }
93
94 // Checks if the request path (minus arguments) matches a given path.
95 bool PathEquals(const char* path) const;
96
97 // Called when we have received some data from clients.
98 // Returns false if an error occurred.
99 bool OnDataAvailable(bool* close_socket);
100
101 // Send a raw buffer of bytes.
102 bool Send(const std::string& data) const;
103
104 // Send an HTTP response. The |status| should start with a valid HTTP
105 // response code, followed by a string. E.g. "200 OK".
106 // If |connection_close| is set to true, an extra "Connection: close" HTTP
107 // header will be included. |content_type| is the mime content type, not
108 // including the "Content-Type: " string.
109 // |extra_headers| should be either empty or a list of headers where each
110 // header terminates with "\r\n".
111 // |data| is the body of the message. It's length will be specified via
112 // a "Content-Length" header.
113 bool Send(const std::string& status, bool connection_close,
114 const std::string& content_type,
115 const std::string& extra_headers, const std::string& data) const;
116
117 // Clears all held state and prepares the socket for receiving a new request.
118 void Clear();
119
120 protected:
121 // A fairly relaxed HTTP header parser. Parses the method, path and
122 // content length (POST only) of a request.
123 // Returns true if a valid request was received and no errors occurred.
124 bool ParseHeaders();
125
126 // Figures out whether the request is a GET or POST and what path is
127 // being requested.
128 bool ParseMethodAndPath(const char* begin, size_t len);
129
130 // Determines the length of the body and it's mime type.
131 bool ParseContentLengthAndType(const char* headers, size_t length);
132
133 protected:
134 RequestMethod method_;
135 size_t content_length_;
136 std::string content_type_;
137 std::string request_path_;
138 std::string request_headers_;
139 std::string data_;
140};
141
142// The server socket. Accepts connections and generates DataSocket instances
143// for each new connection.
144class ListeningSocket : public SocketBase {
145 public:
146 ListeningSocket() {}
147
148 bool Listen(unsigned short port);
149 DataSocket* Accept() const;
150};
151
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200152#endif // EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_