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