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