1 | /********** |
2 | This library is free software; you can redistribute it and/or modify it under |
3 | the terms of the GNU Lesser General Public License as published by the |
4 | Free Software Foundation; either version 3 of the License, or (at your |
5 | option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.) |
6 | |
7 | This library is distributed in the hope that it will be useful, but WITHOUT |
8 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
9 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for |
10 | more details. |
11 | |
12 | You should have received a copy of the GNU Lesser General Public License |
13 | along with this library; if not, write to the Free Software Foundation, Inc., |
14 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
15 | **********/ |
16 | // "mTunnel" multicast access service |
17 | // Copyright (c) 1996-2020 Live Networks, Inc. All rights reserved. |
18 | // 'Group sockets' |
19 | // C++ header |
20 | |
21 | #ifndef _GROUPSOCK_HH |
22 | #define _GROUPSOCK_HH |
23 | |
24 | #ifndef _GROUPSOCK_VERSION_HH |
25 | #include "groupsock_version.hh" |
26 | #endif |
27 | |
28 | #ifndef _NET_INTERFACE_HH |
29 | #include "NetInterface.hh" |
30 | #endif |
31 | |
32 | #ifndef _GROUPEID_HH |
33 | #include "GroupEId.hh" |
34 | #endif |
35 | |
36 | // An "OutputSocket" is (by default) used only to send packets. |
37 | // No packets are received on it (unless a subclass arranges this) |
38 | |
39 | class OutputSocket: public Socket { |
40 | public: |
41 | OutputSocket(UsageEnvironment& env); |
42 | virtual ~OutputSocket(); |
43 | |
44 | virtual Boolean write(netAddressBits address, portNumBits portNum/*in network order*/, u_int8_t ttl, |
45 | unsigned char* buffer, unsigned bufferSize); |
46 | Boolean write(struct sockaddr_in& addressAndPort, u_int8_t ttl, |
47 | unsigned char* buffer, unsigned bufferSize) { |
48 | return write(addressAndPort.sin_addr.s_addr, addressAndPort.sin_port, ttl, buffer, bufferSize); |
49 | } |
50 | |
51 | protected: |
52 | OutputSocket(UsageEnvironment& env, Port port); |
53 | |
54 | portNumBits sourcePortNum() const {return fSourcePort.num();} |
55 | |
56 | private: // redefined virtual function |
57 | virtual Boolean handleRead(unsigned char* buffer, unsigned bufferMaxSize, |
58 | unsigned& bytesRead, |
59 | struct sockaddr_in& fromAddressAndPort); |
60 | |
61 | private: |
62 | Port fSourcePort; |
63 | unsigned fLastSentTTL; |
64 | }; |
65 | |
66 | class destRecord { |
67 | public: |
68 | destRecord(struct in_addr const& addr, Port const& port, u_int8_t ttl, unsigned sessionId, |
69 | destRecord* next); |
70 | virtual ~destRecord(); |
71 | |
72 | public: |
73 | destRecord* fNext; |
74 | GroupEId fGroupEId; |
75 | unsigned fSessionId; |
76 | }; |
77 | |
78 | // A "Groupsock" is used to both send and receive packets. |
79 | // As the name suggests, it was originally designed to send/receive |
80 | // multicast, but it can send/receive unicast as well. |
81 | |
82 | class Groupsock: public OutputSocket { |
83 | public: |
84 | Groupsock(UsageEnvironment& env, struct in_addr const& groupAddr, |
85 | Port port, u_int8_t ttl); |
86 | // used for a 'source-independent multicast' group |
87 | Groupsock(UsageEnvironment& env, struct in_addr const& groupAddr, |
88 | struct in_addr const& sourceFilterAddr, |
89 | Port port); |
90 | // used for a 'source-specific multicast' group |
91 | virtual ~Groupsock(); |
92 | |
93 | virtual destRecord* createNewDestRecord(struct in_addr const& addr, Port const& port, u_int8_t ttl, unsigned sessionId, destRecord* next); |
94 | // Can be redefined by subclasses that also subclass "destRecord" |
95 | |
96 | void changeDestinationParameters(struct in_addr const& newDestAddr, |
97 | Port newDestPort, int newDestTTL, |
98 | unsigned sessionId = 0); |
99 | // By default, the destination address, port and ttl for |
100 | // outgoing packets are those that were specified in |
101 | // the constructor. This works OK for multicast sockets, |
102 | // but for unicast we usually want the destination port |
103 | // number, at least, to be different from the source port. |
104 | // (If a parameter is 0 (or ~0 for ttl), then no change is made to that parameter.) |
105 | // (If no existing "destRecord" exists with this "sessionId", then we add a new "destRecord".) |
106 | unsigned lookupSessionIdFromDestination(struct sockaddr_in const& destAddrAndPort) const; |
107 | // returns 0 if not found |
108 | |
109 | // As a special case, we also allow multiple destinations (addresses & ports) |
110 | // (This can be used to implement multi-unicast.) |
111 | virtual void addDestination(struct in_addr const& addr, Port const& port, unsigned sessionId); |
112 | virtual void removeDestination(unsigned sessionId); |
113 | void removeAllDestinations(); |
114 | Boolean hasMultipleDestinations() const { return fDests != NULL && fDests->fNext != NULL; } |
115 | |
116 | struct in_addr const& groupAddress() const { |
117 | return fIncomingGroupEId.groupAddress(); |
118 | } |
119 | struct in_addr const& sourceFilterAddress() const { |
120 | return fIncomingGroupEId.sourceFilterAddress(); |
121 | } |
122 | |
123 | Boolean isSSM() const { |
124 | return fIncomingGroupEId.isSSM(); |
125 | } |
126 | |
127 | u_int8_t ttl() const { return fIncomingGroupEId.ttl(); } |
128 | |
129 | void multicastSendOnly(); // send, but don't receive any multicast packets |
130 | |
131 | virtual Boolean output(UsageEnvironment& env, unsigned char* buffer, unsigned bufferSize, |
132 | DirectedNetInterface* interfaceNotToFwdBackTo = NULL); |
133 | |
134 | DirectedNetInterfaceSet& members() { return fMembers; } |
135 | |
136 | Boolean deleteIfNoMembers; |
137 | Boolean isSlave; // for tunneling |
138 | |
139 | static NetInterfaceTrafficStats statsIncoming; |
140 | static NetInterfaceTrafficStats statsOutgoing; |
141 | static NetInterfaceTrafficStats statsRelayedIncoming; |
142 | static NetInterfaceTrafficStats statsRelayedOutgoing; |
143 | NetInterfaceTrafficStats statsGroupIncoming; // *not* static |
144 | NetInterfaceTrafficStats statsGroupOutgoing; // *not* static |
145 | NetInterfaceTrafficStats statsGroupRelayedIncoming; // *not* static |
146 | NetInterfaceTrafficStats statsGroupRelayedOutgoing; // *not* static |
147 | |
148 | Boolean wasLoopedBackFromUs(UsageEnvironment& env, struct sockaddr_in& fromAddressAndPort); |
149 | |
150 | public: // redefined virtual functions |
151 | virtual Boolean handleRead(unsigned char* buffer, unsigned bufferMaxSize, |
152 | unsigned& bytesRead, |
153 | struct sockaddr_in& fromAddressAndPort); |
154 | |
155 | protected: |
156 | destRecord* lookupDestRecordFromDestination(struct sockaddr_in const& destAddrAndPort) const; |
157 | |
158 | private: |
159 | void removeDestinationFrom(destRecord*& dests, unsigned sessionId); |
160 | // used to implement (the public) "removeDestination()", and "changeDestinationParameters()" |
161 | int outputToAllMembersExcept(DirectedNetInterface* exceptInterface, |
162 | u_int8_t ttlToFwd, |
163 | unsigned char* data, unsigned size, |
164 | netAddressBits sourceAddr); |
165 | |
166 | protected: |
167 | destRecord* fDests; |
168 | private: |
169 | GroupEId fIncomingGroupEId; |
170 | DirectedNetInterfaceSet fMembers; |
171 | }; |
172 | |
173 | UsageEnvironment& operator<<(UsageEnvironment& s, const Groupsock& g); |
174 | |
175 | // A data structure for looking up a 'groupsock' |
176 | // by (multicast address, port), or by socket number |
177 | class GroupsockLookupTable { |
178 | public: |
179 | Groupsock* Fetch(UsageEnvironment& env, netAddressBits groupAddress, |
180 | Port port, u_int8_t ttl, Boolean& isNew); |
181 | // Creates a new Groupsock if none already exists |
182 | Groupsock* Fetch(UsageEnvironment& env, netAddressBits groupAddress, |
183 | netAddressBits sourceFilterAddr, |
184 | Port port, Boolean& isNew); |
185 | // Creates a new Groupsock if none already exists |
186 | Groupsock* Lookup(netAddressBits groupAddress, Port port); |
187 | // Returns NULL if none already exists |
188 | Groupsock* Lookup(netAddressBits groupAddress, |
189 | netAddressBits sourceFilterAddr, |
190 | Port port); |
191 | // Returns NULL if none already exists |
192 | Groupsock* Lookup(UsageEnvironment& env, int sock); |
193 | // Returns NULL if none already exists |
194 | Boolean Remove(Groupsock const* groupsock); |
195 | |
196 | // Used to iterate through the groupsocks in the table |
197 | class Iterator { |
198 | public: |
199 | Iterator(GroupsockLookupTable& groupsocks); |
200 | |
201 | Groupsock* next(); // NULL iff none |
202 | |
203 | private: |
204 | AddressPortLookupTable::Iterator fIter; |
205 | }; |
206 | |
207 | private: |
208 | Groupsock* AddNew(UsageEnvironment& env, |
209 | netAddressBits groupAddress, |
210 | netAddressBits sourceFilterAddress, |
211 | Port port, u_int8_t ttl); |
212 | |
213 | private: |
214 | friend class Iterator; |
215 | AddressPortLookupTable fTable; |
216 | }; |
217 | |
218 | #endif |
219 | |