reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
UdpTransport.cxx
Go to the documentation of this file.
1#if defined(HAVE_CONFIG_H)
2#include "config.h"
3#endif
4
5#include <memory>
6#include <utility>
7
12#include "rutil/Data.hxx"
13#include "rutil/DnsUtil.hxx"
14#include "rutil/Logger.hxx"
15#include "rutil/Socket.hxx"
17#include "rutil/compat.hxx"
18#include "rutil/stun/Stun.hxx"
19
20#ifdef USE_SIGCOMP
21#include <osc/Stack.h>
22#include <osc/StateChanges.h>
23#include <osc/SigcompMessage.h>
24#endif
25
26#define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT
27
28using namespace std;
29using namespace resip;
30
32 int portNum,
33 IpVersion version,
34 StunSetting stun,
35 const Data& pinterface,
37 Compression &compression,
38 unsigned transportFlags)
39 : InternalTransport(fifo, portNum, version, pinterface, socketFunc, compression, transportFlags),
40 mSigcompStack(nullptr),
41 mStunSetting(stun),
42 mExternalUnknownDatagramHandler(nullptr),
43 mInWritable(false)
44{
45 mPollEventCnt = 0;
48 mStunTxIdValid = false;
49 mStunTxId.fill(0);
53 bind(); // also makes it non-blocking
54
55 InfoLog (<< "Creating UDP transport host=" << pinterface
56 << " port=" << mTuple.getPort()
57 << " ipv4=" << bool(version==V4) );
58
59#ifdef USE_SIGCOMP
61 {
62 DebugLog (<< "Compression enabled for transport: " << *this);
63 mSigcompStack = new osc::Stack(mCompression.getStateHandler());
65 }
66 else
67 {
68 DebugLog (<< "Compression disabled for transport: " << *this);
69 }
70#else
71 DebugLog (<< "No compression library available: " << *this);
72#endif
73 mTxFifo.setDescription("UdpTransport::mTxFifo");
74}
75
77{
78 InfoLog(<< "Shutting down " << mTuple
79 <<" tf="<<mTransportFlags<<" evt="<<(mPollGrp?1:0)
80 <<" stats:"
81 <<" poll="<<mPollEventCnt
82 <<" txtry="<<mTxTryCnt
83 <<" txmsg="<<mTxMsgCnt
84 <<" txfail="<<mTxFailCnt
85 <<" rxtry="<<mRxTryCnt
86 <<" rxmsg="<<mRxMsgCnt
87 <<" rxka="<<mRxKeepaliveCnt
88 <<" rxtr="<<mRxTransactionCnt
89 );
90#ifdef USE_SIGCOMP
91 delete mSigcompStack;
92#endif
93 setPollGrp(nullptr);
94}
95
96void
98{
99 if(mPollGrp)
100 {
102 mPollItemHandle=nullptr;
103 }
104
105 if(mFd!=INVALID_SOCKET && grp)
106 {
108 // above released by InternalTransport destructor
109 // ?bwc? Is this really a good idea? If the InternalTransport d'tor is
110 // freeing this, shouldn't InternalTransport::setPollGrp() handle
111 // creating it?
112 }
113
115}
116
117
121void
123{
125
127 {
128 processTxAll();
129 // FALLTHRU to code below in case queue not-empty
130 // shouldn't ever happen (with current code)
131 // but in future we may throttle transmits
132 }
133
134 if ( mPollGrp )
135 {
136 updateEvents();
137 }
138
139 mStateMachineFifo.flush();
140}
141
142void
144{
145 //assert( mPollGrp );
146 bool haveMsg = mTxFifoOutBuffer.messageAvailable();
147 if ( !mInWritable && haveMsg )
148 {
150 mInWritable = true;
151 }
152 else if ( mInWritable && !haveMsg )
153 {
155 mInWritable = false;
156 }
157}
158
159
160void
162{
164 if ( mask & FPEM_Error )
165 {
166 resip_assert(0);
167 }
168 if ( mask & FPEM_Write )
169 {
170 processTxAll();
171 updateEvents(); // turn-off writability
172 }
173 if ( mask & FPEM_Read )
174 {
175 processRxAll();
176 }
177 mStateMachineFifo.flush();
178}
179
185bool
187{
188 return false;
189}
190
191void
193{
194 fdset.setRead(mFd);
195
196 if (mTxFifoOutBuffer.messageAvailable())
197 {
198 fdset.setWrite(mFd);
199 }
200}
201
202void
204{
206
207 // pull buffers to send out of TxFifo
208 // receive datagrams from fd
209 // preparse and stuff into RxFifo
210 if (fdset.readyToWrite(mFd))
211 {
212 processTxAll();
213 }
214
215 if ( fdset.readyToRead(mFd) )
216 {
217 processRxAll();
218 }
219 mStateMachineFifo.flush();
220}
221
227void
229{
230 SendData *msg;
231 ++mTxTryCnt;
232 while ( (msg=mTxFifoOutBuffer.getNext(RESIP_FIFO_NOWAIT)) != nullptr)
233 {
234 processTxOne(msg);
235 // With UDP we don't need to worry about write blocking (I hope)
237 {
238 break;
239 }
240 }
241}
242
243void
245{
246 resip_assert(data);
247 if(data->command != SendData::NoCommand)
248 {
249 // We don't handle any special SendData commands in the UDP transport yet.
250 return;
251 }
252 ++mTxMsgCnt;
253 std::unique_ptr<SendData> sendData(data);
254 //DebugLog (<< "Sent: " << sendData->data);
255 //DebugLog (<< "Sending message on udp.");
256 resip_assert( sendData->destination.getPort() != 0 );
257
258 const sockaddr& addr = sendData->destination.getSockaddr();
259 int expected;
260 int count;
261
262#ifdef USE_SIGCOMP
263 // If message needs to be compressed, compress it here.
264 if (mSigcompStack &&
265 sendData->sigcompId.size() > 0 &&
266 !sendData->isAlreadyEncoded )
267 {
268 osc::SigcompMessage *sm = mSigcompStack->compressMessage
269 (sendData->data.data(), sendData->data.size(),
270 sendData->sigcompId.data(), sendData->sigcompId.size(),
271 isReliable());
272
273 DebugLog (<< "Compressed message from "
274 << sendData->data.size() << " bytes to "
275 << sm->getDatagramLength() << " bytes");
276
277 expected = sm->getDatagramLength();
278
279 count = sendto(mFd,
280 sm->getDatagramMessage(),
281 sm->getDatagramLength(),
282 0, // flags
283 &addr, sendData->destination.length());
284 delete sm;
285 }
286 else
287#endif
288 {
289 expected = (int)sendData->data.size();
290 count = sendto(mFd,
291 sendData->data.data(), (int)sendData->data.size(),
292 0, // flags
293 &addr, (int)sendData->destination.length());
294 }
295
296 if ( count == SOCKET_ERROR )
297 {
298 int e = getErrno();
299 error(e);
300 InfoLog (<< "Failed (" << e << ") sending to " << sendData->destination);
301 fail(sendData->transactionId);
302 ++mTxFailCnt;
303 }
304 else
305 {
306 if (count != expected)
307 {
308 ErrLog (<< "UDPTransport - send buffer full" );
309 fail(sendData->transactionId);
310 }
311 }
312}
313
320void
322{
323 ++mRxTryCnt;
324 for (;;)
325 {
326 // TBD: check StateMac capacity
327 Tuple sender(mTuple);
328 const int len = processRxRecv(sender);
329 if (len <= 0)
330 {
331 break;
332 }
333 ++mRxMsgCnt;
334 processRxParse(len, sender);
336 {
337 break;
338 }
339 }
340}
341
342/*
343 * Receive from socket and store results into {buffer}. Updates
344 * {sender} with who sent the packet.
345 * Return length of data read:
346 * 0 if no data read and no more data to read (EAGAIN)
347 * >0 if data read and may be more data to read
348**/
349int
351{
352 for (;;)
353 {
354 // !jf! how do we tell if it discarded bytes
355 // !ah! we use the len-1 trick :-(
356 socklen_t slen = sender.length();
357 int len = recvfrom( mFd,
358 mRxBuffer.data(),
360 0 /*flags */,
361 &sender.getMutableSockaddr(),
362 &slen);
363 if ( len == SOCKET_ERROR )
364 {
365 int err = getErrno();
366 if ( err != EAGAIN && err != EWOULDBLOCK ) // Treat EGAIN and EWOULDBLOCK as the same: http://stackoverflow.com/questions/7003234/which-systems-define-eagain-and-ewouldblock-as-different-values
367 {
368 error( err );
369 }
370 len = 0;
371 }
372 if (len + 1 >= MaxMessageSize)
373 {
374 InfoLog( << "Datagram exceeded max length " << MaxMessageSize);
375 continue;
376 }
377 return len;
378 }
379}
380
381
385void
386UdpTransport::processRxParse(int len, const Tuple& sender)
387{
388 //handle incoming CRLFCRLF keep-alive packets
389 if (len == 4 &&
390 strncmp(mRxBuffer.data(), Symbols::CRLFCRLF, len) == 0)
391 {
392 StackLog(<<"Throwing away incoming firewall keep-alive");
394 return;
395 }
396
397 // this must be a STUN response (or garbage)
398 if (mRxBuffer[0] == 1 && mRxBuffer[1] == 1 && ipVersion() == V4)
399 {
400 StunMessage resp;
401
402 resip::Lock lock(myMutex);
403
404 // Drop unsolicited responses - we must have an outstanding request. This
405 // also stops an attacker from priming mStunMappedAddress before any test
406 // is started.
407 if (!mStunTxIdValid)
408 {
409 StackLog(<< "Dropping unsolicited STUN response from " << sender);
410 return;
411 }
412
413 // Validate the response source address against the STUN server we queried.
414 // Ignore transport type (the response always arrives on this UDP socket)
415 // but require the address and port to match (RFC 5389).
416 if (!mStunServerTuple.isEqual(sender, false /*ignorePort*/, true /*ignoreTransport*/))
417 {
418 WarningLog(<< "Dropping STUN response from unexpected source " << sender
419 << " (expected " << mStunServerTuple << ")");
420 return;
421 }
422
423 if (!stunParseMessage(mRxBuffer.data(), len, resp, false))
424 {
425 // Malformed response from the expected server.
426 mStunResult = StunResultResponseParseFailed;
427 return;
428 }
429
430 // The transaction id (including the magic cookie) MUST match the request
431 // we sent (RFC 5389 section 10.1). Reject blind/off-path spoofed responses
432 // while leaving mStunResult unchanged so the genuine response can still be
433 // accepted.
434 if (memcmp(resp.msgHdr.id.octet, mStunTxId.data(), mStunTxId.size()) != 0)
435 {
436 WarningLog(<< "Dropping STUN response with mismatched transaction id from " << sender);
437 return;
438 }
439
440 // Response authenticated by source address and transaction id - extract
441 // the mapped address.
442 mStunResult = StunResultResponseParseFailed;
443 in_addr sin_addr;
444 // Use XorMappedAddress if present - if not use MappedAddress
445 if(resp.hasXorMappedAddress)
446 {
447 uint16_t id16 = resp.msgHdr.id.octet[0]<<8
448 | resp.msgHdr.id.octet[1];
449 uint32_t id32 = resp.msgHdr.id.octet[0]<<24
450 | resp.msgHdr.id.octet[1]<<16
451 | resp.msgHdr.id.octet[2]<<8
452 | resp.msgHdr.id.octet[3];
455
456#if defined(WIN32)
457 sin_addr.S_un.S_addr = htonl(resp.xorMappedAddress.ipv4.addr);
458#else
459 sin_addr.s_addr = htonl(resp.xorMappedAddress.ipv4.addr);
460#endif
461 mStunMappedAddress = Tuple(sin_addr,resp.xorMappedAddress.ipv4.port, UDP);
462 mStunResult = StunResultSuccess;
463 mStunTxIdValid = false; // consume the request; ignore replayed responses
464 }
465 else if(resp.hasMappedAddress)
466 {
467#if defined(WIN32)
468 sin_addr.S_un.S_addr = htonl(resp.mappedAddress.ipv4.addr);
469#else
470 sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);
471#endif
472 mStunMappedAddress = Tuple(sin_addr,resp.mappedAddress.ipv4.port, UDP);
473 mStunResult = StunResultSuccess;
474 mStunTxIdValid = false; // consume the request; ignore replayed responses
475 }
476 return;
477 }
478
479 // this must be a STUN request (or garbage)
480 if (mRxBuffer[0] == 0 && mRxBuffer[1] == 1 && ipVersion() == V4)
481 {
482 // Drop stun requests unless StunEnabled is set and return false to indicate
483 // we did not consume the buffer
484 if (mStunSetting == StunDisabled) return;
485
486 bool changePort = false;
487 bool changeIp = false;
488
489 StunAddress4 myAddr;
490 const sockaddr_in& bi = (const sockaddr_in&)boundInterface();
491 myAddr.addr = ntohl(bi.sin_addr.s_addr);
492 myAddr.port = ntohs(bi.sin_port);
493
494 StunAddress4 from; // packet source
495 const sockaddr_in& fi = (const sockaddr_in&)sender.getSockaddr();
496 from.addr = ntohl(fi.sin_addr.s_addr);
497 from.port = ntohs(fi.sin_port);
498
499 StunMessage resp;
500 StunAddress4 dest;
501 StunAtrString hmacPassword;
502 hmacPassword.sizeValue = 0;
503
504 StunAddress4 secondary;
505 secondary.port = 0;
506 secondary.addr = 0;
507
508 bool ok = stunServerProcessMsg( mRxBuffer.data(), len, // input buffer
509 from, // packet source
510 secondary, // not used
511 myAddr, // address to fill into response
512 myAddr, // not used
513 &resp, // stun response
514 &dest, // where to send response
515 &hmacPassword, // not used
516 &changePort, // not used
517 &changeIp, // not used
518 false ); // logging
519
520 if (ok)
521 {
522 DebugLog(<<"Got UDP STUN keepalive. Sending response...");
523 char* response = new char[STUN_MAX_MESSAGE_SIZE];
524 int rlen = stunEncodeMessage( resp,
525 response,
527 hmacPassword,
528 false );
529 SendData* stunResponse = new SendData(sender, response, rlen);
530 mTxFifo.add(stunResponse);
531 }
532 return;
533 }
534
535 processRxParseSip(mRxBuffer.data(), len, sender);
536}
537
538void
539UdpTransport::processRxParseSip(char* buffer, int len, const Tuple& sender)
540{
541#ifdef USE_SIGCOMP
542 osc::StateChanges *sc = 0;
543#endif
544
545 // Attempt to decode SigComp message, if appropriate.
546 if ((buffer[0] & 0xf8) == 0xf8)
547 {
548 if (!mCompression.isEnabled())
549 {
550 InfoLog(<< "Discarding unexpected SigComp Message");
551 return;
552 }
553#ifdef USE_SIGCOMP
554 const size_t uncompressedLength = mSigcompStack->uncompressMessage(buffer, len, mRxUncompressedBuffer.data(), mRxUncompressedBuffer.size(), sc);
555
556 DebugLog (<< "Uncompressed message from "
557 << len << " bytes to "
558 << uncompressedLength << " bytes");
559
560 osc::SigcompMessage *nack = mSigcompStack->getNack();
561
562 if (nack)
563 {
564 mTxFifo.add(new SendData(sender,
565 Data(nack->getDatagramMessage(),
566 nack->getDatagramLength()),
569 true));
570 delete nack;
571 }
572
573 buffer = mRxUncompressedBuffer.data();
574 len = uncompressedLength;
575#endif
576 }
577
578 auto* const msgBuffer = MsgHeaderScanner::allocateBuffer(len);
579 memcpy(msgBuffer, buffer, len);
580 msgBuffer[len] = '\0'; // null terminate the buffer string just to make debug easier and reduce errors
581
582 //DebugLog ( << "UDP Rcv : " << len << " b" );
583 //DebugLog ( << Data(buffer, len).escaped().c_str());
584
585 std::unique_ptr<SipMessage> message(new SipMessage(&mTuple));
586
587 // set the received from information into the received= parameter in the
588 // via
589
590 // It is presumed that UDP Datagrams are arriving atomically and that
591 // each one is a unique SIP message
592
593 // Save all the info where this message came from
594 message->setSource(sender);
595 //DebugLog (<< "Received from: " << sender);
596
597 // Tell the SipMessage about this datagram buffer.
598 // WATCHOUT: below here buffer is consumed by message
599 message->addBuffer(msgBuffer);
600
601 mMsgHeaderScanner.prepareForMessage(message.get());
602
603 char *unprocessedCharPtr;
604 if (mMsgHeaderScanner.scanChunk(msgBuffer,
605 len,
606 &unprocessedCharPtr) !=
608 {
609 StackLog(<<"Scanner rejecting datagram as unparsable / fragmented from " << sender);
610 StackLog(<< Data(Data::Borrow, msgBuffer, len));
611 if(mExternalUnknownDatagramHandler)
612 {
613 std::unique_ptr<Data> datagram(new Data(msgBuffer, len));
614 (*mExternalUnknownDatagramHandler)(this, sender, std::move(datagram));
615 }
616
617 return;
618 }
619
620 // no pp error
621 const int used = static_cast<int>(unprocessedCharPtr - msgBuffer);
622
623 if (used < len)
624 {
625 // body is present .. add it up.
626 // NB. The Sip Message uses an overlay (again)
627 // for the body. It ALSO expects that the body
628 // will be contiguous (of course).
629 // it doesn't need a new buffer in UDP b/c there
630 // will only be one datagram per buffer. (1:1 strict)
631
632 message->setBody(msgBuffer + used, len - used);
633 //DebugLog(<<"added " << len-used << " byte body");
634 }
635
636 // .bwc. basicCheck takes up substantial CPU. Don't bother doing it
637 // if we're overloaded.
641 && message->isRequest()))
642 {
643 // .bwc. If this fifo is REJECTING_NEW_WORK, we will drop
644 // requests but not responses ( ?bwc? is this right for ACK?).
645 // If we are REJECTING_NON_ESSENTIAL,
646 // we reject all incoming work, since losing something from the
647 // wire will not cause instability or leaks (see
648 // CongestionManager.hxx)
649
650 // .bwc. This handles all appropriate checking for whether
651 // this is a response or an ACK.
652 std::unique_ptr<SendData> tryLater(make503(*message, getExpectedWaitForIncoming()));
653 if (tryLater)
654 {
655 send(std::move(tryLater));
656 }
657
658 return; // dropping message due to congestion
659 }
660
661 if (!basicCheck(*message))
662 {
663 // cannot use it, so, punt on it...
664 // basicCheck queued any response required
665 return;
666 }
667
668 stampReceived(message.get());
669
670#ifdef USE_SIGCOMP
671 if (mCompression.isEnabled() && sc)
672 {
673 const Via &via = message->header(h_Vias).front();
674 if (message->isRequest())
675 {
676 // For requests, the compartment ID is read out of the
677 // top via header field; if not present, we use the
678 // TCP connection for identification purposes.
679 if (via.exists(p_sigcompId))
680 {
681 Data compId = via.param(p_sigcompId);
682 if(!compId.empty())
683 {
684 // .bwc. Crash was happening here. Why was there an empty sigcomp id?
685 mSigcompStack->provideCompartmentId(sc, compId.data(), compId.size());
686 }
687 }
688 else
689 {
690 mSigcompStack->provideCompartmentId(sc, this, sizeof(this));
691 }
692 }
693 else
694 {
695 // For responses, the compartment ID is supposed to be
696 // the same as the compartment ID of the request. We
697 // *could* dig down into the transaction layer to try to
698 // figure this out, but that's a royal pain, and a rather
699 // severe layer violation. In practice, we're going to ferret
700 // the ID out of the the Via header field, which is where we
701 // squirreled it away when we sent this request in the first place.
702 // !bwc! This probably shouldn't be going out over the wire.
703 Data compId = via.param(p_branch).getSigcompCompartment();
704 if(!compId.empty())
705 {
706 mSigcompStack->provideCompartmentId(sc, compId.data(), compId.size());
707 }
708 }
709 }
710#endif
711
712 pushRxMsgUp(message.release());
714}
715
716bool
718{
719 bool changePort=false;
720 bool changeIP=false;
721
722 StunAtrString username;
723 StunAtrString password;
724
725 username.sizeValue = 0;
726 password.sizeValue = 0;
727
728 StunMessage req;
729 stunBuildReqSimple(&req, username, changePort , changeIP , 1);
730
731 // Replace the first 4 bytes of the header with the correct magic cookie required for RFC5389
732 uint32_t* magicCookieField = (uint32_t*)req.msgHdr.id.octet;
733 *magicCookieField = htonl(StunMagicCookie);
734
735 char* buf = new char[STUN_MAX_MESSAGE_SIZE];
736 int len = STUN_MAX_MESSAGE_SIZE;
737
738 int rlen = stunEncodeMessage(req, buf, len, password, false);
739
740 {
741 // Record the request state so processRxParse() can authenticate the
742 // response by source address and transaction id. Only a single STUN test
743 // is tracked at a time - this overwrites any in-flight request (see
744 // stunSendTest() docs).
745 resip::Lock lock(myMutex);
746 memcpy(mStunTxId.data(), req.msgHdr.id.octet, mStunTxId.size());
747 mStunServerTuple = dest;
748 mStunTxIdValid = true;
749 mStunResult = StunResultNoResponse;
750 }
751
752 SendData* stunRequest = new SendData(dest, buf, rlen);
753 mTxFifo.add(stunRequest);
754
755 return true;
756}
757
760{
761 resip::Lock lock(myMutex);
762
763 if (mStunResult == StunResultSuccess)
764 {
765 mappedAddress = mStunMappedAddress;
766 }
767 return mStunResult;
768}
769
770void
772{
773 mExternalUnknownDatagramHandler = handler;
774}
775
776void
778{
779 setSocketRcvBufLen(mFd, buflen);
780}
781
782/* ====================================================================
783 * The Vovida Software License, Version 1.0
784 *
785 * Copyright (c) 2026 SIP Spectrum, Inc. https://www.sipspectrum.com
786 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
787 *
788 * Redistribution and use in source and binary forms, with or without
789 * modification, are permitted provided that the following conditions
790 * are met:
791 *
792 * 1. Redistributions of source code must retain the above copyright
793 * notice, this list of conditions and the following disclaimer.
794 *
795 * 2. Redistributions in binary form must reproduce the above copyright
796 * notice, this list of conditions and the following disclaimer in
797 * the documentation and/or other materials provided with the
798 * distribution.
799 *
800 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
801 * and "Vovida Open Communication Application Library (VOCAL)" must
802 * not be used to endorse or promote products derived from this
803 * software without prior written permission. For written
804 * permission, please contact vocal@vovida.org.
805 *
806 * 4. Products derived from this software may not be called "VOCAL", nor
807 * may "VOCAL" appear in their name, without prior written
808 * permission of Vovida Networks, Inc.
809 *
810 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
811 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
812 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
813 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
814 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
815 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
816 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
817 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
818 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
819 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
820 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
821 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
822 * DAMAGE.
823 *
824 * ====================================================================
825 *
826 * This software consists of voluntary contributions made by Vovida
827 * Networks, Inc. and many individuals on behalf of Vovida Networks,
828 * Inc. For more information on Vovida Networks, Inc., please see
829 * <http://www.vovida.org/>.
830 *
831 * vi: set shiftwidth=3 expandtab:
832 */
#define RESIP_FIFO_NOWAIT
The getNext() method takes an argument {ms} that normally the number of milliseconds to wait.
#define FPEM_Write
Definition FdPoll.hxx:30
#define FPEM_Read
Definition FdPoll.hxx:29
#define FPEM_Error
Definition FdPoll.hxx:31
#define DebugLog(args_)
Definition Logger.hxx:128
#define StackLog(args_)
Definition Logger.hxx:125
#define InfoLog(args_)
Definition Logger.hxx:131
#define WarningLog(args_)
Definition Logger.hxx:134
#define ErrLog(args_)
Definition Logger.hxx:137
#define resip_assert(x)
This file needs to work for both C and C++ code.
Handles cross-platform sockets compatibility.
#define INVALID_SOCKET
Definition Socket.hxx:95
#define SOCKET_ERROR
Definition Socket.hxx:96
#define STUN_MAX_MESSAGE_SIZE
Definition Stun.hxx:23
#define RESIP_TRANSPORT_FLAG_TXNOW
Definition Transport.hxx:68
#define RESIP_TRANSPORT_FLAG_RXALL
Definition Transport.hxx:66
#define RESIP_TRANSPORT_FLAG_TXALL
Definition Transport.hxx:67
void addCompressorsToStack(osc::Stack *)
osc::StateHandler & getStateHandler()
@ REJECTING_NEW_WORK
Overloaded, should refuse new work.
@ REJECTING_NON_ESSENTIAL
Rejecting all work that is non-essential to the health of the system (ie, if dropping something is li...
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
static const Data Empty
Constant that represents a zero-length data.
Definition Data.hxx:882
@ Borrow
The Data instance is borrowing the memory from the passed in buffer.
Definition Data.hxx:260
bool empty() const noexcept
Checks whether the Data is empty.
Definition Data.hxx:591
size_type size() const noexcept
Returns the number of bytes in this Data.
Definition Data.hxx:599
const char * data() const noexcept
Returns a pointer to the contents of this Data.
Definition Data.hxx:608
Interface functor for external unrecognized datagram handling.
virtual FdPollItemHandle addPollItem(Socket sock, FdPollEventMask newMask, FdPollItemIf *item)=0
virtual void delPollItem(FdPollItemHandle handle)=0
virtual void modPollItem(FdPollItemHandle handle, FdPollEventMask newMask)=0
Object-oriented wrapper for your platform's file-descriptor set.
Definition Socket.hxx:162
bool readyToWrite(Socket fd)
Definition Socket.hxx:194
bool readyToRead(Socket fd)
Definition Socket.hxx:189
void setRead(Socket fd)
Definition Socket.hxx:204
void setWrite(Socket fd)
Definition Socket.hxx:216
A templated, threadsafe message-queue class.
Definition Fifo.hxx:16
static Socket socket(TransportType type, IpVersion ipVer)
virtual void send(std::unique_ptr< SendData > data)
ConsumerFifoBuffer< SendData > mTxFifoOutBuffer
virtual void setPollGrp(FdPollGrp *grp)
void prepareForMessage(SipMessage *msg)
MsgHeaderScanner::ScanChunkResult scanChunk(char *chunk, unsigned int chunkLength, char **unprocessedCharPtr)
static char * allocateBuffer(size_t size)
SendDataCommand command
Definition SendData.hxx:80
Represents a SIP message.
static const char * CRLFCRLF
Definition Symbols.hxx:22
void drainDscpRefresh()
Serves a pending refresh and a pending report.
std::unique_ptr< SendData > make503(SipMessage &msg, uint16_t retryAfter)
IpVersion ipVersion() const
const TransportType transport() const
unsigned mTransportFlags
virtual void pushRxMsgUp(SipMessage *msg)
static void stampReceived(SipMessage *request)
uint32_t getExpectedWaitForIncoming() const
void fail(const Data &tid, TransportFailure::FailureReason reason=TransportFailure::Failure, int subCode=0)
Posts a TransportFailure to the TransactionMessage Fifo.
Compression & mCompression
bool basicCheck(const SipMessage &msg)
Perform basic sanity checks on message.
const sockaddr & boundInterface() const
CongestionManager::RejectionBehavior getRejectionBehaviorForIncoming() const
static void error(int e)
Generates a generic log for the platform specific socket error number.
ProducerFifoBuffer< TransactionMessage > mStateMachineFifo
Represents a network address.
Definition Tuple.hxx:59
sockaddr & getMutableSockaddr()
Retrieve the binary representation of the socket address for this tuple.
Definition Tuple.hxx:113
FlowKey mFlowKey
This is a (largely) opaque key that subclasses of Transport will use to help record/find flows.
Definition Tuple.hxx:189
void setType(TransportType type)
Definition Tuple.hxx:123
bool isEqual(const Tuple &tuple, bool ignorePort=false, bool ignoreTransport=false) const
compares this tuple with the one passed in for family, port and address equality.
Definition Tuple.cxx:680
socklen_t length() const
Definition Tuple.cxx:655
int getPort() const
Definition Tuple.cxx:466
const sockaddr & getSockaddr() const
Retrieve a const binary representation of the socket address for this tuple.
Definition Tuple.hxx:109
UdpTransport(Fifo< TransactionMessage > &fifo, int portNum, IpVersion version, StunSetting stun, const Data &interfaceObj, AfterSocketCreationFuncPtr socketFunc=nullptr, Compression &compression=Compression::Disabled, unsigned transportFlags=0)
void setExternalUnknownDatagramHandler(ExternalUnknownDatagramHandler *handler)
Installs a handler for the unknown datagrams arriving on the udp transport.
virtual bool isReliable() const
virtual void setRcvBufLen(int buflen)
void processRxParse(int len, const Tuple &sender)
Parse the contents of {mRxBuffer} and do something with it.
bool stunSendTest(const Tuple &dest)
Send a STUN Binding Request to dest for public-address discovery.
osc::Stack * mSigcompStack
int processRxRecv(Tuple &sender)
void processTxAll()
Added support for TXNOW and TXALL.
virtual void setPollGrp(FdPollGrp *grp)
static constexpr int MaxMessageSize
virtual void buildFdSet(FdSet &fdset)
Adds the Transport's socket FD to the appropriate read or write sets as applicable.
std::array< char, MaxMessageSize > mRxBuffer
void processRxParseSip(char *buffer, int len, const Tuple &sender)
void processTxOne(SendData *data)
void processRxAll()
Add options RXALL (to try receive all readable data).
virtual void processPollEvent(FdPollEventMask mask)
Called by PollGrp when activity is possible.
StunResult stunResult(Tuple &mappedAddress)
Return the result of the most recent stunSendTest(); on StunResultSuccess, mappedAddress is filled wi...
virtual bool hasDataToSend() const
If we return true, the TransactionController will set the timeout to zero so that process() is called...
virtual void process()
Called after a message is added.
Represents the "via-parm" element in the RFC 3261 grammar.
Definition Via.hxx:18
bool exists(const Param< Via > &paramType) const
Definition Via.cxx:266
const Data & param(const ExtensionParameter &param) const
Const accessor for non-natively-supported parameter types.
This file is used to handle compatibility fixes/tweaks so reSIProcate can function on multiple platfo...
dcm! – add UnusedChecking(_enum) below;
unsigned long FlowKey
Definition Tuple.hxx:37
void(* AfterSocketCreationFuncPtr)(Socket s, int transportType, const char *file, int line)
Definition Socket.hxx:107
unsigned short FdPollEventMask
Definition FdPoll.hxx:28
bool stunServerProcessMsg(char *buf, unsigned int bufLen, StunAddress4 &from, StunAddress4 &secondary, StunAddress4 &myAddr, StunAddress4 &altAddr, StunMessage *resp, StunAddress4 *destination, StunAtrString *hmacPassword, bool *changePort, bool *changeIp, bool verbose)
Definition Stun.cxx:1368
unsigned short uint16_t
Definition Stun.hxx:30
std::unique_lock< Mutex > Lock
A convenience class to lock a Lockable (such as a Mutex) on object creation, and unlock on destructio...
Definition Lock.hxx:28
unsigned int uint32_t
Definition Stun.hxx:34
void stunBuildReqSimple(StunMessage *msg, const StunAtrString &username, bool changePort, bool changeIp, unsigned int id)
Definition Stun.cxx:2029
int setSocketRcvBufLen(Socket fd, int buflen)
Definition Socket.cxx:244
int getErrno()
Definition Socket.hxx:97
static const uint32_t StunMagicCookie
Definition Stun.hxx:118
bool stunParseMessage(char *buf, unsigned int bufLen, StunMessage &msg, bool verbose)
Definition Stun.cxx:233
IpVersion
An enumeration of IP versions.
unsigned int stunEncodeMessage(const StunMessage &msg, char *buf, unsigned int bufLen, const StunAtrString &password, bool verbose)
Definition Stun.cxx:760
StunAddress4 ipv4
Definition Stun.hxx:147
uint16_t sizeValue
Definition Stun.hxx:173
bool hasMappedAddress
Definition Stun.hxx:211
bool hasXorMappedAddress
Definition Stun.hxx:254
StunAtrAddress4 xorMappedAddress
Definition Stun.hxx:255
StunMsgHdr msgHdr
Definition Stun.hxx:209
StunAtrAddress4 mappedAddress
Definition Stun.hxx:212
unsigned char octet[16]
Definition Stun.hxx:43