• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 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 EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_
12 #define EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_
13 
14 #ifdef WIN32
15 #include <winsock2.h>
16 typedef int socklen_t;
17 typedef SOCKET NativeSocket;
18 #else
19 #include <netinet/in.h>
20 #include <sys/select.h>
21 #include <sys/socket.h>
22 #define closesocket close
23 typedef int NativeSocket;
24 
25 #ifndef SOCKET_ERROR
26 #define SOCKET_ERROR (-1)
27 #endif
28 
29 #ifndef INVALID_SOCKET
30 #define INVALID_SOCKET static_cast<NativeSocket>(-1)
31 #endif
32 #endif
33 
34 #include <string>
35 
36 class SocketBase {
37  public:
SocketBase()38   SocketBase() : socket_(INVALID_SOCKET) {}
SocketBase(NativeSocket socket)39   explicit SocketBase(NativeSocket socket) : socket_(socket) {}
~SocketBase()40   ~SocketBase() { Close(); }
41 
socket()42   NativeSocket socket() const { return socket_; }
valid()43   bool valid() const { return socket_ != INVALID_SOCKET; }
44 
45   bool Create();
46   void Close();
47 
48  protected:
49   NativeSocket socket_;
50 };
51 
52 // Represents an HTTP server socket.
53 class DataSocket : public SocketBase {
54  public:
55   enum RequestMethod {
56     INVALID,
57     GET,
58     POST,
59     OPTIONS,
60   };
61 
DataSocket(NativeSocket socket)62   explicit DataSocket(NativeSocket socket)
63       : SocketBase(socket), method_(INVALID), content_length_(0) {}
64 
~DataSocket()65   ~DataSocket() {}
66 
67   static const char kCrossOriginAllowHeaders[];
68 
headers_received()69   bool headers_received() const { return method_ != INVALID; }
70 
method()71   RequestMethod method() const { return method_; }
72 
request_path()73   const std::string& request_path() const { return request_path_; }
74   std::string request_arguments() const;
75 
data()76   const std::string& data() const { return data_; }
77 
content_type()78   const std::string& content_type() const { return content_type_; }
79 
content_length()80   size_t content_length() const { return content_length_; }
81 
request_received()82   bool request_received() const {
83     return headers_received() && (method_ != POST || data_received());
84   }
85 
data_received()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.
109   bool Send(const std::string& status,
110             bool connection_close,
111             const std::string& content_type,
112             const std::string& extra_headers,
113             const std::string& data) const;
114 
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.
142 class ListeningSocket : public SocketBase {
143  public:
ListeningSocket()144   ListeningSocket() {}
145 
146   bool Listen(unsigned short port);
147   DataSocket* Accept() const;
148 };
149 
150 #endif  // EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_
151