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