xref: /aosp_15_r20/external/webrtc/examples/peerconnection/server/data_socket.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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) {}
40   SocketBase(SocketBase& other) = delete;
41   SocketBase& operator=(const SocketBase& other) = delete;
~SocketBase()42   ~SocketBase() { Close(); }
43 
socket()44   NativeSocket socket() const { return socket_; }
valid()45   bool valid() const { return socket_ != INVALID_SOCKET; }
46 
47   bool Create();
48   void Close();
49 
50  protected:
51   NativeSocket socket_;
52 };
53 
54 // Represents an HTTP server socket.
55 class DataSocket : public SocketBase {
56  public:
57   enum RequestMethod {
58     INVALID,
59     GET,
60     POST,
61     OPTIONS,
62   };
63 
DataSocket(NativeSocket socket)64   explicit DataSocket(NativeSocket socket)
65       : SocketBase(socket), method_(INVALID), content_length_(0) {}
66 
~DataSocket()67   ~DataSocket() {}
68 
69   static const char kCrossOriginAllowHeaders[];
70 
headers_received()71   bool headers_received() const { return method_ != INVALID; }
72 
method()73   RequestMethod method() const { return method_; }
74 
request_path()75   const std::string& request_path() const { return request_path_; }
76   std::string request_arguments() const;
77 
data()78   const std::string& data() const { return data_; }
79 
content_type()80   const std::string& content_type() const { return content_type_; }
81 
content_length()82   size_t content_length() const { return content_length_; }
83 
request_received()84   bool request_received() const {
85     return headers_received() && (method_ != POST || data_received());
86   }
87 
data_received()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.
111   bool Send(const std::string& status,
112             bool connection_close,
113             const std::string& content_type,
114             const std::string& extra_headers,
115             const std::string& data) const;
116 
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.
144 class ListeningSocket : public SocketBase {
145  public:
ListeningSocket()146   ListeningSocket() {}
147 
148   bool Listen(unsigned short port);
149   DataSocket* Accept() const;
150 };
151 
152 #endif  // EXAMPLES_PEERCONNECTION_SERVER_DATA_SOCKET_H_
153