blob: bafa5d39c2f1633a40cd3648310150fe5a59c7c1 [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
Yves Gerey665174f2018-06-19 15:03:05 +020030#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:
Yves Gerey665174f2018-06-19 15:03:05 +020038 SocketBase() : socket_(INVALID_SOCKET) {}
39 explicit SocketBase(NativeSocket socket) : socket_(socket) {}
Philipp Hanckec91c2f52021-07-22 13:51:21 +020040 SocketBase(SocketBase& other) = delete;
41 SocketBase& operator=(const SocketBase& other) = delete;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000042 ~SocketBase() { Close(); }
43
tommi@webrtc.org2c13f652014-11-28 10:37:31 +000044 NativeSocket socket() const { return socket_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000045 bool valid() const { return socket_ != INVALID_SOCKET; }
46
47 bool Create();
48 void Close();
49
50 protected:
tommi@webrtc.org2c13f652014-11-28 10:37:31 +000051 NativeSocket socket_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000052};
53
54// Represents an HTTP server socket.
55class DataSocket : public SocketBase {
56 public:
57 enum RequestMethod {
58 INVALID,
59 GET,
60 POST,
61 OPTIONS,
62 };
63
tommi@webrtc.org2c13f652014-11-28 10:37:31 +000064 explicit DataSocket(NativeSocket socket)
Yves Gerey665174f2018-06-19 15:03:05 +020065 : SocketBase(socket), method_(INVALID), content_length_(0) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066
Yves Gerey665174f2018-06-19 15:03:05 +020067 ~DataSocket() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +000068
69 static const char kCrossOriginAllowHeaders[];
70
71 bool headers_received() const { return method_ != INVALID; }
72
73 RequestMethod method() const { return method_; }
74
75 const std::string& request_path() const { return request_path_; }
76 std::string request_arguments() const;
77
78 const std::string& data() const { return data_; }
79
80 const std::string& content_type() const { return content_type_; }
81
82 size_t content_length() const { return content_length_; }
83
84 bool request_received() const {
85 return headers_received() && (method_ != POST || data_received());
86 }
87
88 bool data_received() const {
89 return method_ != POST || data_.length() >= content_length_;
90 }
91
92 // Checks if the request path (minus arguments) matches a given path.
93 bool PathEquals(const char* path) const;
94
95 // Called when we have received some data from clients.
96 // Returns false if an error occurred.
97 bool OnDataAvailable(bool* close_socket);
98
99 // Send a raw buffer of bytes.
100 bool Send(const std::string& data) const;
101
102 // Send an HTTP response. The |status| should start with a valid HTTP
103 // response code, followed by a string. E.g. "200 OK".
104 // If |connection_close| is set to true, an extra "Connection: close" HTTP
105 // header will be included. |content_type| is the mime content type, not
106 // including the "Content-Type: " string.
107 // |extra_headers| should be either empty or a list of headers where each
108 // header terminates with "\r\n".
109 // |data| is the body of the message. It's length will be specified via
110 // a "Content-Length" header.
Yves Gerey665174f2018-06-19 15:03:05 +0200111 bool Send(const std::string& status,
112 bool connection_close,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000113 const std::string& content_type,
Yves Gerey665174f2018-06-19 15:03:05 +0200114 const std::string& extra_headers,
115 const std::string& data) const;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000116
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_