/src/resiprocate/resip/stack/Transport.hxx
Line | Count | Source |
1 | | #if !defined(RESIP_TRANSPORT_HXX) |
2 | | #define RESIP_TRANSPORT_HXX |
3 | | |
4 | | #include "rutil/BaseException.hxx" |
5 | | #include "rutil/Data.hxx" |
6 | | #include "rutil/FdSetIOObserver.hxx" |
7 | | #include "rutil/ProducerFifoBuffer.hxx" |
8 | | #include "resip/stack/TransportFailure.hxx" |
9 | | #include "resip/stack/TcpConnectState.hxx" |
10 | | #include "resip/stack/Tuple.hxx" |
11 | | #include "resip/stack/NameAddr.hxx" |
12 | | #include "resip/stack/Compression.hxx" |
13 | | #include "resip/stack/SendData.hxx" |
14 | | |
15 | | #include <list> |
16 | | #include <memory> |
17 | | #include <utility> |
18 | | |
19 | | namespace resip |
20 | | { |
21 | | |
22 | | class TransactionMessage; |
23 | | class SipMessage; |
24 | | class Connection; |
25 | | class Compression; |
26 | | class FdPollGrp; |
27 | | |
28 | | /** |
29 | | * TransportFlags is bit-mask that can be set when creating a transport. |
30 | | * All flags default to "off" to preserve "traditional" resip behavior. |
31 | | * Not all Transports support all flags. All options are experimental. |
32 | | * The flags are: |
33 | | * NOBIND: |
34 | | * On transports that support it (TCP/TLS), do not bind a listening |
35 | | * socket; thus no in-bound connections are possible. This can conserve |
36 | | * ports and avoid port conflicts in pure-outbound (NAT'd) cases. |
37 | | * RXALL: |
38 | | * When receiving from socket, read all possible messages before |
39 | | * returning to event loop. This allows higher thruput. Without this flag, |
40 | | * only one message is read at a time, which is slower over-all, but |
41 | | * is more "even" and balanced. |
42 | | * TXALL: |
43 | | * When transmitting to a socket, write all possible messages before |
44 | | * returning to event loop. This allows higher thruput but burstier. |
45 | | * TXNOW: |
46 | | * When a message to transmit is posted to Transport's transmit queue |
47 | | * immediately try sending it. This should have less latency |
48 | | * and less overhead with select/poll stuff, but will have deeper |
49 | | * call stacks. |
50 | | * OWNTHREAD: |
51 | | * Specifies whether this Transport object has its own thread (ie; if |
52 | | * set, the TransportSelector should not run the select/poll loop for |
53 | | * this transport, since that is another thread's job) |
54 | | */ |
55 | | #define RESIP_TRANSPORT_FLAG_NOBIND (1<<0) |
56 | | #define RESIP_TRANSPORT_FLAG_RXALL (1<<1) |
57 | | #define RESIP_TRANSPORT_FLAG_TXALL (1<<2) |
58 | | #define RESIP_TRANSPORT_FLAG_TXNOW (1<<4) |
59 | | #define RESIP_TRANSPORT_FLAG_OWNTHREAD (1<<5) |
60 | | |
61 | | /** |
62 | | @brief The base class for Transport classes. |
63 | | |
64 | | A Transport presents layer 4 of the OSI model, the transport layer. |
65 | | For IP-based protocols, this means that a Transport object has an |
66 | | IP address (v4 or v6), a transport layer protocol (UDP or TCP/TLS), |
67 | | and a port number. These are managed through the Transport's Tuple |
68 | | member. |
69 | | |
70 | | */ |
71 | | class Transport : public FdSetIOObserver |
72 | | { |
73 | | public: |
74 | | |
75 | | class SipMessageLoggingHandler |
76 | | { |
77 | | public: |
78 | | SipMessageLoggingHandler() = default; |
79 | | SipMessageLoggingHandler(const SipMessageLoggingHandler&) = delete; |
80 | | SipMessageLoggingHandler(SipMessageLoggingHandler&&) = delete; |
81 | | virtual ~SipMessageLoggingHandler() = default; |
82 | | |
83 | | SipMessageLoggingHandler& operator=(const SipMessageLoggingHandler&) = delete; |
84 | | SipMessageLoggingHandler& operator=(SipMessageLoggingHandler&&) = delete; |
85 | | |
86 | | virtual void outboundMessage(const Tuple &source, const Tuple &destination, const SipMessage &msg) = 0; |
87 | | // Note: retransmissions store already encoded messages, so callback doesn't send SipMessage it sends |
88 | | // the encoded version of the SipMessage instead. If you need a SipMessage you will need to |
89 | | // re-parse back into a SipMessage in the callback handler. |
90 | 0 | virtual void outboundRetransmit(const Tuple &source, const Tuple &destination, const SendData &data) {} |
91 | | virtual void inboundMessage(const Tuple& source, const Tuple& destination, const SipMessage &msg) = 0; |
92 | | }; |
93 | | |
94 | | using SipMessageLoggingHandlerList = std::vector<std::shared_ptr<SipMessageLoggingHandler> >; |
95 | | |
96 | | void setSipMessageLoggingHandler(std::shared_ptr<SipMessageLoggingHandler> handler); |
97 | | void addSipMessageLoggingHandler(std::shared_ptr<SipMessageLoggingHandler> handler); |
98 | | void setSipMessageLoggingHandlers(const SipMessageLoggingHandlerList& handlers); |
99 | | void unsetSipMessageLoggingHandler() noexcept; |
100 | | SipMessageLoggingHandlerList getSipMessageLoggingHandlers() const noexcept; |
101 | | |
102 | | /** |
103 | | @brief General exception class for Transport. |
104 | | |
105 | | This would be thrown if there was an attempt to bind to a port |
106 | | that is already in use. |
107 | | */ |
108 | | class Exception final : public BaseException |
109 | | { |
110 | | public: |
111 | | Exception(const Data& msg, const Data& file, int line); |
112 | 0 | const char* name() const noexcept override { return "TransportException"; } |
113 | | }; |
114 | | |
115 | | /** |
116 | | @param rxFifo the TransactionMessage Fifo that will receive |
117 | | any ConnectionTerminated or TransportFailure messages. |
118 | | |
119 | | @param tlsDomain the domain name of the Transport |
120 | | |
121 | | @param socketFunc subclassers can call this function after |
122 | | the socket is created. This is not currently used by |
123 | | Transport. |
124 | | */ |
125 | | Transport(Fifo<TransactionMessage>& rxFifo, |
126 | | const GenericIPAddress& address, |
127 | | const Data& tlsDomain = Data::Empty, // !dcm! where is this used? |
128 | | AfterSocketCreationFuncPtr socketFunc = nullptr, |
129 | | Compression &compression = Compression::Disabled |
130 | | ); |
131 | | |
132 | | /** |
133 | | @param rxFifo the TransactionMessage Fifo that will receive |
134 | | any ConnectionTerminated or TransportFailure messages. |
135 | | |
136 | | @param interfaceObj a "presentation format" representation |
137 | | of the IP address of this transport |
138 | | @see Tuple::inet_ntop() for information about "presentation |
139 | | format" |
140 | | |
141 | | @param portNum is the port to receive and/or send on |
142 | | |
143 | | @param tlsDomain the domain name of the Transport |
144 | | |
145 | | @todo Note that because of InternalTransport's constructor, |
146 | | tlsDomain is always set to Data::Empty at construction time, |
147 | | in practice. |
148 | | |
149 | | @param socketFunc subclassers can call this function after |
150 | | the socket is created. This is not currently used by |
151 | | Transport. |
152 | | */ |
153 | | Transport(Fifo<TransactionMessage>& rxFifo, |
154 | | int portNum, |
155 | | IpVersion version, |
156 | | const Data& interfaceObj, |
157 | | const Data& tlsDomain = Data::Empty, |
158 | | AfterSocketCreationFuncPtr socketFunc = nullptr, |
159 | | Compression &compression = Compression::Disabled, |
160 | | unsigned transportFlags = 0, |
161 | | const Data& netNs = Data::Empty); |
162 | | |
163 | | virtual ~Transport(); |
164 | | |
165 | | virtual void onReload(); |
166 | | |
167 | | /** |
168 | | @note Subclasses override this method by checking whether |
169 | | there are unprocessed messages on the TransactionMessage |
170 | | Fifo (that was passed in to the constructor). |
171 | | */ |
172 | | virtual bool isFinished() const=0; |
173 | | |
174 | | std::unique_ptr<SendData> makeSendData( const Tuple& tuple, const Data& data, const Data& tid, const Data &sigcompId = Data::Empty); |
175 | | |
176 | | /** |
177 | | @todo !bwc! What we do with a SendData is flexible. It might make a |
178 | | copy, or send synchronously, or convert to another type, |
179 | | etc. |
180 | | |
181 | | @todo !bch! Should this be protected and not public? |
182 | | !bwc! TransportSelector uses this directly for retransmissions. |
183 | | */ |
184 | | virtual void send(std::unique_ptr<SendData> data)=0; |
185 | | |
186 | | /** |
187 | | Called when a writer is done adding messages to the TxFifo; this is |
188 | | used to interrupt the select call if the Transport is running in its |
189 | | own thread. This does nothing if select is not currently blocking, so |
190 | | don't bother calling this from the same thread that selects on this |
191 | | Transport's fds. Default impl is a no-op. |
192 | | */ |
193 | 0 | virtual void poke(){}; |
194 | | |
195 | | /** |
196 | | If there is work to do, this is the method that does it. If |
197 | | the socket is readable, it is read. If the socket is |
198 | | writable and there are outgoing messages to be sent, they are |
199 | | sent. |
200 | | |
201 | | Incoming messages are parsed and dispatched to the relevant |
202 | | entity. SIP messages will be posted to the |
203 | | TransactionMessage Fifo. |
204 | | |
205 | | @see sendData() |
206 | | |
207 | | @param fdset is the FdSet after select() has been called. |
208 | | @see FdSet::select() |
209 | | */ |
210 | | virtual void process(FdSet& fdset) = 0; |
211 | | |
212 | | /** |
213 | | Adds the Transport's socket FD to the appropriate read or |
214 | | write sets as applicable. |
215 | | */ |
216 | | virtual void buildFdSet( FdSet& fdset) =0; |
217 | | |
218 | 0 | virtual unsigned int getTimeTillNextProcessMS(){return UINT_MAX;} |
219 | | |
220 | | /** |
221 | | Version of process to be invoked periodically when using callback-based |
222 | | IO (via FdPollGrp). |
223 | | */ |
224 | | virtual void process() = 0; |
225 | | |
226 | | virtual void setPollGrp(FdPollGrp *grp) = 0; |
227 | | |
228 | | /** |
229 | | Posts a ConnectionTerminated message to TransactionMessage |
230 | | Fifo. |
231 | | */ |
232 | | void flowTerminated(const Tuple& flow, |
233 | | TransportFailure::FailureReason failureReason, |
234 | | int failureSubCode, |
235 | | const Data& failureString, |
236 | | const std::list<Data> additionalFailureStrings); |
237 | | void keepAlivePong(const Tuple& flow); |
238 | | |
239 | | /** |
240 | | Posts a TransportFailure to the TransactionMessage Fifo. |
241 | | */ |
242 | | void fail(const Data& tid, |
243 | | TransportFailure::FailureReason reason = TransportFailure::Failure, |
244 | | int subCode = 0); |
245 | | |
246 | | /** |
247 | | Posts a TcpConnectState to the TransactionMessage Fifo. |
248 | | */ |
249 | | void setTcpConnectState(const Data& tid, TcpConnectState::State state); |
250 | | |
251 | | /** |
252 | | Generates a generic log for the platform specific socket |
253 | | error number. |
254 | | |
255 | | @param e the socket error number |
256 | | */ |
257 | | static void error(int e); |
258 | | static Data errorToString(int e); |
259 | | |
260 | | // These methods are used by the TransportSelector |
261 | 0 | const Data& interfaceName() const { return mInterface; } |
262 | | |
263 | 0 | int port() const { return mTuple.getPort(); } |
264 | | |
265 | | /// @deprecated use ipVersion() |
266 | 0 | bool isV4() const { return mTuple.isV4(); } // !dcm! -- deprecate ASAP |
267 | | |
268 | 0 | IpVersion ipVersion() const { return mTuple.ipVersion(); } |
269 | | |
270 | | /** |
271 | | @return the domain name that will be used for TLS, to, for |
272 | | example, find the certificate to present in the TLS |
273 | | handshake. |
274 | | */ |
275 | 0 | const Data& tlsDomain() const { return mTlsDomain; } |
276 | 0 | const sockaddr& boundInterface() const { return mTuple.getSockaddr(); } |
277 | 0 | const Tuple& getTuple() const { return mTuple; } |
278 | | |
279 | | /// @return This transport's TransportType. |
280 | 0 | const TransportType transport() const { return mTuple.getType(); } |
281 | | virtual bool isReliable() const =0; |
282 | | virtual bool isDatagram() const =0; |
283 | | |
284 | | /// @return net namespace in which Transport is bound |
285 | 0 | const Data& netNs() const { return(mTuple.getNetNs()); } |
286 | | |
287 | | /** |
288 | | @return true here if the subclass has a specific contact |
289 | | value that it wishes the TransportSelector to use. |
290 | | */ |
291 | 0 | virtual bool hasSpecificContact() const { return false; } |
292 | | |
293 | | /** |
294 | | Perform basic sanity checks on message. Return false |
295 | | if there is a problem eg) no Vias. |
296 | | |
297 | | @note --SIDE EFFECT-- This will queue a response if it CAN |
298 | | for a via-less request. Response will go straight into the |
299 | | TxFifo |
300 | | */ |
301 | | bool basicCheck(const SipMessage& msg); |
302 | | |
303 | | void makeFailedResponse(const SipMessage& msg, |
304 | | int responseCode = 400, |
305 | | const char * warning = nullptr); |
306 | | std::unique_ptr<SendData> make503(SipMessage& msg, |
307 | | uint16_t retryAfter); |
308 | | |
309 | | std::unique_ptr<SendData> make100(SipMessage& msg); |
310 | | void setRemoteSigcompId(SipMessage&msg, Data& id); |
311 | | // mark the received= and rport parameters if necessary |
312 | | static void stampReceived(SipMessage* request); |
313 | | |
314 | | /** |
315 | | Returns true if this Transport should be included in the |
316 | | FdSet processing loop, false if the Transport will provide |
317 | | its own cycles. If the Transport is going to provide its own |
318 | | cycles, the startOwnProcessing() and shutdown() will be |
319 | | called to tell the Transport when to process. |
320 | | |
321 | | @retval true will run in the SipStack's processing context |
322 | | @retval false provides own cycles, just puts messages in rxFifo |
323 | | */ |
324 | | virtual bool shareStackProcessAndSelect() const=0; |
325 | | |
326 | | /** |
327 | | transports that returned false to |
328 | | shareStackProcessAndSelect() shouldn't put messages into the |
329 | | fifo until this is called |
330 | | |
331 | | @todo ?dcm? avoid the received a message but haven't added a |
332 | | transport to the TransportSelector race, but this might not |
333 | | be necessary. |
334 | | */ |
335 | | virtual void startOwnProcessing()=0; |
336 | | |
337 | | /// only applies to transports that shareStackProcessAndSelect |
338 | | virtual bool hasDataToSend() const = 0; |
339 | | |
340 | | /** |
341 | | This starts shutting-down procedures for this Transport. New |
342 | | requests may be denied while "mShuttingDown" is true. |
343 | | |
344 | | Overriding implementations should chain through to this. |
345 | | |
346 | | @todo ?dcm? pure virtual protected method to enforce this? |
347 | | @see basicCheck() |
348 | | @see isFinished() |
349 | | */ |
350 | | virtual void shutdown() |
351 | 0 | { |
352 | | // !jf! should use the fifo to pass this in |
353 | 0 | mShuttingDown = true; |
354 | 0 | } |
355 | 0 | virtual bool isShuttingDown() { return mShuttingDown; } |
356 | | |
357 | | // also used by the TransportSelector. |
358 | | // requires that the two transports be |
359 | | bool operator==(const Transport& rhs) const; |
360 | | |
361 | | //# queued messages on this transport |
362 | | virtual unsigned int getFifoSize() const=0; |
363 | | |
364 | | void callSocketFunc(Socket sock); |
365 | | virtual void invokeAfterSocketCreationFunc() const = 0; //used to invoke the after socket creation func immediately for all existing sockets - can be used to modify QOS settings at runtime |
366 | | |
367 | | virtual void setCongestionManager(CongestionManager* manager) |
368 | 0 | { |
369 | 0 | mCongestionManager=manager; |
370 | 0 | } |
371 | | |
372 | | CongestionManager::RejectionBehavior getRejectionBehaviorForIncoming() const |
373 | 0 | { |
374 | 0 | if(mCongestionManager) |
375 | 0 | { |
376 | 0 | return mCongestionManager->getRejectionBehavior(&mStateMachineFifo.getFifo()); |
377 | 0 | } |
378 | 0 | return CongestionManager::NORMAL; |
379 | 0 | } |
380 | | |
381 | | void flushStateMacFifo() |
382 | 0 | { |
383 | 0 | mStateMachineFifo.flush(); |
384 | 0 | } |
385 | | |
386 | | uint32_t getExpectedWaitForIncoming() const |
387 | 0 | { |
388 | 0 | return (uint32_t)mStateMachineFifo.getFifo().expectedWaitTimeMilliSec()/1000; |
389 | 0 | } |
390 | | |
391 | | // called by Connection to deliver a received message |
392 | | virtual void pushRxMsgUp(SipMessage* msg); |
393 | | |
394 | | // set the receive buffer length (SO_RCVBUF) |
395 | 0 | virtual void setRcvBufLen(int buflen) { }; // make pure? |
396 | | |
397 | 0 | inline unsigned int getKey() const {return mTuple.mTransportKey;} |
398 | 0 | inline void setKey(unsigned int pKey) { mTuple.mTransportKey = pKey;} // should only be called once after creation |
399 | | |
400 | | protected: |
401 | | |
402 | | Data mInterface; |
403 | | Tuple mTuple; |
404 | | |
405 | | CongestionManager* mCongestionManager; |
406 | | ProducerFifoBuffer<TransactionMessage> mStateMachineFifo; // passed in |
407 | | bool mShuttingDown; |
408 | | |
409 | 0 | void setTlsDomain(const Data& domain) { mTlsDomain = domain; } |
410 | | private: |
411 | | static const Data transportNames[MAX_TRANSPORT]; |
412 | | friend EncodeStream& operator<<(EncodeStream& strm, const Transport& rhs); |
413 | | |
414 | | Data mTlsDomain; |
415 | | SipMessageLoggingHandlerList mSipMessageLoggingHandlers; |
416 | | |
417 | | protected: |
418 | | AfterSocketCreationFuncPtr mSocketFunc; |
419 | | Compression &mCompression; |
420 | | unsigned mTransportFlags; |
421 | | }; |
422 | | |
423 | | EncodeStream& operator<<(EncodeStream& strm, const Transport& rhs); |
424 | | |
425 | | } |
426 | | |
427 | | #endif |
428 | | |
429 | | /* ==================================================================== |
430 | | * The Vovida Software License, Version 1.0 |
431 | | * |
432 | | * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. |
433 | | * |
434 | | * Redistribution and use in source and binary forms, with or without |
435 | | * modification, are permitted provided that the following conditions |
436 | | * are met: |
437 | | * |
438 | | * 1. Redistributions of source code must retain the above copyright |
439 | | * notice, this list of conditions and the following disclaimer. |
440 | | * |
441 | | * 2. Redistributions in binary form must reproduce the above copyright |
442 | | * notice, this list of conditions and the following disclaimer in |
443 | | * the documentation and/or other materials provided with the |
444 | | * distribution. |
445 | | * |
446 | | * 3. The names "VOCAL", "Vovida Open Communication Application Library", |
447 | | * and "Vovida Open Communication Application Library (VOCAL)" must |
448 | | * not be used to endorse or promote products derived from this |
449 | | * software without prior written permission. For written |
450 | | * permission, please contact vocal@vovida.org. |
451 | | * |
452 | | * 4. Products derived from this software may not be called "VOCAL", nor |
453 | | * may "VOCAL" appear in their name, without prior written |
454 | | * permission of Vovida Networks, Inc. |
455 | | * |
456 | | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
457 | | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
458 | | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND |
459 | | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA |
460 | | * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES |
461 | | * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, |
462 | | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
463 | | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
464 | | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
465 | | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
466 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
467 | | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
468 | | * DAMAGE. |
469 | | * |
470 | | * ==================================================================== |
471 | | * |
472 | | * This software consists of voluntary contributions made by Vovida |
473 | | * Networks, Inc. and many individuals on behalf of Vovida Networks, |
474 | | * Inc. For more information on Vovida Networks, Inc., please see |
475 | | * <http://www.vovida.org/>. |
476 | | * |
477 | | * vi: set shiftwidth=3 expandtab: |
478 | | */ |