From 0bce8eed98acce2532bbbf9878fc4a477735a33e Mon Sep 17 00:00:00 2001 From: Gerald Begumisa Date: Thu, 23 Oct 2008 21:02:24 +0000 Subject: Modified VoIp capture plugin so that if any of the network devices being captured from go offline, orkaudio does not simply stop but attempts to re-open the device. In such a case, orkaudio attempts to re-open the device after 60 seconds from when the device went offline. If it fails to re-open i.e is still offline, orkaudio shall keep trying every 60 seconds. git-svn-id: https://oreka.svn.sourceforge.net/svnroot/oreka/trunk@564 09dcff7a-b715-0410-9601-b79a96267cd0 --- orkaudio/audiocaptureplugins/voip/VoIp.cpp | 128 ++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 1 deletion(-) (limited to 'orkaudio/audiocaptureplugins/voip') diff --git a/orkaudio/audiocaptureplugins/voip/VoIp.cpp b/orkaudio/audiocaptureplugins/voip/VoIp.cpp index 37a2f84..7731743 100644 --- a/orkaudio/audiocaptureplugins/voip/VoIp.cpp +++ b/orkaudio/audiocaptureplugins/voip/VoIp.cpp @@ -86,6 +86,10 @@ public: void StartCapture(CStdString& port); void StopCapture(CStdString& port); void ReportPcapStats(); + pcap_t* OpenDevice(CStdString& name); + void AddPcapDeviceToMap(CStdString& deviceName, pcap_t* pcapHandle); + void RemovePcapDeviceFromMap(pcap_t* pcapHandle); + CStdString GetPcapDeviceName(pcap_t* pcapHandle); private: void OpenDevices(); void OpenPcapFile(CStdString& filename); @@ -95,6 +99,9 @@ private: pcap_t* m_pcapHandle; std::list m_pcapHandles; + + std::map m_pcapDeviceMap; + ACE_Thread_Mutex m_pcapDeviceMapMutex; }; typedef ACE_Singleton VoIpSingleton; @@ -2695,6 +2702,56 @@ void SingleDeviceCaptureThreadHandler(pcap_t* pcapHandle) } log.Format("Stop Capturing: pcap handle:%x", pcapHandle); LOG4CXX_INFO(s_packetLog, log); + + if(s_liveCapture == true) + { + CStdString deviceName; + pcap_t* oldHandle = NULL; + + deviceName = VoIpSingleton::instance()->GetPcapDeviceName(pcapHandle); + if(deviceName.size()) + { + oldHandle = pcapHandle; + VoIpSingleton::instance()->RemovePcapDeviceFromMap(pcapHandle); + pcap_close(pcapHandle); // XXX this can cause a crash if later other code is added to close all handles in the m_pcapHandles list + + while(1) + { + struct timespec ts; + + ts.tv_sec = 60; // Try re-open after a minute + ts.tv_nsec = 0; + ACE_OS::nanosleep (&ts, NULL); + + log.Format("Attempting to re-open device:%s - old handle:%x was closed", deviceName, oldHandle); + LOG4CXX_INFO(s_packetLog, log); + + pcapHandle = VoIpSingleton::instance()->OpenDevice(deviceName); + if(pcapHandle != NULL) + { + VoIpSingleton::instance()->AddPcapDeviceToMap(deviceName, pcapHandle); + + log.Format("Start Capturing: pcap handle:%x", pcapHandle); + LOG4CXX_INFO(s_packetLog, log); + + pcap_loop(pcapHandle, 0, HandlePacket, NULL); + + log.Format("Stop Capturing: pcap handle:%x", pcapHandle); + LOG4CXX_INFO(s_packetLog, log); + + oldHandle = pcapHandle; + VoIpSingleton::instance()->RemovePcapDeviceFromMap(pcapHandle); + pcap_close(pcapHandle); + } + } + } + else + { + log.Format("Running in live capture mode but unable to determine which device handle:%x belongs to. Will not restart capture", pcapHandle); + LOG4CXX_INFO(s_packetLog, log); + pcap_close(pcapHandle); // XXX this can cause a crash if later other code is added to close all handles in the m_pcapHandles list + } + } } else { @@ -2855,6 +2912,68 @@ void VoIp::SetPcapSocketBufferSize(pcap_t* pcapHandle) #endif } +void VoIp::AddPcapDeviceToMap(CStdString& deviceName, pcap_t* pcapHandle) +{ + MutexSentinel mutexSentinel(m_pcapDeviceMapMutex); + + m_pcapDeviceMap.insert(std::make_pair(pcapHandle, deviceName)); +} + +void VoIp::RemovePcapDeviceFromMap(pcap_t* pcapHandle) +{ + MutexSentinel mutexSentinel(m_pcapDeviceMapMutex); + + m_pcapDeviceMap.erase(pcapHandle); +} + +CStdString VoIp::GetPcapDeviceName(pcap_t* pcapHandle) +{ + MutexSentinel mutexSentinel(m_pcapDeviceMapMutex); + std::map::iterator pair; + CStdString deviceName; + + pair = m_pcapDeviceMap.find(pcapHandle); + if(pair != m_pcapDeviceMap.end()) + { + deviceName = pair->second; + } + + return deviceName; +} + +pcap_t* VoIp::OpenDevice(CStdString& name) +{ + char error[PCAP_ERRBUF_SIZE]; + char *perror = NULL; + MutexSentinel mutexSentinel(m_pcapDeviceMapMutex); + CStdString logMsg; + + m_pcapHandle = NULL; + memset(error, 0, sizeof(error)); + m_pcapHandle = pcap_open_live((char*)name.c_str(), 1500, PROMISCUOUS, 500, error); + + if(!strlen(error)) + { + perror = ApplyPcapFilter(); + if(perror != NULL) + { + snprintf(error, PCAP_ERRBUF_SIZE, "%s", perror); + } + } + if(strlen(error)) + { + LOG4CXX_ERROR(s_packetLog, CStdString("pcap error when opening device; error message:") + error); + } + else + { + logMsg.Format("Successfully opened device. pcap handle:%x", m_pcapHandle); + LOG4CXX_INFO(s_packetLog, logMsg); + SetPcapSocketBufferSize(m_pcapHandle); + } + + return m_pcapHandle; +} + void VoIp::OpenDevices() { pcap_if_t* devices = NULL; @@ -2910,12 +3029,15 @@ void VoIp::OpenDevices() } else { - CStdString logMsg; + CStdString logMsg, deviceName; + + deviceName = device->name; logMsg.Format("Successfully opened device. pcap handle:%x", m_pcapHandle); LOG4CXX_INFO(s_packetLog, logMsg); SetPcapSocketBufferSize(m_pcapHandle); m_pcapHandles.push_back(m_pcapHandle); + AddPcapDeviceToMap(deviceName, m_pcapHandle); } } } @@ -2942,11 +3064,15 @@ void VoIp::OpenDevices() } else { + CStdString deviceName; + logMsg.Format("Successfully opened default device:%s pcap handle:%x", defaultDevice->name, m_pcapHandle); LOG4CXX_INFO(s_packetLog, logMsg); SetPcapSocketBufferSize(m_pcapHandle); m_pcapHandles.push_back(m_pcapHandle); + deviceName = defaultDevice->name; + AddPcapDeviceToMap(deviceName, m_pcapHandle); } } else -- cgit v1.2.3