• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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