128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org/* 2a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis * Copyright 2011 The WebRTC Project Authors. All rights reserved. 328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 4a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis * Use of this source code is governed by a BSD-style license 5a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis * that can be found in the LICENSE file in the root of the source 6a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis * tree. An additional intellectual property rights grant can be found 7a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis * in the file PATENTS. All contributing project authors may 8a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis * be found in the AUTHORS file in the root of the source tree. 928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org */ 1028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 1128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <stdio.h> 1228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <stdlib.h> 1328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <string.h> 1428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 1528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <vector> 1628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 17a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis#include "webrtc/examples/peerconnection/server/data_socket.h" 18a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis#include "webrtc/examples/peerconnection/server/peer_channel.h" 19a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis#include "webrtc/examples/peerconnection/server/utils.h" 20a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/flags.h" 2128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 2228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgDEFINE_bool(help, false, "Prints this message"); 2328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgDEFINE_int(port, 8888, "The port on which to listen."); 2428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 2528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic const size_t kMaxConnections = (FD_SETSIZE - 2); 2628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 2728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid HandleBrowserRequest(DataSocket* ds, bool* quit) { 2828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org assert(ds && ds->valid()); 2928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org assert(quit); 3028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const std::string& path = ds->request_path(); 3228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org *quit = (path.compare("/quit") == 0); 3428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (*quit) { 3628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ds->Send("200 OK", true, "text/html", "", 3728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org "<html><body>Quitting...</body></html>"); 3828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else if (ds->method() == DataSocket::OPTIONS) { 3928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // We'll get this when a browsers do cross-resource-sharing requests. 4028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // The headers to allow cross-origin script support will be set inside 4128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Send. 4228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ds->Send("200 OK", true, "", "", ""); 4328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 4428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Here we could write some useful output back to the browser depending on 4528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // the path. 4628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org printf("Received an invalid request: %s\n", ds->request_path().c_str()); 4728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ds->Send("500 Sorry", true, "text/html", "", 4828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org "<html><body>Sorry, not yet implemented</body></html>"); 4928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 5028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 5128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 5228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgint main(int argc, char** argv) { 53d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org rtc::FlagList::SetFlagsFromCommandLine(&argc, argv, true); 5428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (FLAG_help) { 55d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org rtc::FlagList::Print(NULL, false); 5628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return 0; 5728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 5828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 5928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Abort if the user specifies a port that is outside the allowed 6028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // range [1, 65535]. 6128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if ((FLAG_port < 1) || (FLAG_port > 65535)) { 6228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org printf("Error: %i is not a valid port.\n", FLAG_port); 6328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return -1; 6428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 6528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 6628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ListeningSocket listener; 6728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!listener.Create()) { 6828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org printf("Failed to create server socket\n"); 6928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return -1; 7028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else if (!listener.Listen(FLAG_port)) { 7128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org printf("Failed to listen on server socket\n"); 7228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return -1; 7328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 7428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 7528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org printf("Server listening on port %i\n", FLAG_port); 7628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 7728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org PeerChannel clients; 7828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org typedef std::vector<DataSocket*> SocketArray; 7928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SocketArray sockets; 8028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool quit = false; 8128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org while (!quit) { 8228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org fd_set socket_set; 8328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org FD_ZERO(&socket_set); 8428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (listener.valid()) 8528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org FD_SET(listener.socket(), &socket_set); 8628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 8728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (SocketArray::iterator i = sockets.begin(); i != sockets.end(); ++i) 8828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org FD_SET((*i)->socket(), &socket_set); 8928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 9028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org struct timeval timeout = { 10, 0 }; 9128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (select(FD_SETSIZE, &socket_set, NULL, NULL, &timeout) == SOCKET_ERROR) { 9228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org printf("select failed\n"); 9328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 9428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 9528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 9628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (SocketArray::iterator i = sockets.begin(); i != sockets.end(); ++i) { 9728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org DataSocket* s = *i; 9828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool socket_done = true; 9928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (FD_ISSET(s->socket(), &socket_set)) { 10028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (s->OnDataAvailable(&socket_done) && s->request_received()) { 10128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ChannelMember* member = clients.Lookup(s); 10228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (member || PeerChannel::IsPeerConnection(s)) { 10328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!member) { 10428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (s->PathEquals("/sign_in")) { 10528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org clients.AddMember(s); 10628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 10728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org printf("No member found for: %s\n", 10828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org s->request_path().c_str()); 10928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org s->Send("500 Error", true, "text/plain", "", 11028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org "Peer most likely gone."); 11128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 11228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else if (member->is_wait_request(s)) { 11328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // no need to do anything. 11428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org socket_done = false; 11528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 11628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ChannelMember* target = clients.IsTargetedRequest(s); 11728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (target) { 11828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org member->ForwardRequestToPeer(s, target); 11928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else if (s->PathEquals("/sign_out")) { 12028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org s->Send("200 OK", true, "text/plain", "", ""); 12128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 12228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org printf("Couldn't find target for request: %s\n", 12328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org s->request_path().c_str()); 12428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org s->Send("500 Error", true, "text/plain", "", 12528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org "Peer most likely gone."); 12628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 12728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 12828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 12928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org HandleBrowserRequest(s, &quit); 13028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (quit) { 13128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org printf("Quitting...\n"); 13228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org FD_CLR(listener.socket(), &socket_set); 13328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org listener.Close(); 13428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org clients.CloseAll(); 13528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 13628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 13728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 13828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 13928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org socket_done = false; 14028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 14128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 14228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (socket_done) { 14328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org printf("Disconnecting socket\n"); 14428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org clients.OnClosing(s); 14528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org assert(s->valid()); // Close must not have been called yet. 14628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org FD_CLR(s->socket(), &socket_set); 14728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org delete (*i); 14828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org i = sockets.erase(i); 14928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (i == sockets.end()) 15028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 15128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 15228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 15328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 15428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org clients.CheckForTimeout(); 15528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 15628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (FD_ISSET(listener.socket(), &socket_set)) { 15728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org DataSocket* s = listener.Accept(); 15828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (sockets.size() >= kMaxConnections) { 15928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org delete s; // sorry, that's all we can take. 16028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org printf("Connection limit reached\n"); 16128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 16228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sockets.push_back(s); 16328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org printf("New connection...\n"); 16428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 16528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 16628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 16728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 16828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (SocketArray::iterator i = sockets.begin(); i != sockets.end(); ++i) 16928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org delete (*i); 17028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sockets.clear(); 17128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 17228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return 0; 17328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 174