10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/* 20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle 30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2011, Google Inc. 40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without 60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met: 70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * this list of conditions and the following disclaimer. 100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * this list of conditions and the following disclaimer in the documentation 120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * and/or other materials provided with the distribution. 130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 3. The name of the author may not be used to endorse or promote products 140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * derived from this software without specific prior written permission. 150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */ 270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/examples/peerconnection/server/peer_channel.h" 290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <stdio.h> 310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <stdlib.h> 320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <string.h> 330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <algorithm> 350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/examples/peerconnection/server/data_socket.h" 370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/examples/peerconnection/server/utils.h" 380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Set to the peer id of the originator when messages are being 400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// exchanged between peers, but set to the id of the receiving peer 410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// itself when notifications are sent from the server about the state 420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// of other peers. 430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// WORKAROUND: Since support for CORS varies greatly from one browser to the 450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// next, we don't use a custom name for our peer-id header (originally it was 460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// "X-Peer-Id: "). Instead, we use a "simple header", "Pragma" which should 470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// always be exposed to CORS requests. There is a special CORS header devoted 480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// to exposing proprietary headers (Access-Control-Expose-Headers), however 490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// at this point it is not working correctly in some popular browsers. 500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const char kPeerIdHeader[] = "Pragma: "; 510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const char* kRequestPaths[] = { 530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "/wait", "/sign_out", "/message", 540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}; 550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgenum RequestPathIndex { 570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org kWait, 580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org kSignOut, 590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org kMessage, 600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}; 610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 62b6ef00f11f5d79b02007907c14a1ae1cd8de8028tommi@webrtc.orgconst size_t kMaxNameLength = 512; 63b6ef00f11f5d79b02007907c14a1ae1cd8de8028tommi@webrtc.org 640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// ChannelMember 660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint ChannelMember::s_member_id_ = 0; 690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgChannelMember::ChannelMember(DataSocket* socket) 710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org : waiting_socket_(NULL), id_(++s_member_id_), 720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org connected_(true), timestamp_(time(NULL)) { 730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(socket); 740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(socket->method() == DataSocket::GET); 750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(socket->PathEquals("/sign_in")); 760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org name_ = socket->request_arguments(); // TODO: urldecode 77b6ef00f11f5d79b02007907c14a1ae1cd8de8028tommi@webrtc.org if (name_.empty()) 780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org name_ = "peer_" + int2str(id_); 79b6ef00f11f5d79b02007907c14a1ae1cd8de8028tommi@webrtc.org else if (name_.length() > kMaxNameLength) 80b6ef00f11f5d79b02007907c14a1ae1cd8de8028tommi@webrtc.org name_.resize(kMaxNameLength); 81b6ef00f11f5d79b02007907c14a1ae1cd8de8028tommi@webrtc.org 820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::replace(name_.begin(), name_.end(), ',', '_'); 830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgChannelMember::~ChannelMember() { 860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ChannelMember::is_wait_request(DataSocket* ds) const { 890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ds && ds->PathEquals(kRequestPaths[kWait]); 900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ChannelMember::TimedOut() { 930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return waiting_socket_ == NULL && (time(NULL) - timestamp_) > 30; 940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstd::string ChannelMember::GetPeerIdHeader() const { 970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string ret(kPeerIdHeader + int2str(id_) + "\r\n"); 980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ret; 990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ChannelMember::NotifyOfOtherMember(const ChannelMember& other) { 1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(&other != this); 1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org QueueResponse("200 OK", "text/plain", GetPeerIdHeader(), 1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org other.GetEntry()); 1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 108b6ef00f11f5d79b02007907c14a1ae1cd8de8028tommi@webrtc.org// Returns a string in the form "name,id,connected\n". 1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstd::string ChannelMember::GetEntry() const { 110b6ef00f11f5d79b02007907c14a1ae1cd8de8028tommi@webrtc.org assert(name_.length() <= kMaxNameLength); 1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org char entry[1024] = {0}; 1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sprintf(entry, "%s,%i,%i\n", name_.c_str(), id_, connected_); // NOLINT 1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return entry; 1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid ChannelMember::ForwardRequestToPeer(DataSocket* ds, ChannelMember* peer) { 1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(peer); 1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(ds); 1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string extra_headers(GetPeerIdHeader()); 1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (peer == this) { 1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ds->Send("200 OK", true, ds->content_type(), extra_headers, 1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ds->data()); 1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org printf("Client %s sending to %s\n", 1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org name_.c_str(), peer->name().c_str()); 1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org peer->QueueResponse("200 OK", ds->content_type(), extra_headers, 1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ds->data()); 1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ds->Send("200 OK", true, "text/plain", "", ""); 1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid ChannelMember::OnClosing(DataSocket* ds) { 1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (ds == waiting_socket_) { 1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org waiting_socket_ = NULL; 1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org timestamp_ = time(NULL); 1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid ChannelMember::QueueResponse(const std::string& status, 1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string& content_type, 1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string& extra_headers, 1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string& data) { 1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (waiting_socket_) { 1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(queue_.size() == 0); 1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(waiting_socket_->method() == DataSocket::GET); 1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool ok = waiting_socket_->Send(status, true, content_type, extra_headers, 1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org data); 1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!ok) { 1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org printf("Failed to deliver data to waiting socket\n"); 1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org waiting_socket_ = NULL; 1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org timestamp_ = time(NULL); 1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org QueuedResponse qr; 1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org qr.status = status; 1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org qr.content_type = content_type; 1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org qr.extra_headers = extra_headers; 1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org qr.data = data; 1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org queue_.push(qr); 1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid ChannelMember::SetWaitingSocket(DataSocket* ds) { 1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(ds->method() == DataSocket::GET); 1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (ds && !queue_.empty()) { 1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(waiting_socket_ == NULL); 1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const QueuedResponse& response = queue_.front(); 1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ds->Send(response.status, true, response.content_type, 1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org response.extra_headers, response.data); 1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org queue_.pop(); 1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org waiting_socket_ = ds; 1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// PeerChannel 1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// static 1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool PeerChannel::IsPeerConnection(const DataSocket* ds) { 1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(ds); 1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return (ds->method() == DataSocket::POST && ds->content_length() > 0) || 1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org (ds->method() == DataSocket::GET && ds->PathEquals("/sign_in")); 1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgChannelMember* PeerChannel::Lookup(DataSocket* ds) const { 1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(ds); 1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (ds->method() != DataSocket::GET && ds->method() != DataSocket::POST) 1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return NULL; 1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org size_t i = 0; 1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (; i < ARRAYSIZE(kRequestPaths); ++i) { 1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (ds->PathEquals(kRequestPaths[i])) 1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (i == ARRAYSIZE(kRequestPaths)) 2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return NULL; 2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string args(ds->request_arguments()); 2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static const char kPeerId[] = "peer_id="; 2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org size_t found = args.find(kPeerId); 2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (found == std::string::npos) 2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return NULL; 2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int id = atoi(&args[found + ARRAYSIZE(kPeerId) - 1]); 2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Members::const_iterator iter = members_.begin(); 2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (; iter != members_.end(); ++iter) { 2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (id == (*iter)->id()) { 2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (i == kWait) 2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org (*iter)->SetWaitingSocket(ds); 2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (i == kSignOut) 2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org (*iter)->set_disconnected(); 2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return *iter; 2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return NULL; 2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgChannelMember* PeerChannel::IsTargetedRequest(const DataSocket* ds) const { 2260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(ds); 2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Regardless of GET or POST, we look for the peer_id parameter 2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // only in the request_path. 2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string& path = ds->request_path(); 2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org size_t args = path.find('?'); 2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (args == std::string::npos) 2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return NULL; 2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org size_t found; 2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const char kTargetPeerIdParam[] = "to="; 2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org do { 2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org found = path.find(kTargetPeerIdParam, args); 2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (found == std::string::npos) 2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return NULL; 2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (found == (args + 1) || path[found - 1] == '&') { 2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org found += ARRAYSIZE(kTargetPeerIdParam) - 1; 2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org args = found + ARRAYSIZE(kTargetPeerIdParam) - 1; 2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } while (true); 2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int id = atoi(&path[found]); 2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Members::const_iterator i = members_.begin(); 2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (; i != members_.end(); ++i) { 2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if ((*i)->id() == id) { 2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return *i; 2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return NULL; 2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool PeerChannel::AddMember(DataSocket* ds) { 2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(IsPeerConnection(ds)); 2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ChannelMember* new_guy = new ChannelMember(ds); 2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Members failures; 2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org BroadcastChangedState(*new_guy, &failures); 2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org HandleDeliveryFailures(&failures); 2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org members_.push_back(new_guy); 2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org printf("New member added (total=%s): %s\n", 2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org size_t2str(members_.size()).c_str(), new_guy->name().c_str()); 2650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Let the newly connected peer know about other members of the channel. 2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string content_type; 2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string response = BuildResponseForNewMember(*new_guy, &content_type); 2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ds->Send("200 Added", true, content_type, new_guy->GetPeerIdHeader(), 2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org response); 2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PeerChannel::CloseAll() { 2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Members::const_iterator i = members_.begin(); 2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (; i != members_.end(); ++i) { 2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org (*i)->QueueResponse("200 OK", "text/plain", "", "Server shutting down"); 2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org DeleteAll(); 2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PeerChannel::OnClosing(DataSocket* ds) { 2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (Members::iterator i = members_.begin(); i != members_.end(); ++i) { 2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ChannelMember* m = (*i); 2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org m->OnClosing(ds); 2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!m->connected()) { 2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org i = members_.erase(i); 2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Members failures; 2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org BroadcastChangedState(*m, &failures); 2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org HandleDeliveryFailures(&failures); 2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org delete m; 2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (i == members_.end()) 2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org printf("Total connected: %s\n", size_t2str(members_.size()).c_str()); 2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PeerChannel::CheckForTimeout() { 3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (Members::iterator i = members_.begin(); i != members_.end(); ++i) { 3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ChannelMember* m = (*i); 3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (m->TimedOut()) { 3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org printf("Timeout: %s\n", m->name().c_str()); 3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org m->set_disconnected(); 3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org i = members_.erase(i); 3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Members failures; 3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org BroadcastChangedState(*m, &failures); 3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org HandleDeliveryFailures(&failures); 3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org delete m; 3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (i == members_.end()) 3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PeerChannel::DeleteAll() { 3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (Members::iterator i = members_.begin(); i != members_.end(); ++i) 3180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org delete (*i); 3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org members_.clear(); 3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PeerChannel::BroadcastChangedState(const ChannelMember& member, 3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Members* delivery_failures) { 3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // This function should be called prior to DataSocket::Close(). 3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(delivery_failures); 3260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!member.connected()) { 3280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org printf("Member disconnected: %s\n", member.name().c_str()); 3290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Members::iterator i = members_.begin(); 3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (; i != members_.end(); ++i) { 3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (&member != (*i)) { 3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!(*i)->NotifyOfOtherMember(member)) { 3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org (*i)->set_disconnected(); 3360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org delivery_failures->push_back(*i); 3370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org i = members_.erase(i); 3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (i == members_.end()) 3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PeerChannel::HandleDeliveryFailures(Members* failures) { 3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(failures); 3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org while (!failures->empty()) { 3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Members::iterator i = failures->begin(); 3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ChannelMember* member = *i; 3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(!member->connected()); 3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org failures->erase(i); 3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org BroadcastChangedState(*member, failures); 3540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org delete member; 3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Builds a simple list of "name,id\n" entries for each member. 3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstd::string PeerChannel::BuildResponseForNewMember(const ChannelMember& member, 3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string* content_type) { 3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert(content_type); 3620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *content_type = "text/plain"; 3640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The peer itself will always be the first entry. 3650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string response(member.GetEntry()); 3660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (Members::iterator i = members_.begin(); i != members_.end(); ++i) { 3670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (member.id() != (*i)->id()) { 3680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org assert((*i)->connected()); 3690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org response += (*i)->GetEntry(); 3700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return response; 3740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 375