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 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include <vector>
16
17 #include "webrtc/examples/peerconnection/server/data_socket.h"
18 #include "webrtc/examples/peerconnection/server/peer_channel.h"
19 #include "webrtc/examples/peerconnection/server/utils.h"
20 #include "webrtc/base/flags.h"
21
22 DEFINE_bool(help, false, "Prints this message");
23 DEFINE_int(port, 8888, "The port on which to listen.");
24
25 static const size_t kMaxConnections = (FD_SETSIZE - 2);
26
HandleBrowserRequest(DataSocket * ds,bool * quit)27 void HandleBrowserRequest(DataSocket* ds, bool* quit) {
28 assert(ds && ds->valid());
29 assert(quit);
30
31 const std::string& path = ds->request_path();
32
33 *quit = (path.compare("/quit") == 0);
34
35 if (*quit) {
36 ds->Send("200 OK", true, "text/html", "",
37 "<html><body>Quitting...</body></html>");
38 } else if (ds->method() == DataSocket::OPTIONS) {
39 // We'll get this when a browsers do cross-resource-sharing requests.
40 // The headers to allow cross-origin script support will be set inside
41 // Send.
42 ds->Send("200 OK", true, "", "", "");
43 } else {
44 // Here we could write some useful output back to the browser depending on
45 // the path.
46 printf("Received an invalid request: %s\n", ds->request_path().c_str());
47 ds->Send("500 Sorry", true, "text/html", "",
48 "<html><body>Sorry, not yet implemented</body></html>");
49 }
50 }
51
main(int argc,char ** argv)52 int main(int argc, char** argv) {
53 rtc::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
54 if (FLAG_help) {
55 rtc::FlagList::Print(NULL, false);
56 return 0;
57 }
58
59 // Abort if the user specifies a port that is outside the allowed
60 // range [1, 65535].
61 if ((FLAG_port < 1) || (FLAG_port > 65535)) {
62 printf("Error: %i is not a valid port.\n", FLAG_port);
63 return -1;
64 }
65
66 ListeningSocket listener;
67 if (!listener.Create()) {
68 printf("Failed to create server socket\n");
69 return -1;
70 } else if (!listener.Listen(FLAG_port)) {
71 printf("Failed to listen on server socket\n");
72 return -1;
73 }
74
75 printf("Server listening on port %i\n", FLAG_port);
76
77 PeerChannel clients;
78 typedef std::vector<DataSocket*> SocketArray;
79 SocketArray sockets;
80 bool quit = false;
81 while (!quit) {
82 fd_set socket_set;
83 FD_ZERO(&socket_set);
84 if (listener.valid())
85 FD_SET(listener.socket(), &socket_set);
86
87 for (SocketArray::iterator i = sockets.begin(); i != sockets.end(); ++i)
88 FD_SET((*i)->socket(), &socket_set);
89
90 struct timeval timeout = { 10, 0 };
91 if (select(FD_SETSIZE, &socket_set, NULL, NULL, &timeout) == SOCKET_ERROR) {
92 printf("select failed\n");
93 break;
94 }
95
96 for (SocketArray::iterator i = sockets.begin(); i != sockets.end(); ++i) {
97 DataSocket* s = *i;
98 bool socket_done = true;
99 if (FD_ISSET(s->socket(), &socket_set)) {
100 if (s->OnDataAvailable(&socket_done) && s->request_received()) {
101 ChannelMember* member = clients.Lookup(s);
102 if (member || PeerChannel::IsPeerConnection(s)) {
103 if (!member) {
104 if (s->PathEquals("/sign_in")) {
105 clients.AddMember(s);
106 } else {
107 printf("No member found for: %s\n",
108 s->request_path().c_str());
109 s->Send("500 Error", true, "text/plain", "",
110 "Peer most likely gone.");
111 }
112 } else if (member->is_wait_request(s)) {
113 // no need to do anything.
114 socket_done = false;
115 } else {
116 ChannelMember* target = clients.IsTargetedRequest(s);
117 if (target) {
118 member->ForwardRequestToPeer(s, target);
119 } else if (s->PathEquals("/sign_out")) {
120 s->Send("200 OK", true, "text/plain", "", "");
121 } else {
122 printf("Couldn't find target for request: %s\n",
123 s->request_path().c_str());
124 s->Send("500 Error", true, "text/plain", "",
125 "Peer most likely gone.");
126 }
127 }
128 } else {
129 HandleBrowserRequest(s, &quit);
130 if (quit) {
131 printf("Quitting...\n");
132 FD_CLR(listener.socket(), &socket_set);
133 listener.Close();
134 clients.CloseAll();
135 }
136 }
137 }
138 } else {
139 socket_done = false;
140 }
141
142 if (socket_done) {
143 printf("Disconnecting socket\n");
144 clients.OnClosing(s);
145 assert(s->valid()); // Close must not have been called yet.
146 FD_CLR(s->socket(), &socket_set);
147 delete (*i);
148 i = sockets.erase(i);
149 if (i == sockets.end())
150 break;
151 }
152 }
153
154 clients.CheckForTimeout();
155
156 if (FD_ISSET(listener.socket(), &socket_set)) {
157 DataSocket* s = listener.Accept();
158 if (sockets.size() >= kMaxConnections) {
159 delete s; // sorry, that's all we can take.
160 printf("Connection limit reached\n");
161 } else {
162 sockets.push_back(s);
163 printf("New connection...\n");
164 }
165 }
166 }
167
168 for (SocketArray::iterator i = sockets.begin(); i != sockets.end(); ++i)
169 delete (*i);
170 sockets.clear();
171
172 return 0;
173 }
174