xref: /aosp_15_r20/external/webrtc/examples/peerconnection/server/main.cc (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 #include <stdio.h>
12*d9f75844SAndroid Build Coastguard Worker #include <stdlib.h>
13*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_POSIX)
14*d9f75844SAndroid Build Coastguard Worker #include <sys/select.h>
15*d9f75844SAndroid Build Coastguard Worker #endif
16*d9f75844SAndroid Build Coastguard Worker #include <time.h>
17*d9f75844SAndroid Build Coastguard Worker 
18*d9f75844SAndroid Build Coastguard Worker #include <string>
19*d9f75844SAndroid Build Coastguard Worker #include <vector>
20*d9f75844SAndroid Build Coastguard Worker 
21*d9f75844SAndroid Build Coastguard Worker #include "absl/flags/flag.h"
22*d9f75844SAndroid Build Coastguard Worker #include "absl/flags/parse.h"
23*d9f75844SAndroid Build Coastguard Worker #include "absl/flags/usage.h"
24*d9f75844SAndroid Build Coastguard Worker #include "examples/peerconnection/server/data_socket.h"
25*d9f75844SAndroid Build Coastguard Worker #include "examples/peerconnection/server/peer_channel.h"
26*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
27*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/field_trial.h"
28*d9f75844SAndroid Build Coastguard Worker #include "test/field_trial.h"
29*d9f75844SAndroid Build Coastguard Worker 
30*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(
31*d9f75844SAndroid Build Coastguard Worker     std::string,
32*d9f75844SAndroid Build Coastguard Worker     force_fieldtrials,
33*d9f75844SAndroid Build Coastguard Worker     "",
34*d9f75844SAndroid Build Coastguard Worker     "Field trials control experimental features. This flag specifies the field "
35*d9f75844SAndroid Build Coastguard Worker     "trials in effect. E.g. running with "
36*d9f75844SAndroid Build Coastguard Worker     "--force_fieldtrials=WebRTC-FooFeature/Enabled/ "
37*d9f75844SAndroid Build Coastguard Worker     "will assign the group Enabled to field trial WebRTC-FooFeature. Multiple "
38*d9f75844SAndroid Build Coastguard Worker     "trials are separated by \"/\"");
39*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(int, port, 8888, "default: 8888");
40*d9f75844SAndroid Build Coastguard Worker 
41*d9f75844SAndroid Build Coastguard Worker static const size_t kMaxConnections = (FD_SETSIZE - 2);
42*d9f75844SAndroid Build Coastguard Worker 
HandleBrowserRequest(DataSocket * ds,bool * quit)43*d9f75844SAndroid Build Coastguard Worker void HandleBrowserRequest(DataSocket* ds, bool* quit) {
44*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(ds && ds->valid());
45*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(quit);
46*d9f75844SAndroid Build Coastguard Worker 
47*d9f75844SAndroid Build Coastguard Worker   const std::string& path = ds->request_path();
48*d9f75844SAndroid Build Coastguard Worker 
49*d9f75844SAndroid Build Coastguard Worker   *quit = (path.compare("/quit") == 0);
50*d9f75844SAndroid Build Coastguard Worker 
51*d9f75844SAndroid Build Coastguard Worker   if (*quit) {
52*d9f75844SAndroid Build Coastguard Worker     ds->Send("200 OK", true, "text/html", "",
53*d9f75844SAndroid Build Coastguard Worker              "<html><body>Quitting...</body></html>");
54*d9f75844SAndroid Build Coastguard Worker   } else if (ds->method() == DataSocket::OPTIONS) {
55*d9f75844SAndroid Build Coastguard Worker     // We'll get this when a browsers do cross-resource-sharing requests.
56*d9f75844SAndroid Build Coastguard Worker     // The headers to allow cross-origin script support will be set inside
57*d9f75844SAndroid Build Coastguard Worker     // Send.
58*d9f75844SAndroid Build Coastguard Worker     ds->Send("200 OK", true, "", "", "");
59*d9f75844SAndroid Build Coastguard Worker   } else {
60*d9f75844SAndroid Build Coastguard Worker     // Here we could write some useful output back to the browser depending on
61*d9f75844SAndroid Build Coastguard Worker     // the path.
62*d9f75844SAndroid Build Coastguard Worker     printf("Received an invalid request: %s\n", ds->request_path().c_str());
63*d9f75844SAndroid Build Coastguard Worker     ds->Send("500 Sorry", true, "text/html", "",
64*d9f75844SAndroid Build Coastguard Worker              "<html><body>Sorry, not yet implemented</body></html>");
65*d9f75844SAndroid Build Coastguard Worker   }
66*d9f75844SAndroid Build Coastguard Worker }
67*d9f75844SAndroid Build Coastguard Worker 
main(int argc,char * argv[])68*d9f75844SAndroid Build Coastguard Worker int main(int argc, char* argv[]) {
69*d9f75844SAndroid Build Coastguard Worker   absl::SetProgramUsageMessage(
70*d9f75844SAndroid Build Coastguard Worker       "Example usage: ./peerconnection_server --port=8888\n");
71*d9f75844SAndroid Build Coastguard Worker   absl::ParseCommandLine(argc, argv);
72*d9f75844SAndroid Build Coastguard Worker 
73*d9f75844SAndroid Build Coastguard Worker   // InitFieldTrialsFromString stores the char*, so the char array must outlive
74*d9f75844SAndroid Build Coastguard Worker   // the application.
75*d9f75844SAndroid Build Coastguard Worker   const std::string force_field_trials = absl::GetFlag(FLAGS_force_fieldtrials);
76*d9f75844SAndroid Build Coastguard Worker   webrtc::field_trial::InitFieldTrialsFromString(force_field_trials.c_str());
77*d9f75844SAndroid Build Coastguard Worker 
78*d9f75844SAndroid Build Coastguard Worker   int port = absl::GetFlag(FLAGS_port);
79*d9f75844SAndroid Build Coastguard Worker 
80*d9f75844SAndroid Build Coastguard Worker   // Abort if the user specifies a port that is outside the allowed
81*d9f75844SAndroid Build Coastguard Worker   // range [1, 65535].
82*d9f75844SAndroid Build Coastguard Worker   if ((port < 1) || (port > 65535)) {
83*d9f75844SAndroid Build Coastguard Worker     printf("Error: %i is not a valid port.\n", port);
84*d9f75844SAndroid Build Coastguard Worker     return -1;
85*d9f75844SAndroid Build Coastguard Worker   }
86*d9f75844SAndroid Build Coastguard Worker 
87*d9f75844SAndroid Build Coastguard Worker   ListeningSocket listener;
88*d9f75844SAndroid Build Coastguard Worker   if (!listener.Create()) {
89*d9f75844SAndroid Build Coastguard Worker     printf("Failed to create server socket\n");
90*d9f75844SAndroid Build Coastguard Worker     return -1;
91*d9f75844SAndroid Build Coastguard Worker   } else if (!listener.Listen(port)) {
92*d9f75844SAndroid Build Coastguard Worker     printf("Failed to listen on server socket\n");
93*d9f75844SAndroid Build Coastguard Worker     return -1;
94*d9f75844SAndroid Build Coastguard Worker   }
95*d9f75844SAndroid Build Coastguard Worker 
96*d9f75844SAndroid Build Coastguard Worker   printf("Server listening on port %i\n", port);
97*d9f75844SAndroid Build Coastguard Worker 
98*d9f75844SAndroid Build Coastguard Worker   PeerChannel clients;
99*d9f75844SAndroid Build Coastguard Worker   typedef std::vector<DataSocket*> SocketArray;
100*d9f75844SAndroid Build Coastguard Worker   SocketArray sockets;
101*d9f75844SAndroid Build Coastguard Worker   bool quit = false;
102*d9f75844SAndroid Build Coastguard Worker   while (!quit) {
103*d9f75844SAndroid Build Coastguard Worker     fd_set socket_set;
104*d9f75844SAndroid Build Coastguard Worker     FD_ZERO(&socket_set);
105*d9f75844SAndroid Build Coastguard Worker     if (listener.valid())
106*d9f75844SAndroid Build Coastguard Worker       FD_SET(listener.socket(), &socket_set);
107*d9f75844SAndroid Build Coastguard Worker 
108*d9f75844SAndroid Build Coastguard Worker     for (SocketArray::iterator i = sockets.begin(); i != sockets.end(); ++i)
109*d9f75844SAndroid Build Coastguard Worker       FD_SET((*i)->socket(), &socket_set);
110*d9f75844SAndroid Build Coastguard Worker 
111*d9f75844SAndroid Build Coastguard Worker     struct timeval timeout = {10, 0};
112*d9f75844SAndroid Build Coastguard Worker     if (select(FD_SETSIZE, &socket_set, NULL, NULL, &timeout) == SOCKET_ERROR) {
113*d9f75844SAndroid Build Coastguard Worker       printf("select failed\n");
114*d9f75844SAndroid Build Coastguard Worker       break;
115*d9f75844SAndroid Build Coastguard Worker     }
116*d9f75844SAndroid Build Coastguard Worker 
117*d9f75844SAndroid Build Coastguard Worker     for (SocketArray::iterator i = sockets.begin(); i != sockets.end(); ++i) {
118*d9f75844SAndroid Build Coastguard Worker       DataSocket* s = *i;
119*d9f75844SAndroid Build Coastguard Worker       bool socket_done = true;
120*d9f75844SAndroid Build Coastguard Worker       if (FD_ISSET(s->socket(), &socket_set)) {
121*d9f75844SAndroid Build Coastguard Worker         if (s->OnDataAvailable(&socket_done) && s->request_received()) {
122*d9f75844SAndroid Build Coastguard Worker           ChannelMember* member = clients.Lookup(s);
123*d9f75844SAndroid Build Coastguard Worker           if (member || PeerChannel::IsPeerConnection(s)) {
124*d9f75844SAndroid Build Coastguard Worker             if (!member) {
125*d9f75844SAndroid Build Coastguard Worker               if (s->PathEquals("/sign_in")) {
126*d9f75844SAndroid Build Coastguard Worker                 clients.AddMember(s);
127*d9f75844SAndroid Build Coastguard Worker               } else {
128*d9f75844SAndroid Build Coastguard Worker                 printf("No member found for: %s\n", s->request_path().c_str());
129*d9f75844SAndroid Build Coastguard Worker                 s->Send("500 Error", true, "text/plain", "",
130*d9f75844SAndroid Build Coastguard Worker                         "Peer most likely gone.");
131*d9f75844SAndroid Build Coastguard Worker               }
132*d9f75844SAndroid Build Coastguard Worker             } else if (member->is_wait_request(s)) {
133*d9f75844SAndroid Build Coastguard Worker               // no need to do anything.
134*d9f75844SAndroid Build Coastguard Worker               socket_done = false;
135*d9f75844SAndroid Build Coastguard Worker             } else {
136*d9f75844SAndroid Build Coastguard Worker               ChannelMember* target = clients.IsTargetedRequest(s);
137*d9f75844SAndroid Build Coastguard Worker               if (target) {
138*d9f75844SAndroid Build Coastguard Worker                 member->ForwardRequestToPeer(s, target);
139*d9f75844SAndroid Build Coastguard Worker               } else if (s->PathEquals("/sign_out")) {
140*d9f75844SAndroid Build Coastguard Worker                 s->Send("200 OK", true, "text/plain", "", "");
141*d9f75844SAndroid Build Coastguard Worker               } else {
142*d9f75844SAndroid Build Coastguard Worker                 printf("Couldn't find target for request: %s\n",
143*d9f75844SAndroid Build Coastguard Worker                        s->request_path().c_str());
144*d9f75844SAndroid Build Coastguard Worker                 s->Send("500 Error", true, "text/plain", "",
145*d9f75844SAndroid Build Coastguard Worker                         "Peer most likely gone.");
146*d9f75844SAndroid Build Coastguard Worker               }
147*d9f75844SAndroid Build Coastguard Worker             }
148*d9f75844SAndroid Build Coastguard Worker           } else {
149*d9f75844SAndroid Build Coastguard Worker             HandleBrowserRequest(s, &quit);
150*d9f75844SAndroid Build Coastguard Worker             if (quit) {
151*d9f75844SAndroid Build Coastguard Worker               printf("Quitting...\n");
152*d9f75844SAndroid Build Coastguard Worker               FD_CLR(listener.socket(), &socket_set);
153*d9f75844SAndroid Build Coastguard Worker               listener.Close();
154*d9f75844SAndroid Build Coastguard Worker               clients.CloseAll();
155*d9f75844SAndroid Build Coastguard Worker             }
156*d9f75844SAndroid Build Coastguard Worker           }
157*d9f75844SAndroid Build Coastguard Worker         }
158*d9f75844SAndroid Build Coastguard Worker       } else {
159*d9f75844SAndroid Build Coastguard Worker         socket_done = false;
160*d9f75844SAndroid Build Coastguard Worker       }
161*d9f75844SAndroid Build Coastguard Worker 
162*d9f75844SAndroid Build Coastguard Worker       if (socket_done) {
163*d9f75844SAndroid Build Coastguard Worker         printf("Disconnecting socket\n");
164*d9f75844SAndroid Build Coastguard Worker         clients.OnClosing(s);
165*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK(s->valid());  // Close must not have been called yet.
166*d9f75844SAndroid Build Coastguard Worker         FD_CLR(s->socket(), &socket_set);
167*d9f75844SAndroid Build Coastguard Worker         delete (*i);
168*d9f75844SAndroid Build Coastguard Worker         i = sockets.erase(i);
169*d9f75844SAndroid Build Coastguard Worker         if (i == sockets.end())
170*d9f75844SAndroid Build Coastguard Worker           break;
171*d9f75844SAndroid Build Coastguard Worker       }
172*d9f75844SAndroid Build Coastguard Worker     }
173*d9f75844SAndroid Build Coastguard Worker 
174*d9f75844SAndroid Build Coastguard Worker     clients.CheckForTimeout();
175*d9f75844SAndroid Build Coastguard Worker 
176*d9f75844SAndroid Build Coastguard Worker     if (FD_ISSET(listener.socket(), &socket_set)) {
177*d9f75844SAndroid Build Coastguard Worker       DataSocket* s = listener.Accept();
178*d9f75844SAndroid Build Coastguard Worker       if (sockets.size() >= kMaxConnections) {
179*d9f75844SAndroid Build Coastguard Worker         delete s;  // sorry, that's all we can take.
180*d9f75844SAndroid Build Coastguard Worker         printf("Connection limit reached\n");
181*d9f75844SAndroid Build Coastguard Worker       } else {
182*d9f75844SAndroid Build Coastguard Worker         sockets.push_back(s);
183*d9f75844SAndroid Build Coastguard Worker         printf("New connection...\n");
184*d9f75844SAndroid Build Coastguard Worker       }
185*d9f75844SAndroid Build Coastguard Worker     }
186*d9f75844SAndroid Build Coastguard Worker   }
187*d9f75844SAndroid Build Coastguard Worker 
188*d9f75844SAndroid Build Coastguard Worker   for (SocketArray::iterator i = sockets.begin(); i != sockets.end(); ++i)
189*d9f75844SAndroid Build Coastguard Worker     delete (*i);
190*d9f75844SAndroid Build Coastguard Worker   sockets.clear();
191*d9f75844SAndroid Build Coastguard Worker 
192*d9f75844SAndroid Build Coastguard Worker   return 0;
193*d9f75844SAndroid Build Coastguard Worker }
194