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