1/*
2 * libjingle
3 * Copyright 2011, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 *  1. Redistributions of source code must retain the above copyright notice,
9 *     this list of conditions and the following disclaimer.
10 *  2. Redistributions in binary form must reproduce the above copyright notice,
11 *     this list of conditions and the following disclaimer in the documentation
12 *     and/or other materials provided with the distribution.
13 *  3. The name of the author may not be used to endorse or promote products
14 *     derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifndef TALK_EXAMPLES_PEERCONNECTION_SERVER_PEER_CHANNEL_H_
29#define TALK_EXAMPLES_PEERCONNECTION_SERVER_PEER_CHANNEL_H_
30#pragma once
31
32#include <time.h>
33
34#include <queue>
35#include <string>
36#include <vector>
37
38class DataSocket;
39
40// Represents a single peer connected to the server.
41class ChannelMember {
42 public:
43  explicit ChannelMember(DataSocket* socket);
44  ~ChannelMember();
45
46  bool connected() const { return connected_; }
47  int id() const { return id_; }
48  void set_disconnected() { connected_ = false; }
49  bool is_wait_request(DataSocket* ds) const;
50  const std::string& name() const { return name_; }
51
52  bool TimedOut();
53
54  std::string GetPeerIdHeader() const;
55
56  bool NotifyOfOtherMember(const ChannelMember& other);
57
58  // Returns a string in the form "name,id\n".
59  std::string GetEntry() const;
60
61  void ForwardRequestToPeer(DataSocket* ds, ChannelMember* peer);
62
63  void OnClosing(DataSocket* ds);
64
65  void QueueResponse(const std::string& status, const std::string& content_type,
66                     const std::string& extra_headers, const std::string& data);
67
68  void SetWaitingSocket(DataSocket* ds);
69
70 protected:
71  struct QueuedResponse {
72    std::string status, content_type, extra_headers, data;
73  };
74
75  DataSocket* waiting_socket_;
76  int id_;
77  bool connected_;
78  time_t timestamp_;
79  std::string name_;
80  std::queue<QueuedResponse> queue_;
81  static int s_member_id_;
82};
83
84// Manages all currently connected peers.
85class PeerChannel {
86 public:
87  typedef std::vector<ChannelMember*> Members;
88
89  PeerChannel() {
90  }
91
92  ~PeerChannel() {
93    DeleteAll();
94  }
95
96  const Members& members() const { return members_; }
97
98  // Returns true if the request should be treated as a new ChannelMember
99  // request.  Otherwise the request is not peerconnection related.
100  static bool IsPeerConnection(const DataSocket* ds);
101
102  // Finds a connected peer that's associated with the |ds| socket.
103  ChannelMember* Lookup(DataSocket* ds) const;
104
105  // Checks if the request has a "peer_id" parameter and if so, looks up the
106  // peer for which the request is targeted at.
107  ChannelMember* IsTargetedRequest(const DataSocket* ds) const;
108
109  // Adds a new ChannelMember instance to the list of connected peers and
110  // associates it with the socket.
111  bool AddMember(DataSocket* ds);
112
113  // Closes all connections and sends a "shutting down" message to all
114  // connected peers.
115  void CloseAll();
116
117  // Called when a socket was determined to be closing by the peer (or if the
118  // connection went dead).
119  void OnClosing(DataSocket* ds);
120
121  void CheckForTimeout();
122
123 protected:
124  void DeleteAll();
125  void BroadcastChangedState(const ChannelMember& member,
126                             Members* delivery_failures);
127  void HandleDeliveryFailures(Members* failures);
128
129  // Builds a simple list of "name,id\n" entries for each member.
130  std::string BuildResponseForNewMember(const ChannelMember& member,
131                                        std::string* content_type);
132
133 protected:
134  Members members_;
135};
136
137#endif  // TALK_EXAMPLES_PEERCONNECTION_SERVER_PEER_CHANNEL_H_
138