tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

main.cc (6247B)


      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 <cstdio>
     12 #include <cstdlib>
     13 #include <ctime>
     14 #include <string>
     15 #include <vector>
     16 
     17 #include "absl/flags/flag.h"
     18 #include "absl/flags/parse.h"
     19 #include "absl/flags/usage.h"
     20 #include "examples/peerconnection/server/data_socket.h"
     21 #include "examples/peerconnection/server/peer_channel.h"
     22 #include "rtc_base/checks.h"
     23 
     24 #if defined(WEBRTC_POSIX)
     25 #include <sys/select.h>
     26 #endif
     27 
     28 // As of now, no components in peerconnection_server rely on WebRTC components
     29 // that change its behavior based on a field trial, so this flag is currently
     30 // unused. See peerconnection_client for example how this command line flag
     31 // can be used and propagated.
     32 ABSL_FLAG(
     33    std::string,
     34    force_fieldtrials,
     35    "",
     36    "Field trials control experimental features. This flag specifies the field "
     37    "trials in effect. E.g. running with "
     38    "--force_fieldtrials=WebRTC-FooFeature/Enabled/ "
     39    "will assign the group Enabled to field trial WebRTC-FooFeature. Multiple "
     40    "trials are separated by \"/\"");
     41 ABSL_FLAG(int, port, 8888, "default: 8888");
     42 
     43 static const size_t kMaxConnections = (FD_SETSIZE - 2);
     44 
     45 void HandleBrowserRequest(DataSocket* ds, bool* quit) {
     46  RTC_DCHECK(ds && ds->valid());
     47  RTC_DCHECK(quit);
     48 
     49  const std::string& path = ds->request_path();
     50 
     51  *quit = (path.compare("/quit") == 0);
     52 
     53  if (*quit) {
     54    ds->Send("200 OK", true, "text/html", "",
     55             "<html><body>Quitting...</body></html>");
     56  } else if (ds->method() == DataSocket::OPTIONS) {
     57    // We'll get this when a browsers do cross-resource-sharing requests.
     58    // The headers to allow cross-origin script support will be set inside
     59    // Send.
     60    ds->Send("200 OK", true, "", "", "");
     61  } else {
     62    // Here we could write some useful output back to the browser depending on
     63    // the path.
     64    printf("Received an invalid request: %s\n", ds->request_path().c_str());
     65    ds->Send("500 Sorry", true, "text/html", "",
     66             "<html><body>Sorry, not yet implemented</body></html>");
     67  }
     68 }
     69 
     70 int main(int argc, char* argv[]) {
     71  absl::SetProgramUsageMessage(
     72      "Example usage: ./peerconnection_server --port=8888\n");
     73  absl::ParseCommandLine(argc, argv);
     74 
     75  int port = absl::GetFlag(FLAGS_port);
     76 
     77  // Abort if the user specifies a port that is outside the allowed
     78  // range [1, 65535].
     79  if ((port < 1) || (port > 65535)) {
     80    printf("Error: %i is not a valid port.\n", port);
     81    return -1;
     82  }
     83 
     84  ListeningSocket listener;
     85  if (!listener.Create()) {
     86    printf("Failed to create server socket\n");
     87    return -1;
     88  } else if (!listener.Listen(port)) {
     89    printf("Failed to listen on server socket\n");
     90    return -1;
     91  }
     92 
     93  printf("Server listening on port %i\n", port);
     94 
     95  PeerChannel clients;
     96  typedef std::vector<DataSocket*> SocketArray;
     97  SocketArray sockets;
     98  bool quit = false;
     99  while (!quit) {
    100    fd_set socket_set;
    101    FD_ZERO(&socket_set);
    102    if (listener.valid())
    103      FD_SET(listener.socket(), &socket_set);
    104 
    105    for (SocketArray::iterator i = sockets.begin(); i != sockets.end(); ++i)
    106      FD_SET((*i)->socket(), &socket_set);
    107 
    108    struct timeval timeout = {.tv_sec = 10, .tv_usec = 0};
    109    if (select(FD_SETSIZE, &socket_set, nullptr, nullptr, &timeout) ==
    110        SOCKET_ERROR) {
    111      printf("select failed\n");
    112      break;
    113    }
    114 
    115    for (SocketArray::iterator i = sockets.begin(); i != sockets.end(); ++i) {
    116      DataSocket* s = *i;
    117      bool socket_done = true;
    118      if (FD_ISSET(s->socket(), &socket_set)) {
    119        if (s->OnDataAvailable(&socket_done) && s->request_received()) {
    120          ChannelMember* member = clients.Lookup(s);
    121          if (member || PeerChannel::IsPeerConnection(s)) {
    122            if (!member) {
    123              if (s->PathEquals("/sign_in")) {
    124                clients.AddMember(s);
    125              } else {
    126                printf("No member found for: %s\n", s->request_path().c_str());
    127                s->Send("500 Error", true, "text/plain", "",
    128                        "Peer most likely gone.");
    129              }
    130            } else if (member->is_wait_request(s)) {
    131              // no need to do anything.
    132              socket_done = false;
    133            } else {
    134              ChannelMember* target = clients.IsTargetedRequest(s);
    135              if (target) {
    136                member->ForwardRequestToPeer(s, target);
    137              } else if (s->PathEquals("/sign_out")) {
    138                s->Send("200 OK", true, "text/plain", "", "");
    139              } else {
    140                printf("Couldn't find target for request: %s\n",
    141                       s->request_path().c_str());
    142                s->Send("500 Error", true, "text/plain", "",
    143                        "Peer most likely gone.");
    144              }
    145            }
    146          } else {
    147            HandleBrowserRequest(s, &quit);
    148            if (quit) {
    149              printf("Quitting...\n");
    150              FD_CLR(listener.socket(), &socket_set);
    151              listener.Close();
    152              clients.CloseAll();
    153            }
    154          }
    155        }
    156      } else {
    157        socket_done = false;
    158      }
    159 
    160      if (socket_done) {
    161        printf("Disconnecting socket\n");
    162        clients.OnClosing(s);
    163        RTC_DCHECK(s->valid());  // Close must not have been called yet.
    164        FD_CLR(s->socket(), &socket_set);
    165        delete (*i);
    166        i = sockets.erase(i);
    167        if (i == sockets.end())
    168          break;
    169      }
    170    }
    171 
    172    clients.CheckForTimeout();
    173 
    174    if (FD_ISSET(listener.socket(), &socket_set)) {
    175      DataSocket* s = listener.Accept();
    176      if (sockets.size() >= kMaxConnections) {
    177        delete s;  // sorry, that's all we can take.
    178        printf("Connection limit reached\n");
    179      } else {
    180        sockets.push_back(s);
    181        printf("New connection...\n");
    182      }
    183    }
    184  }
    185 
    186  for (SocketArray::iterator i = sockets.begin(); i != sockets.end(); ++i)
    187    delete (*i);
    188  sockets.clear();
    189 
    190  return 0;
    191 }