📄 dtlstransport.cxx
字号:
}
// no pp error
int used = unprocessedCharPtr - (char *)pt ;
if ( used < len )
{
// body is present .. add it up.
// NB. The Sip Message uses an overlay (again)
// for the body. It ALSO expects that the body
// will be contiguous (of course).
// it doesn't need a new buffer in UDP b/c there
// will only be one datagram per buffer. (1:1 strict)
message->setBody( (char *)pt + used, len - used ) ;
//DebugLog(<<"added " << len-used << " byte body");
}
if ( ! basicCheck( *message ) )
{
delete message ; // cannot use it, so, punt on it...
// basicCheck queued any response required
message = 0 ;
return ;
}
stampReceived( message) ;
#ifdef USE_SIGCOMP
if (mCompression.isEnabled() && sc)
{
const Via &via = message->header(h_Vias).front();
if (message->isRequest())
{
// For requests, the compartment ID is read out of the
// top via header field; if not present, we use the
// TCP connection for identification purposes.
if (via.exists(p_sigcompId))
{
Data compId = via.param(p_sigcompId);
mSigcompStack->provideCompartmentId(
sc, compId.data(), compId.size());
}
else
{
mSigcompStack->provideCompartmentId(sc, this, sizeof(this));
}
}
else
{
// For responses, the compartment ID is supposed to be
// the same as the compartment ID of the request. We
// *could* dig down into the transaction layer to try to
// figure this out, but that's a royal pain, and a rather
// severe layer violation. In practice, we're going to ferret
// the ID out of the the Via header field, which is where we
// squirreled it away when we sent this request in the first place.
Data compId = via.param(p_branch).getSigcompCompartment();
mSigcompStack->provideCompartmentId(sc, compId.data(), compId.size());
}
}
#endif
mStateMachineFifo.add( message ) ;
}
void DtlsTransport::_write( FdSet& fdset )
{
SSL *ssl ;
BIO *wBio ;
int retry = 0 ;
SendData *sendData ;
if ( mSendData != NULL )
sendData = mSendData ;
else
sendData = mTxFifo.getNext() ;
//DebugLog (<< "Sent: " << sendData->data);
//DebugLog (<< "Sending message on udp.");
assert( &(*sendData) );
assert( sendData->destination.getPort() != 0 );
sockaddr peer = sendData->destination.getSockaddr();
ssl = mDtlsConnections[ *((struct sockaddr_in *)&peer) ] ;
/* If we don't have a binding, then we're a client */
if ( ssl == NULL )
{
ssl = SSL_new( mClientCtx ) ;
assert( ssl ) ;
SSL_set_connect_state( ssl ) ;
wBio = BIO_new_dgram( mFd, BIO_NOCLOSE ) ;
assert( wBio ) ;
BIO_dgram_set_peer( wBio, &peer) ;
/* the real rbio will be set by _read */
SSL_set_bio( ssl, mDummyBio, wBio ) ;
/* we should be ready to take this out if the
* connection fails later */
mDtlsConnections [ *((struct sockaddr_in *)&peer) ] = ssl ;
}
int expected;
int count;
#ifdef USE_SIGCOMP
// If message needs to be compressed, compress it here.
if (mSigcompStack &&
sendData->sigcompId.size() > 0 &&
!sendData->isAlreadyCompressed )
{
osc::SigcompMessage *sm = mSigcompStack->compressMessage
(sendData->data.data(), sendData->data.size(),
sendData->sigcompId.data(), sendData->sigcompId.size(),
isReliable());
DebugLog (<< "Compressed message from "
<< sendData->data.size() << " bytes to "
<< sm->getDatagramLength() << " bytes");
expected = sm->getDatagramLength();
count = SSL_Write(ssl,
sm->getDatagramMessage(),
sm->getDatagramLength());
delete sm;
}
else
#endif
{
expected = sendData->data.size();
count = SSL_write(ssl, sendData->data.data(),
sendData->data.size());
}
/*
* all reads go through _read, so the most likely result during a handshake
* will be SSL_ERROR_WANT_READ
*/
if ( count <= 0 )
{
/* cache unqueued data */
mSendData = sendData ;
int err = SSL_get_error( ssl, count ) ;
switch( err )
{
case SSL_ERROR_NONE:
break;
case SSL_ERROR_SSL:
break;
case SSL_ERROR_WANT_READ:
retry = 1 ;
break;
case SSL_ERROR_WANT_WRITE:
retry = 1 ;
fdset.setWrite(mFd);
break;
case SSL_ERROR_SYSCALL:
{
int e = getErrno();
error(e);
InfoLog (<< "Failed (" << e << ") sending to "
<< sendData->destination);
fail(sendData->transactionId);
break;
}
case SSL_ERROR_ZERO_RETURN:
_cleanupConnectionState( ssl, *((struct sockaddr_in *)&peer) ) ;
break ;
case SSL_ERROR_WANT_CONNECT:
break;
case SSL_ERROR_WANT_ACCEPT:
break;
default:
break ;
}
}
else
{
mSendData = NULL ;
}
/*
* ngm: is sendData deleted by a higher layer? Seems to be the case after
* checking with UdpTransport
*/
if ( ! retry && count != int(sendData->data.size()) )
{
ErrLog (<< "UDPTransport - send buffer full" );
fail(sendData->transactionId);
}
}
void
DtlsTransport::_doHandshake( void )
{
DtlsMessage *msg = mHandshakePending.getNext() ;
SSL *ssl = msg->getSsl() ;
delete msg ;
int ret = SSL_do_handshake( ssl ) ;
switch( ret )
{
case SSL_ERROR_NONE:
break;
case SSL_ERROR_SSL:
break;
case SSL_ERROR_WANT_READ:
break;
case SSL_ERROR_WANT_WRITE:
break;
case SSL_ERROR_SYSCALL:
break;
case SSL_ERROR_ZERO_RETURN:
break;
case SSL_ERROR_WANT_CONNECT:
break;
case SSL_ERROR_WANT_ACCEPT:
break;
default:
break ;
}
}
void
DtlsTransport::process(FdSet& fdset)
{
// pull buffers to send out of TxFifo
// receive datagrams from fd
// preparse and stuff into RxFifo
mTimer.process() ;
while ( mHandshakePending.messageAvailable() )
_doHandshake() ;
if ( ( mSendData != NULL || mTxFifo.messageAvailable() )
&& fdset.readyToWrite( mFd ) )
_write( fdset ) ;
// !jf! this may have to change - when we read a message that is too big
if ( fdset.readyToRead(mFd) )
_read( fdset ) ;
}
void
DtlsTransport::buildFdSet( FdSet& fdset )
{
fdset.setRead(mFd);
if ( mSendData != NULL || mTxFifo.messageAvailable() )
{
fdset.setWrite(mFd);
}
}
void
DtlsTransport::_cleanupConnectionState( SSL *ssl, struct sockaddr_in peer )
{
/*
* SSL_free decrements the ref-count for mDummyBio by 1, so
* add 1 to the ref-count to make sure it does not get free'd
*/
CRYPTO_add( &mDummyBio->references, 1, CRYPTO_LOCK_BIO ) ;
SSL_free( ssl ) ;
mDtlsConnections.erase( peer ) ;
}
void
DtlsTransport::_mapDebug( const char *where, const char *action, SSL *ssl )
{
fprintf( stderr, "%s: %s\t%p\n", where, action, ssl ) ;
fprintf( stderr, "map sizet = %d\n", mDtlsConnections.size() ) ;
}
void
DtlsTransport::_printSock( const struct sockaddr_in *sock )
{
fprintf( stderr, "addr = %s\t port = %d\n", inet_ntoa( sock->sin_addr ),
ntohs( sock->sin_port ) ) ;
}
#endif /* USE_DTLS */
/* ====================================================================
* The Vovida Software License, Version 1.0
*
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
* and "Vovida Open Communication Application Library (VOCAL)" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact vocal@vovida.org.
*
* 4. Products derived from this software may not be called "VOCAL", nor
* may "VOCAL" appear in their name, without prior written
* permission of Vovida Networks, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by Vovida
* Networks, Inc. and many individuals on behalf of Vovida Networks,
* Inc. For more information on Vovida Networks, Inc., please see
* <http://www.vovida.org/>.
*
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -