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 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 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