blob: 4429bc5a00f924a311c445a39740c8b8860848b2 [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) {}
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)
Yves Gerey665174f2018-06-19 15:03:05 +020063 : SocketBase(socket), method_(INVALID), content_length_(0) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +000064
Yves Gerey665174f2018-06-19 15:03:05 +020065 ~DataSocket() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066
67 static const char kCrossOriginAllowHeaders[];
68
69 bool headers_received() const { return method_ != INVALID; }
70
71 RequestMethod method() const { return method_; }
72
73 const std::string& request_path() const { return request_path_; }
74 std::string request_arguments() const;
75
76 const std::string& data() const { return data_; }
77
78 const std::string& content_type() const { return content_type_; }
79
80 size_t content_length() const { return content_length_; }
81
82 bool request_received() const {
83 return headers_received() && (method_ != POST || data_received());
84 }
85
86 bool data_received() const {
87 return method_ != POST || data_.length() >= content_length_;
88 }
89
90 // Checks if the request path (minus arguments) matches a given path.
91 bool PathEquals(const char* path) const;
92
93 // Called when we have received some data from clients.
94 // Returns false if an error occurred.
95 bool OnDataAvailable(bool* close_socket);
96
97 // Send a raw buffer of bytes.
98 bool Send(const std::string& data) const;
99
100 // Send an HTTP response. The |status| should start with a valid HTTP
101 // response code, followed by a string. E.g. "200 OK".
102 // If |connection_close| is set to true, an extra "Connection: close" HTTP
103 // header will be included. |content_type| is the mime content type, not
104 // including the "Content-Type: " string.
105 // |extra_headers| should be either empty or a list of headers where each
106 // header terminates with "\r\n".
107 // |data| is the body of the message. It's length will be specified via
108 // a "Content-Length" header.
Yves Gerey665174f2018-06-19 15:03:05 +0200109 bool Send(const std::string& status,
110 bool connection_close,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000111 const std::string& content_type,
Yves Gerey665174f2018-06-19 15:03:05 +0200112 const std::string& extra_headers,
113 const std::string& data) const;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000114
115 // Clears all held state and prepares the socket for receiving a new request.
116 void Clear();
117
118 protected:
119 // A fairly relaxed HTTP header parser. Parses the method, path and
120 // content length (POST only) of a request.
121 // Returns true if a valid request was received and no errors occurred.
122 bool ParseHeaders();
123
124 // Figures out whether the request is a GET or POST and what path is
125 // being requested.
126 bool ParseMethodAndPath(const char* begin, size_t len);
127
128 // Determines the length of the body and it's mime type.
129 bool ParseContentLengthAndType(const char* headers, size_t length);
130
131 protected:
132 RequestMethod method_;
133 size_t content_length_;
134 std::string content_type_;
135 std::string request_path_;
136 std::string request_headers_;
137 std::string data_;
138};
139
140// The server socket. Accepts connections and generates DataSocket instances
141// for each new connection.
142class ListeningSocket : public SocketBase {
143 public:
144 ListeningSocket() {}
145
146 bool Listen(unsigned short port);
147 DataSocket* Accept() const;
148};
149
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200150#endif // EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_