/* * Copyright (C) 2007-2012 Dmytro Bogovych * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef _WIN32 # include # include #endif #include #include "EP_ReliableTunnel.h" #include "EP_Engine.h" #include "Log.h" #include "../ICE/ICECRC32.h" enum { CONFIRMATION_PT = 1, DATA_PT = 2 }; #define CONFIRMATION_TIMEOUT 500 #define LOG_SUBSYSTEM "RT" ReliableTunnel::ReliableTunnel(const char* streamname) { mStack.setEncryption(this); mStreamName = streamname; mBandwidth = 0; mExitSignal = ::CreateEvent(NULL, FALSE, FALSE, NULL); mDataSignal = ::CreateEvent(NULL, FALSE, FALSE, NULL); } ReliableTunnel::~ReliableTunnel() { ::CloseHandle(mDataSignal); ::CloseHandle(mExitSignal); } std::string ReliableTunnel::streamName() { return mStreamName; } std::string ReliableTunnel::streamProfile() { return "RTP/DP"; } void ReliableTunnel::setDestinationAddress(InternetAddress& addr) { mDestination = addr; } void ReliableTunnel::queueData(const void* bufferptr, int buffersize) { assert(bufferptr != NULL); assert(buffersize != 0); resip::Lock l(mNewQueuedGuard); mNewQueued.push_back(std::string((const char*)bufferptr, buffersize)); ::SetEvent(mDataSignal); } // This method is called by user agent to send ICE packet from mediasocket void ReliableTunnel::sendData(InternetAddress& addr, const void* dataBuffer, unsigned int datasize) { switch (addr.type()) { case AF_INET: mSocket4.sendDatagram(addr, dataBuffer, datasize); return; case AF_INET6: mSocket4.sendDatagram(addr, dataBuffer, datasize); return; } } void ReliableTunnel::sessionEstablished(int conntype) { // Start worker thread if (conntype == EV_ICE) run(); } void ReliableTunnel::sessionTerminated() { // Stop worker thread ::SetEvent(mExitSignal); shutdown(); join(); } void ReliableTunnel::updateSdpOffer(resip::SdpContents::Session::Medium& sdp) { // Get new destination port mDestination.setPort((unsigned short)sdp.port()); sdp.addCodec(resip::SdpContents::Session::Codec("rt", 104)); } void ReliableTunnel::setSocket(DatagramSocket& socket4, DatagramSocket& socket6) { mSocket4 = socket4; mSocket6 = socket6; } DatagramSocket& ReliableTunnel::socket(int family) { switch (family) { case AF_INET: return mSocket4; case AF_INET6: return mSocket4; default: assert(0); } } bool ReliableTunnel::processSdpOffer(const resip::SdpContents::Session::Medium& media) { //check for default port number mDestination.setPort(media.port()); return true; } void ReliableTunnel::thread() { // Construct event array while (true) { HANDLE eventarray[2] = { mDataSignal, mExitSignal }; DWORD rescode = ::WaitForMultipleObjects(2, eventarray, FALSE, INFINITE); if (rescode == WAIT_OBJECT_0) { resip::Lock l(mNewQueuedGuard); for (unsigned i = 0; imDestination, buffer, length); } } void ReliableTunnel::setEncryptionKey(void* ptr, unsigned length) { #ifdef USE_OPENSSL BF_set_key(&mCipher, length, (const unsigned char*)ptr); #endif #ifdef USE_CRYPTOPP mEncryptor.SetKey((unsigned char*)ptr, length); mDecryptor.SetKey((unsigned char*)ptr, length); #endif // Save key mEncryptionKey = std::string((const char*)ptr, length); }