reSIProcate/stack  9694
DtlsTransport.cxx
Go to the documentation of this file.
00001 
00002 #if defined(HAVE_CONFIG_H)
00003   #include "config.h"
00004 #endif
00005 
00006 #ifdef USE_SSL
00007 #ifdef USE_DTLS
00008 
00009 #include <memory>
00010 
00011 #ifndef RESIP_COMPAT_HXX
00012 #include "rutil/compat.hxx"
00013 #endif
00014 
00015 #ifndef RESIP_DATA_HXX
00016 #include "rutil/Data.hxx"
00017 #endif
00018 
00019 #ifndef RESIP_DNSUTIL_HXX
00020 #include "rutil/DnsUtil.hxx"
00021 #endif
00022 
00023 #ifndef RESIP_SOCKET_HXX
00024 #include "rutil/Socket.hxx"
00025 #endif
00026 
00027 #ifndef RESIP_LOGGER_HXX
00028 #include "rutil/Logger.hxx"
00029 #endif
00030 
00031 #ifndef RESIP_SIPMESSAGE_HXX
00032 #include "resip/stack/SipMessage.hxx"
00033 #endif
00034 
00035 #ifndef RESIP_HELPER_HXX
00036 #include "resip/stack/Helper.hxx"
00037 #endif
00038 
00039 #ifndef RESIP_SECURITY_HXX
00040 #include "resip/stack/ssl/Security.hxx"
00041 #endif
00042 
00043 #ifndef RESIP_DTLSMESSAGE_HXX
00044 #include "resip/stack/DtlsMessage.hxx"
00045 #endif
00046 
00047 #ifndef RESIP_DTLSTRANSPORT_HXX
00048 #include "resip/stack/ssl/DtlsTransport.hxx"
00049 #endif
00050 
00051 #include "rutil/WinLeakCheck.hxx"
00052 
00053 #include <openssl/e_os2.h>
00054 #include <openssl/evp.h>
00055 #include <openssl/crypto.h>
00056 #include <openssl/err.h>
00057 #include <openssl/pem.h>
00058 #include <openssl/pkcs7.h>
00059 #include <openssl/x509v3.h>
00060 #include <openssl/ssl.h>
00061 
00062 #ifdef USE_SIGCOMP
00063 #include <osc/Stack.h>
00064 #include <osc/StateChanges.h>
00065 #include <osc/SigcompMessage.h>
00066 #endif
00067 
00068 #define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT
00069 
00070 using namespace std;
00071 using namespace resip;
00072 
00073 // .slg. Note that DTLS handshakes were really broken in older versions of OpenSSL 0.9.8
00074 //       You should use at least version 0.9.8g for both client and server.
00075 
00076 DtlsTransport::DtlsTransport(Fifo<TransactionMessage>& fifo,
00077                              int portNum,
00078                              IpVersion version,
00079                              const Data& interfaceObj,
00080                              Security& security,
00081                              const Data& sipDomain,
00082                              AfterSocketCreationFuncPtr socketFunc,
00083                              Compression& compression)
00084  : UdpTransport( fifo, portNum, version,
00085    StunDisabled, interfaceObj, socketFunc, compression ),
00086    mTimer( mHandshakePending ),
00087    mSecurity( &security ),
00088    mDomain(sipDomain)
00089 {
00090    setTlsDomain(sipDomain);
00091    InfoLog ( << "Creating DTLS transport host=" << interfaceObj
00092              << " port=" << mTuple.getPort()
00093              << " ipv4=" << version ) ;
00094 
00095    mTxFifo.setDescription("DtlsTransport::mTxFifo");
00096 
00097    mTuple.setType( transport() );
00098 
00099    mClientCtx = mSecurity->createDomainCtx(DTLSv1_client_method(), Data::Empty) ;
00100    mServerCtx = mSecurity->createDomainCtx(DTLSv1_server_method(), sipDomain) ;
00101    assert( mClientCtx ) ;
00102    assert( mServerCtx ) ;
00103 
00104    mDummyBio = BIO_new( BIO_s_mem() ) ;
00105    assert( mDummyBio ) ;
00106 
00107    mSendData = NULL ;
00108 
00109    /* DTLS: partial reads end up discarding unread UDP bytes :-(
00110     * Setting read ahead solves this problem.
00111     * Source of this comment is: apps/s_client.c from OpenSSL source
00112     */
00113    SSL_CTX_set_read_ahead(mClientCtx, 1);
00114    SSL_CTX_set_read_ahead(mServerCtx, 1);
00115 
00116    /* trying to read from this BIO always returns retry */
00117    BIO_set_mem_eof_return( mDummyBio, -1 ) ;
00118 }
00119 
00120 DtlsTransport::~DtlsTransport()
00121 {
00122    DebugLog (<< "Shutting down " << mTuple);
00123 
00124    while(mDtlsConnections.begin() != mDtlsConnections.end())
00125    {
00126        _cleanupConnectionState(mDtlsConnections.begin()->second, mDtlsConnections.begin()->first);
00127    }
00128    SSL_CTX_free(mClientCtx);mClientCtx=0;
00129    SSL_CTX_free(mServerCtx);mServerCtx=0;
00130 
00131    BIO_free( mDummyBio) ;
00132 }
00133 
00134 void
00135 DtlsTransport::_read( FdSet& fdset )
00136 {
00137    //should this buffer be allocated on the stack and then copied out, as it
00138    //needs to be deleted every time EWOULDBLOCK is encountered
00139    // .dlb. can we determine the size of the buffer before we allocate?
00140    // something about MSG_PEEK|MSG_TRUNC in Stevens..
00141    // .dlb. RFC3261 18.1.1 MUST accept 65K datagrams. would have to attempt to
00142    // adjust the UDP buffer as well...
00143    unsigned int bufferLen = UdpTransport::MaxBufferSize + 5 ;
00144    char* buffer = new char[ bufferLen ] ;
00145    unsigned char *pt = new unsigned char[ bufferLen ] ;
00146 
00147    SSL *ssl ;
00148    BIO *rbio ;
00149    BIO *wbio ;
00150 
00151    // !jf! how do we tell if it discarded bytes
00152    // !ah! we use the len-1 trick :-(
00153    Tuple tuple(mTuple) ;
00154    socklen_t slen = tuple.length() ;
00155    int len = recvfrom( mFd,
00156                        buffer,
00157                        UdpTransport::MaxBufferSize,
00158                        0 /*flags */,
00159                        &tuple.getMutableSockaddr(),
00160                        &slen ) ;
00161    if ( len == SOCKET_ERROR )
00162    {
00163       int err = getErrno() ;
00164       if ( err != EWOULDBLOCK  )
00165       {
00166          error( err ) ;
00167       }
00168    }
00169 
00170    if (len == 0 || len == SOCKET_ERROR)
00171    {
00172       delete [] buffer ;
00173       buffer = 0 ;
00174       return ;
00175    }
00176 
00177    if ( len + 1 >= UdpTransport::MaxBufferSize )
00178    {
00179       InfoLog (<<"Datagram exceeded max length "<<UdpTransport::MaxBufferSize ) ;
00180       delete [] buffer ; buffer = 0 ;
00181       return ;
00182    }
00183 
00184    //DebugLog ( << "UDP Rcv : " << len << " b" );
00185    //DebugLog ( << Data(buffer, len).escaped().c_str());
00186 
00187    /* begin SSL stuff */
00188    struct sockaddr peer = tuple.getMutableSockaddr() ;
00189 
00190    ssl = mDtlsConnections[ *((struct sockaddr_in *)&peer) ] ;
00191 
00192    /*
00193     * If we don't have a binding for this peer,
00194     * then we're a server.
00195     */
00196    if ( ssl == NULL )
00197    {
00198       ssl = SSL_new( mServerCtx ) ;
00199       assert( ssl ) ;
00200 
00201       // clear SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE set in SSL_CTX if we are a server
00202       SSL_set_verify(ssl, 0, 0);
00203 
00204       InfoLog( << "DTLS handshake starting (Server mode)" );
00205 
00206       SSL_set_accept_state( ssl ) ;
00207 
00208       wbio = BIO_new_dgram( (int)mFd, BIO_NOCLOSE ) ;
00209       assert( wbio ) ;
00210 
00211       BIO_dgram_set_peer( wbio, &peer ) ;
00212 
00213       SSL_set_bio( ssl, NULL, wbio ) ;
00214 
00215       /* remember this connection */
00216       mDtlsConnections[ *((struct sockaddr_in *)&peer) ] = ssl ;
00217    }
00218 
00219    rbio = BIO_new_mem_buf( buffer, len ) ;
00220    BIO_set_mem_eof_return( rbio, -1 ) ;
00221 
00222    ssl->rbio = rbio ;
00223 
00224    len = SSL_read( ssl, pt, UdpTransport::MaxBufferSize ) ;
00225    int err = SSL_get_error( ssl, len ) ;
00226 
00227    /* done with the rbio */
00228    BIO_free( ssl->rbio ) ;
00229    ssl->rbio = mDummyBio ;
00230    delete [] buffer ;
00231    buffer = 0 ;
00232 
00233    if ( len <= 0 )
00234    {
00235       char errorString[1024];
00236 
00237       switch( err )
00238       {
00239          case SSL_ERROR_NONE:
00240             break ;
00241          case SSL_ERROR_SSL:
00242             {
00243                ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
00244                DebugLog( << "Got DTLS read condition SSL_ERROR_SSL on"
00245                          << " addr = " << inet_ntoa(((struct sockaddr_in *)&peer)->sin_addr)
00246                          << " port = " << ntohs(((struct sockaddr_in *)&peer)->sin_port)
00247                          << " error = " << errorString );
00248             }
00249             break ;
00250          case SSL_ERROR_WANT_READ:
00251             break ;
00252          case SSL_ERROR_WANT_WRITE:
00253             break ;
00254          case SSL_ERROR_SYSCALL:
00255             {
00256                ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
00257                DebugLog( << "Got DTLS read condition SSL_ERROR_SYSCALL on"
00258                          << " addr = " << inet_ntoa(((struct sockaddr_in *)&peer)->sin_addr)
00259                          << " port = " << ntohs(((struct sockaddr_in *)&peer)->sin_port)
00260                          << " error = " << errorString );
00261             }
00262             break ;
00263             /* connection closed */
00264          case SSL_ERROR_ZERO_RETURN:
00265             {
00266                ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
00267                DebugLog( << "Got DTLS read condition SSL_ERROR_ZERO_RETURN on"
00268                          << " addr = " << inet_ntoa(((struct sockaddr_in *)&peer)->sin_addr)
00269                          << " port = " << ntohs(((struct sockaddr_in *)&peer)->sin_port)
00270                          << " error = " << errorString );
00271 
00272                _cleanupConnectionState( ssl, *((struct sockaddr_in *)&peer) ) ;
00273             }
00274             break ;
00275          case SSL_ERROR_WANT_CONNECT:
00276             break ;
00277          case SSL_ERROR_WANT_ACCEPT:
00278             break ;
00279          default:
00280             break ;
00281       }
00282    }
00283 
00284    if ( len <= 0 )
00285        return ;
00286 
00287    if ( SSL_in_init( ssl ) )
00288       mTimer.add( ssl, DtlsReceiveTimeout ) ;
00289 
00290 #ifdef USE_SIGCOMP
00291    osc::StateChanges *sc = 0;
00292 #endif
00293 
00294    if ((pt[0] & 0xf8) == 0xf8)
00295    {
00296       if(!mCompression.isEnabled())
00297       {
00298         InfoLog(<< "Discarding unexpected SigComp message");
00299         delete [] pt;
00300         return;
00301       }
00302 #ifdef USE_SIGCOMP
00303       unsigned char *newPt = new unsigned char[ bufferLen ] ;
00304       size_t uncompressedLength =
00305         mSigcompStack->uncompressMessage(pt, len,
00306                                          newPt, UdpTransport::MaxBufferSize,
00307                                          sc);
00308 
00309       DebugLog (<< "Unompressed message from "
00310                 << len << " bytes to "
00311                 << uncompressedLength << " bytes");
00312 
00313       osc::SigcompMessage *nack = mSigcompStack->getNack();
00314 
00315       if (nack)
00316       {
00317         mTxFifo.add(new SendData(tuple,
00318                                  Data(nack->getDatagramMessage(),
00319                                       nack->getDatagramLength()),
00320                                  Data::Empty,
00321                                  Data::Empty,
00322                                  true)
00323                    );
00324         delete nack;
00325       }
00326 
00327       delete[] buffer;
00328       buffer = newBuffer;
00329       len = uncompressedLength;
00330 #endif
00331    }
00332 
00333    SipMessage* message = new SipMessage(this);
00334 
00335    // set the received from information into the received= parameter in the
00336    // via
00337 
00338    // It is presumed that UDP Datagrams are arriving atomically and that
00339    // each one is a unique SIP message
00340 
00341    // Save all the info where this message came from
00342    tuple.transport = this ;
00343    message->setSource( tuple ) ;
00344    //DebugLog (<< "Received from: " << tuple);
00345 
00346    // Tell the SipMessage about this datagram buffer.
00347    message->addBuffer( (char *)pt ) ;
00348 
00349    mMsgHeaderScanner.prepareForMessage( message ) ;
00350 
00351    char *unprocessedCharPtr ;
00352    if (mMsgHeaderScanner.scanChunk( (char *)pt,
00353                                     len,
00354                                     &unprocessedCharPtr ) !=
00355        MsgHeaderScanner::scrEnd)
00356    {
00357       DebugLog( << "Scanner rejecting datagram as unparsable / fragmented from "
00358                 << tuple ) ;
00359       DebugLog( << Data( pt, len ) ) ;
00360       delete message ;
00361       message = 0 ;
00362       return ;
00363    }
00364 
00365    // no pp error
00366    int used = int(unprocessedCharPtr - (char *)pt);
00367 
00368    if ( used < len )
00369    {
00370       // body is present .. add it up.
00371       // NB. The Sip Message uses an overlay (again)
00372       // for the body. It ALSO expects that the body
00373       // will be contiguous (of course).
00374       // it doesn't need a new buffer in UDP b/c there
00375       // will only be one datagram per buffer. (1:1 strict)
00376 
00377       message->setBody( (char *)pt + used, len - used ) ;
00378       //DebugLog(<<"added " << len-used << " byte body");
00379    }
00380 
00381    if ( ! basicCheck( *message ) )
00382    {
00383       delete message ; // cannot use it, so, punt on it...
00384       // basicCheck queued any response required
00385       message = 0 ;
00386       return ;
00387    }
00388 
00389    stampReceived( message) ;
00390 
00391 #ifdef USE_SIGCOMP
00392       if (mCompression.isEnabled() && sc)
00393       {
00394         const Via &via = message->header(h_Vias).front();
00395         if (message->isRequest())
00396         {
00397           // For requests, the compartment ID is read out of the
00398           // top via header field; if not present, we use the
00399           // TCP connection for identification purposes.
00400           if (via.exists(p_sigcompId))
00401           {
00402             Data compId = via.param(p_sigcompId);
00403             mSigcompStack->provideCompartmentId(
00404                              sc, compId.data(), compId.size());
00405           }
00406           else
00407           {
00408             mSigcompStack->provideCompartmentId(sc, this, sizeof(this));
00409           }
00410         }
00411         else
00412         {
00413           // For responses, the compartment ID is supposed to be
00414           // the same as the compartment ID of the request. We
00415           // *could* dig down into the transaction layer to try to
00416           // figure this out, but that's a royal pain, and a rather
00417           // severe layer violation. In practice, we're going to ferret
00418           // the ID out of the the Via header field, which is where we
00419           // squirreled it away when we sent this request in the first place.
00420           Data compId = via.param(p_branch).getSigcompCompartment();
00421           mSigcompStack->provideCompartmentId(sc, compId.data(), compId.size());
00422         }
00423 
00424       }
00425 #endif
00426 
00427    mStateMachineFifo.add( message ) ;
00428 }
00429 
00430 void DtlsTransport::_write( FdSet& fdset )
00431 {
00432    SSL *ssl ;
00433    BIO *wBio ;
00434    int retry = 0 ;
00435 
00436    SendData *sendData ;
00437    if ( mSendData != NULL )
00438        sendData = mSendData ;
00439    else
00440        sendData = mTxFifo.getNext() ;
00441 
00442    //DebugLog (<< "Sent: " <<  sendData->data);
00443    //DebugLog (<< "Sending message on udp.");
00444 
00445    assert( &(*sendData) );
00446    assert( sendData->destination.getPort() != 0 );
00447 
00448    sockaddr peer = sendData->destination.getSockaddr();
00449 
00450    ssl = mDtlsConnections[ *((struct sockaddr_in *)&peer) ] ;
00451 
00452    /* If we don't have a binding, then we're a client */
00453    if ( ssl == NULL )
00454    {
00455       ssl = SSL_new( mClientCtx ) ;
00456       assert( ssl ) ;
00457 
00458 
00459       InfoLog( << "DTLS handshake starting (client mode)" );
00460 
00461       SSL_set_connect_state( ssl ) ;
00462 
00463       wBio = BIO_new_dgram( (int)mFd, BIO_NOCLOSE ) ;
00464       assert( wBio ) ;
00465 
00466       BIO_dgram_set_peer( wBio, &peer) ;
00467 
00468       /* the real rbio will be set by _read */
00469       SSL_set_bio( ssl, mDummyBio, wBio ) ;
00470 
00471       /* we should be ready to take this out if the
00472        * connection fails later */
00473       mDtlsConnections [ *((struct sockaddr_in *)&peer) ] = ssl ;
00474    }
00475 
00476    int expected;
00477    int count;
00478 
00479 #ifdef USE_SIGCOMP
00480    // If message needs to be compressed, compress it here.
00481    if (mSigcompStack &&
00482        sendData->sigcompId.size() > 0 &&
00483        !sendData->isAlreadyCompressed )
00484    {
00485        osc::SigcompMessage *sm = mSigcompStack->compressMessage
00486          (sendData->data.data(), sendData->data.size(),
00487           sendData->sigcompId.data(), sendData->sigcompId.size(),
00488           isReliable());
00489 
00490        DebugLog (<< "Compressed message from "
00491                  << sendData->data.size() << " bytes to "
00492                  << sm->getDatagramLength() << " bytes");
00493 
00494        expected = sm->getDatagramLength();
00495 
00496        count = SSL_Write(ssl,
00497                          sm->getDatagramMessage(),
00498                          sm->getDatagramLength());
00499        delete sm;
00500    }
00501    else
00502 #endif
00503    {
00504       expected = (int)sendData->data.size();
00505 
00506       count = SSL_write(ssl, sendData->data.data(),
00507                         (int)sendData->data.size());
00508    }
00509 
00510    /*
00511     * all reads go through _read, so the most likely result during a handshake
00512     * will be SSL_ERROR_WANT_READ
00513     */
00514 
00515    if ( count <= 0 )
00516    {
00517       /* cache unqueued data */
00518       mSendData = sendData ;
00519 
00520       int err = SSL_get_error( ssl, count ) ;
00521 
00522       char errorString[1024];
00523 
00524       switch( err )
00525       {
00526          case SSL_ERROR_NONE:
00527             break;
00528          case SSL_ERROR_SSL:
00529             {
00530                ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
00531                DebugLog( << "Got DTLS write condition SSL_ERROR_SSL on "
00532                          << sendData->destination
00533                          << " error = " << errorString );
00534             }
00535             break;
00536          case SSL_ERROR_WANT_READ:
00537             retry = 1 ;
00538             break;
00539          case SSL_ERROR_WANT_WRITE:
00540              retry = 1 ;
00541              fdset.setWrite(mFd);
00542             break;
00543          case SSL_ERROR_SYSCALL:
00544             {
00545                int e = getErrno();
00546                error(e);
00547 
00548                ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
00549                DebugLog( << "Got DTLS write condition SSL_ERROR_SYSCALL "
00550                          << "Failed (" << e << ") sending to "
00551                          << sendData->destination
00552                          << " error = " << errorString );
00553 
00554                fail(sendData->transactionId);
00555             }
00556             break;
00557          case SSL_ERROR_ZERO_RETURN:
00558             {
00559                ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
00560                DebugLog( << "Got DTLS write condition SSL_ERROR_ZERO_RETURN on "
00561                          << sendData->destination
00562                          << " error = " << errorString );
00563 
00564                _cleanupConnectionState( ssl, *((struct sockaddr_in *)&peer) ) ;
00565             }
00566             break ;
00567          case SSL_ERROR_WANT_CONNECT:
00568             break;
00569          case SSL_ERROR_WANT_ACCEPT:
00570             break;
00571          default:
00572             break ;
00573       }
00574    }
00575    else
00576    {
00577       mSendData = NULL ;
00578    }
00579 
00580    /*
00581     * ngm: is sendData deleted by a higher layer?  Seems to be the case after
00582     * checking with UdpTransport
00583     */
00584 
00585    if ( ! retry && count != int(sendData->data.size()) )
00586    {
00587       ErrLog (<< "UDPTransport - send buffer full" );
00588       fail(sendData->transactionId);
00589    }
00590 }
00591 
00592 void
00593 DtlsTransport::_doHandshake( void )
00594 {
00595    DtlsMessage *msg = mHandshakePending.getNext() ;
00596    SSL *ssl = msg->getSsl() ;
00597 
00598    delete msg ;
00599 
00600    ERR_clear_error();
00601 
00602    int ret = SSL_do_handshake( ssl ) ;
00603 
00604    if (ret <= 0) {
00605       int err = SSL_get_error(ssl, ret);
00606 
00607       char errorString[1024];
00608 
00609       switch (err)
00610       {
00611          case SSL_ERROR_NONE:
00612             break;
00613          case SSL_ERROR_SSL:
00614             {
00615                ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
00616                DebugLog( << "Got DTLS handshake code SSL_ERROR_SSL"
00617                          << " error = " << errorString );
00618             }
00619             break;
00620          case SSL_ERROR_WANT_READ:
00621             break;
00622          case SSL_ERROR_WANT_WRITE:
00623             break;
00624          case SSL_ERROR_SYSCALL:
00625             {
00626                ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
00627                DebugLog( << "Got DTLS handshake code SSL_ERROR_SYSCALL"
00628                          << " error = " << errorString );
00629             }
00630             break;
00631          case SSL_ERROR_ZERO_RETURN:
00632             {
00633                ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
00634                DebugLog( << "Got DTLS handshake code SSL_ERROR_ZERO_RETURN"
00635                          << " error = " << errorString );
00636             }
00637             break;
00638          case SSL_ERROR_WANT_CONNECT:
00639             break;
00640          case SSL_ERROR_WANT_ACCEPT:
00641             break;
00642          default:
00643             break ;
00644       }
00645    }
00646 }
00647 
00648 void
00649 DtlsTransport::process(FdSet& fdset)
00650 {
00651    // pull buffers to send out of TxFifo
00652    // receive datagrams from fd
00653    // preparse and stuff into RxFifo
00654 
00655    mTimer.process() ;
00656 
00657    while ( mHandshakePending.messageAvailable() )
00658       _doHandshake() ;
00659 
00660    if ( ( mSendData != NULL || mTxFifo.messageAvailable() )
00661        && fdset.readyToWrite( mFd ) )
00662       _write( fdset ) ;
00663 
00664    // !jf! this may have to change - when we read a message that is too big
00665    if ( fdset.readyToRead(mFd) )
00666       _read( fdset ) ;
00667 }
00668 
00669 
00670 void
00671 DtlsTransport::buildFdSet( FdSet& fdset )
00672 {
00673    fdset.setRead(mFd);
00674 
00675    if ( mSendData != NULL || mTxFifo.messageAvailable() )
00676    {
00677      fdset.setWrite(mFd);
00678    }
00679 }
00680 
00681 void
00682 DtlsTransport::_cleanupConnectionState( SSL *ssl, struct sockaddr_in peer )
00683 {
00684    /*
00685     * SSL_free decrements the ref-count for mDummyBio by 1, so
00686     * add 1 to the ref-count to make sure it does not get free'd
00687     */
00688    CRYPTO_add(&mDummyBio->references, 1, CRYPTO_LOCK_BIO);
00689    SSL_shutdown(ssl);
00690    SSL_free(ssl) ;
00691    mDtlsConnections.erase(peer) ;
00692 }
00693 
00694 void
00695 DtlsTransport::_mapDebug( const char *where, const char *action, SSL *ssl )
00696 {
00697    fprintf( stderr, "%s: %s\t%p\n", where, action, ssl ) ;
00698    fprintf( stderr, "map sizet = %d\n", mDtlsConnections.size() ) ;
00699 }
00700 
00701 void
00702 DtlsTransport::_printSock( const struct sockaddr_in *sock )
00703 {
00704    fprintf( stderr, "addr = %s\t port = %d\n", inet_ntoa( sock->sin_addr ),
00705             ntohs( sock->sin_port ) ) ;
00706 }
00707 
00708 #endif /* USE_DTLS */
00709 #endif /* USE_SSL */
00710 
00711 /* ====================================================================
00712  * The Vovida Software License, Version 1.0
00713  *
00714  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00715  *
00716  * Redistribution and use in source and binary forms, with or without
00717  * modification, are permitted provided that the following conditions
00718  * are met:
00719  *
00720  * 1. Redistributions of source code must retain the above copyright
00721  *    notice, this list of conditions and the following disclaimer.
00722  *
00723  * 2. Redistributions in binary form must reproduce the above copyright
00724  *    notice, this list of conditions and the following disclaimer in
00725  *    the documentation and/or other materials provided with the
00726  *    distribution.
00727  *
00728  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00729  *    and "Vovida Open Communication Application Library (VOCAL)" must
00730  *    not be used to endorse or promote products derived from this
00731  *    software without prior written permission. For written
00732  *    permission, please contact vocal@vovida.org.
00733  *
00734  * 4. Products derived from this software may not be called "VOCAL", nor
00735  *    may "VOCAL" appear in their name, without prior written
00736  *    permission of Vovida Networks, Inc.
00737  *
00738  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00739  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00740  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00741  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00742  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00743  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00744  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00745  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00746  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00747  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00748  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00749  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00750  * DAMAGE.
00751  *
00752  * ====================================================================
00753  *
00754  * This software consists of voluntary contributions made by Vovida
00755  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00756  * Inc.  For more information on Vovida Networks, Inc., please see
00757  * <http://www.vovida.org/>.
00758  *
00759  */