blob: eafda60630311c1809a51af18d442faadfacfb25 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
Donald E Curtisa8736442015-08-05 15:48:13 -07002 * Copyright 2011 The WebRTC Project Authors. All rights reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
Donald E Curtisa8736442015-08-05 15:48:13 -07004 * 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.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14
15#include <vector>
16
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "examples/peerconnection/server/data_socket.h"
18#include "examples/peerconnection/server/peer_channel.h"
19#include "examples/peerconnection/server/utils.h"
20#include "rtc_tools/simple_command_line_parser.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000021
22static const size_t kMaxConnections = (FD_SETSIZE - 2);
23
24void HandleBrowserRequest(DataSocket* ds, bool* quit) {
25 assert(ds && ds->valid());
26 assert(quit);
27
28 const std::string& path = ds->request_path();
29
30 *quit = (path.compare("/quit") == 0);
31
32 if (*quit) {
33 ds->Send("200 OK", true, "text/html", "",
34 "<html><body>Quitting...</body></html>");
35 } else if (ds->method() == DataSocket::OPTIONS) {
36 // We'll get this when a browsers do cross-resource-sharing requests.
37 // The headers to allow cross-origin script support will be set inside
38 // Send.
39 ds->Send("200 OK", true, "", "", "");
40 } else {
41 // Here we could write some useful output back to the browser depending on
42 // the path.
43 printf("Received an invalid request: %s\n", ds->request_path().c_str());
44 ds->Send("500 Sorry", true, "text/html", "",
45 "<html><body>Sorry, not yet implemented</body></html>");
46 }
47}
48
Robin Raymond1c62ffa2017-12-03 16:45:56 -050049int main(int argc, char* argv[]) {
tkchinbad7b092016-03-11 20:45:16 -080050 std::string program_name = argv[0];
51 std::string usage = "Example usage: " + program_name + " --port=8888";
52 webrtc::test::CommandLineParser parser;
53 parser.Init(argc, argv);
54 parser.SetUsageMessage(usage);
55 parser.SetFlag("port", "8888");
56 parser.SetFlag("help", "false");
57 parser.ProcessFlags();
58
59 if (parser.GetFlag("help") == "true") {
60 parser.PrintUsageMessage();
henrike@webrtc.org28e20752013-07-10 00:45:36 +000061 return 0;
62 }
63
tkchinbad7b092016-03-11 20:45:16 -080064 int port = strtol((parser.GetFlag("port")).c_str(), NULL, 10);
65
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066 // Abort if the user specifies a port that is outside the allowed
67 // range [1, 65535].
tkchinbad7b092016-03-11 20:45:16 -080068 if ((port < 1) || (port > 65535)) {
69 printf("Error: %i is not a valid port.\n", port);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000070 return -1;
71 }
72
73 ListeningSocket listener;
74 if (!listener.Create()) {
75 printf("Failed to create server socket\n");
76 return -1;
tkchinbad7b092016-03-11 20:45:16 -080077 } else if (!listener.Listen(port)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000078 printf("Failed to listen on server socket\n");
79 return -1;
80 }
81
tkchinbad7b092016-03-11 20:45:16 -080082 printf("Server listening on port %i\n", port);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000083
84 PeerChannel clients;
85 typedef std::vector<DataSocket*> SocketArray;
86 SocketArray sockets;
87 bool quit = false;
88 while (!quit) {
89 fd_set socket_set;
90 FD_ZERO(&socket_set);
91 if (listener.valid())
92 FD_SET(listener.socket(), &socket_set);
93
94 for (SocketArray::iterator i = sockets.begin(); i != sockets.end(); ++i)
95 FD_SET((*i)->socket(), &socket_set);
96
Yves Gerey665174f2018-06-19 15:03:05 +020097 struct timeval timeout = {10, 0};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000098 if (select(FD_SETSIZE, &socket_set, NULL, NULL, &timeout) == SOCKET_ERROR) {
99 printf("select failed\n");
100 break;
101 }
102
103 for (SocketArray::iterator i = sockets.begin(); i != sockets.end(); ++i) {
104 DataSocket* s = *i;
105 bool socket_done = true;
106 if (FD_ISSET(s->socket(), &socket_set)) {
107 if (s->OnDataAvailable(&socket_done) && s->request_received()) {
108 ChannelMember* member = clients.Lookup(s);
109 if (member || PeerChannel::IsPeerConnection(s)) {
110 if (!member) {
111 if (s->PathEquals("/sign_in")) {
112 clients.AddMember(s);
113 } else {
Yves Gerey665174f2018-06-19 15:03:05 +0200114 printf("No member found for: %s\n", s->request_path().c_str());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000115 s->Send("500 Error", true, "text/plain", "",
116 "Peer most likely gone.");
117 }
118 } else if (member->is_wait_request(s)) {
119 // no need to do anything.
120 socket_done = false;
121 } else {
122 ChannelMember* target = clients.IsTargetedRequest(s);
123 if (target) {
124 member->ForwardRequestToPeer(s, target);
125 } else if (s->PathEquals("/sign_out")) {
126 s->Send("200 OK", true, "text/plain", "", "");
127 } else {
128 printf("Couldn't find target for request: %s\n",
Yves Gerey665174f2018-06-19 15:03:05 +0200129 s->request_path().c_str());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000130 s->Send("500 Error", true, "text/plain", "",
131 "Peer most likely gone.");
132 }
133 }
134 } else {
135 HandleBrowserRequest(s, &quit);
136 if (quit) {
137 printf("Quitting...\n");
138 FD_CLR(listener.socket(), &socket_set);
139 listener.Close();
140 clients.CloseAll();
141 }
142 }
143 }
144 } else {
145 socket_done = false;
146 }
147
148 if (socket_done) {
149 printf("Disconnecting socket\n");
150 clients.OnClosing(s);
151 assert(s->valid()); // Close must not have been called yet.
152 FD_CLR(s->socket(), &socket_set);
153 delete (*i);
154 i = sockets.erase(i);
155 if (i == sockets.end())
156 break;
157 }
158 }
159
160 clients.CheckForTimeout();
161
162 if (FD_ISSET(listener.socket(), &socket_set)) {
163 DataSocket* s = listener.Accept();
164 if (sockets.size() >= kMaxConnections) {
165 delete s; // sorry, that's all we can take.
166 printf("Connection limit reached\n");
167 } else {
168 sockets.push_back(s);
169 printf("New connection...\n");
170 }
171 }
172 }
173
174 for (SocketArray::iterator i = sockets.begin(); i != sockets.end(); ++i)
175 delete (*i);
176 sockets.clear();
177
178 return 0;
179}