1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CAST_COMMON_CHANNEL_VIRTUAL_CONNECTION_H_
6 #define CAST_COMMON_CHANNEL_VIRTUAL_CONNECTION_H_
7 
8 #include <array>
9 #include <cstdint>
10 #include <string>
11 
12 namespace openscreen {
13 namespace cast {
14 
15 // Transport system on top of CastSocket that allows routing messages over a
16 // single socket to different virtual endpoints (e.g. system messages vs.
17 // messages for a particular app).
18 struct VirtualConnection {
19   // Virtual connections can have slightly different semantics for a particular
20   // endpoint based on its type.
21   enum class Type : int8_t {
22     // Normal connections.  Receiver applications should not exit while they
23     // still have strong connections open (e.g. active senders).
24     kStrong = 0,
25 
26     // Same as strong except if the connected endpoint is a receiver
27     // application, it may stop if its only remaining open connections are all
28     // weak.
29     kWeak = 1,
30 
31     // Receiver applications do not receive connected/disconnected notifications
32     // about these connections.  The following additional conditions apply:
33     //  - Receiver app can still receive "urn:x-cast:com.google.cast.media"
34     //    messages over invisible connections.
35     //  - Receiver app can only send broadcast messages over an invisible
36     //    connection.
37     kInvisible = 2,
38 
39     kMinValue = kStrong,
40     kMaxValue = kInvisible,
41   };
42 
43   // Cast V2 protocol version constants.  Must be in sync with
44   // proto/cast_channel.proto.
45   enum class ProtocolVersion {
46     kV2_1_0,
47     kV2_1_1,
48     kV2_1_2,
49     kV2_1_3,
50   };
51 
52   enum CloseReason {
53     kUnknown,
54     kFirstReason = kUnknown,
55 
56     // Underlying socket has been closed by peer. This happens when Cast sender
57     // closed transport connection normally without graceful virtual connection
58     // close. Though it is not an error, graceful virtual connection in advance
59     // is better.
60     kTransportClosed,
61 
62     // Underlying socket has been aborted by peer. Peer is no longer reachable
63     // because of app crash or network error.
64     kTransportAborted,
65 
66     // Messages sent from peer are in wrong format or too long.
67     kTransportInvalidMessage,
68 
69     // Underlying socket has been idle for a long period. This only happens when
70     // heartbeat is enabled and there is a network error.
71     kTransportTooLongInactive,
72 
73     // The virtual connection has been closed by this endpoint.
74     kClosedBySelf,
75 
76     // The virtual connection has been closed by the peer gracefully.
77     kClosedByPeer,
78     kLastReason = kClosedByPeer,
79   };
80 
81   struct AssociatedData {
82     Type type;
83     std::string user_agent;
84 
85     // Last two bytes of the peer's IP address, whether IPv4 or IPv6.
86     std::array<uint8_t, 2> ip_fragment;
87 
88     ProtocolVersion max_protocol_version;
89   };
90 
91   // |local_id| and |peer_id| can be one of several formats:
92   //  - sender-0 or receiver-0: identifies the appropriate platform endpoint of
93   //    the device.  Authentication and transport-related messages use these.
94   //  - sender-12345: Possible form of a Cast sender ID.  The number portion is
95   //    intended to be unique within that device (i.e., unique per CastSocket).
96   //  - Random decimal number: Possible form of a Cast sender ID.  Also randomly
97   //    intended to be unique within that device (i.e., unique per CastSocket).
98   //  - GUID-style hex string: Random string identifying a particular receiver
99   //    app on the device.
100   //
101   // Additionally, |peer_id| can be an asterisk when broadcast-sending.
102   std::string local_id;
103   std::string peer_id;
104   int socket_id;
105 };
106 
107 inline bool operator==(const VirtualConnection& a, const VirtualConnection& b) {
108   return a.local_id == b.local_id && a.peer_id == b.peer_id &&
109          a.socket_id == b.socket_id;
110 }
111 
112 inline bool operator!=(const VirtualConnection& a, const VirtualConnection& b) {
113   return !(a == b);
114 }
115 
116 }  // namespace cast
117 }  // namespace openscreen
118 
119 #endif  // CAST_COMMON_CHANNEL_VIRTUAL_CONNECTION_H_
120