/* * Retrieves the address information (hostname, port number) for the * specified Maya command port name. If the port name contains a * colon (':') character, it is interpreted as "<hostname>:<port>". * Otherwise, it is assumed to specify a Maya Unix socket path. * * Returns true if successful, or false otherwise. If this function * returns true, the caller is responsible for freeing the address * information that is dynamically allocated, using freeaddrinfo(). */ bool GetMayaCommandPortAddress(LPCSTR pszName, ADDRINFO** ppAddrInfo) { CAtlStringA strName(pszName); CAtlStringA strHost("localhost"); CAtlStringA strPath; CAtlStringA strPort; int nFindPos = strName.Find(':'); if (nFindPos >= 0) { // split port name into hostname and port if (nFindPos > 0) { strHost = strName.Left(nFindPos); } strPort = strName.Mid(nFindPos + 1); if (strPort.IsEmpty()) return false; if (getaddrinfo(strHost, strPort, NULL, ppAddrInfo) == 0) return true; strPath = strPort; } else { strPath = pszName; } // get port number for unix socket path UINT16 nPort; if (!GetPortForMayaUnixSocketPath(strPath, &nPort)) return false; strPort.Format("%u", nPort); return (getaddrinfo(strHost, strPort, NULL, ppAddrInfo) == 0); }
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup) { std::string strHost(pszName); if (strHost.empty()) return false; if (boost::algorithm::starts_with(strHost, "[") && boost::algorithm::ends_with(strHost, "]")) { strHost = strHost.substr(1, strHost.size() - 2); } return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup); }
BOOL CNetwork::Resolve(LPCTSTR pszHost, int nPort, SOCKADDR_IN* pHost, BOOL bNames) const { ZeroMemory( pHost, sizeof(*pHost) ); pHost->sin_family = PF_INET; pHost->sin_port = htons( nPort ); if ( pszHost == NULL || *pszHost == 0 ) return FALSE; CString strHost( pszHost ); int nColon = strHost.Find( ':' ); if ( nColon >= 0 ) { if ( _stscanf( strHost.Mid( nColon + 1 ), _T("%i"), &nPort ) == 1 ) { pHost->sin_port = htons( nPort ); } strHost = strHost.Left( nColon ); } USES_CONVERSION; LPCSTR pszaHost = T2CA( (LPCTSTR)strHost ); DWORD dwIP = inet_addr( pszaHost ); if ( dwIP == INADDR_NONE ) { if ( ! bNames ) return TRUE; HOSTENT* pLookup = gethostbyname( pszaHost ); if ( pLookup == NULL ) return FALSE; CopyMemory( &pHost->sin_addr, pLookup->h_addr, 4 ); } else { CopyMemory( &pHost->sin_addr, &dwIP, 4 ); } return TRUE; }
void *deviceThread::Entry() { // Must have a valid pointer to the device item if (NULL == m_pDeviceItem) return NULL; // Must have a valid pointer to the control object if (NULL == m_pCtrlObject) return NULL; // We need to create a clientobject and add this object to the list m_pDeviceItem->m_pClientItem = new CClientItem; if (NULL == m_pDeviceItem->m_pClientItem) { return NULL; } // This is now an active Client m_pDeviceItem->m_pClientItem->m_bOpen = true; if ( VSCP_DRIVER_LEVEL2 == m_pDeviceItem->m_driverLevel ) { m_pDeviceItem->m_pClientItem->m_type = CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL2; } else { m_pDeviceItem->m_pClientItem->m_type = CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL1; } m_pDeviceItem->m_pClientItem->m_strDeviceName = m_pDeviceItem->m_strName; m_pDeviceItem->m_pClientItem->m_strDeviceName += _(" Started at "); wxDateTime now = wxDateTime::Now(); m_pDeviceItem->m_pClientItem->m_strDeviceName += now.FormatISODate(); m_pDeviceItem->m_pClientItem->m_strDeviceName += _(" "); m_pDeviceItem->m_pClientItem->m_strDeviceName += now.FormatISOTime(); m_pCtrlObject->logMsg(m_pDeviceItem->m_pClientItem->m_strDeviceName + _("\n"), DAEMON_LOGMSG_DEBUG); // Add the client to the Client List m_pCtrlObject->m_wxClientMutex.Lock(); m_pCtrlObject->addClient(m_pDeviceItem->m_pClientItem); m_pCtrlObject->m_wxClientMutex.Unlock(); // Load dynamic library if (!m_wxdll.Load(m_pDeviceItem->m_strPath, wxDL_LAZY)) { m_pCtrlObject->logMsg(_("Unable to load dynamic library.\n") ); return NULL; } if (VSCP_DRIVER_LEVEL1 == m_pDeviceItem->m_driverLevel) { // Now find methods in library { wxString str; str = _("Loading level I driver: "); str += m_pDeviceItem->m_strName; str += _("\n"); m_pCtrlObject->logMsg(str); wxLogDebug(str); } // * * * * CANAL OPEN * * * * if (NULL == (m_pDeviceItem->m_proc_CanalOpen = (LPFNDLL_CANALOPEN) m_wxdll.GetSymbol(_T("CanalOpen")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalOpen.\n") ); return NULL; } // * * * * CANAL CLOSE * * * * if (NULL == (m_pDeviceItem->m_proc_CanalClose = (LPFNDLL_CANALCLOSE) m_wxdll.GetSymbol(_T("CanalClose")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalClose.\n") ); return NULL; } // * * * * CANAL GETLEVEL * * * * if (NULL == (m_pDeviceItem->m_proc_CanalGetLevel = (LPFNDLL_CANALGETLEVEL) m_wxdll.GetSymbol(_T("CanalGetLevel")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetLevel.\n") ); return NULL; } // * * * * CANAL SEND * * * * if (NULL == (m_pDeviceItem->m_proc_CanalSend = (LPFNDLL_CANALSEND) m_wxdll.GetSymbol(_T("CanalSend")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalSend.\n") ); return NULL; } // * * * * CANAL DATA AVAILABLE * * * * if (NULL == (m_pDeviceItem->m_proc_CanalDataAvailable = (LPFNDLL_CANALDATAAVAILABLE) m_wxdll.GetSymbol(_T("CanalDataAvailable")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalDataAvailable.\n") ); return NULL; } // * * * * CANAL RECEIVE * * * * if (NULL == (m_pDeviceItem->m_proc_CanalReceive = (LPFNDLL_CANALRECEIVE) m_wxdll.GetSymbol(_T("CanalReceive")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalReceive.\n") ); return NULL; } // * * * * CANAL GET STATUS * * * * if (NULL == (m_pDeviceItem->m_proc_CanalGetStatus = (LPFNDLL_CANALGETSTATUS) m_wxdll.GetSymbol(_T("CanalGetStatus")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetStatus.\n") ); return NULL; } // * * * * CANAL GET STATISTICS * * * * if (NULL == (m_pDeviceItem->m_proc_CanalGetStatistics = (LPFNDLL_CANALGETSTATISTICS) m_wxdll.GetSymbol(_T("CanalGetStatistics")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetStatistics.\n") ); return NULL; } // * * * * CANAL SET FILTER * * * * if (NULL == (m_pDeviceItem->m_proc_CanalSetFilter = (LPFNDLL_CANALSETFILTER) m_wxdll.GetSymbol(_T("CanalSetFilter")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalSetFilter.\n") ); return NULL; } // * * * * CANAL SET MASK * * * * if (NULL == (m_pDeviceItem->m_proc_CanalSetMask = (LPFNDLL_CANALSETMASK) m_wxdll.GetSymbol(_T("CanalSetMask")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalSetMask.\n") ); return NULL; } // * * * * CANAL GET VERSION * * * * if (NULL == (m_pDeviceItem->m_proc_CanalGetVersion = (LPFNDLL_CANALGETVERSION) m_wxdll.GetSymbol(_T("CanalGetVersion")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetVersion.\n") ); return NULL; } // * * * * CANAL GET DLL VERSION * * * * if (NULL == (m_pDeviceItem->m_proc_CanalGetDllVersion = (LPFNDLL_CANALGETDLLVERSION) m_wxdll.GetSymbol(_T("CanalGetDllVersion")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetDllVersion.\n") ); return NULL; } // * * * * CANAL GET VENDOR STRING * * * * if (NULL == (m_pDeviceItem->m_proc_CanalGetVendorString = (LPFNDLL_CANALGETVENDORSTRING) m_wxdll.GetSymbol(_T("CanalGetVendorString")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetVendorString.\n") ); return NULL; } // ****************************** // Generation 2 Methods // ****************************** // * * * * CANAL BLOCKING SEND * * * * m_pDeviceItem->m_proc_CanalBlockingSend = NULL; if (m_wxdll.HasSymbol(_T("CanalBlockingSend"))) { if (NULL == (m_pDeviceItem->m_proc_CanalBlockingSend = (LPFNDLL_CANALBLOCKINGSEND) m_wxdll.GetSymbol(_T("CanalBlockingSend")))) { m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalBlockingSend. Probably Generation 1 driver.\n") ); m_pDeviceItem->m_proc_CanalBlockingSend = NULL; } } else { m_pCtrlObject->logMsg(_T("CanalBlockingSend not available. \n\tNon blocking operations set.\n") ); } // * * * * CANAL BLOCKING RECEIVE * * * * m_pDeviceItem->m_proc_CanalBlockingReceive = NULL; if (m_wxdll.HasSymbol(_T("CanalBlockingReceive"))) { if (NULL == (m_pDeviceItem->m_proc_CanalBlockingReceive = (LPFNDLL_CANALBLOCKINGRECEIVE) m_wxdll.GetSymbol(_T("CanalBlockingReceive")))) { m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalBlockingReceive. Probably Generation 1 driver.\n") ); m_pDeviceItem->m_proc_CanalBlockingReceive = NULL; } } else { m_pCtrlObject->logMsg(_T("CanalBlockingReceive not available. \n\tNon blocking operations set.\n")); } // * * * * CANAL GET DRIVER INFO * * * * m_pDeviceItem->m_proc_CanalGetdriverInfo = NULL; if (m_wxdll.HasSymbol(_T("CanalGetDriverInfo"))) { if (NULL == (m_pDeviceItem->m_proc_CanalGetdriverInfo = (LPFNDLL_CANALGETDRIVERINFO) m_wxdll.GetSymbol(_T("CanalGetDriverInfo")))) { m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetDriverInfo. Probably Generation 1 driver.\n") ); m_pDeviceItem->m_proc_CanalGetdriverInfo = NULL; } } // Open the device m_pDeviceItem->m_openHandle = m_pDeviceItem->m_proc_CanalOpen((const char *) m_pDeviceItem->m_strParameter.mb_str(wxConvUTF8), m_pDeviceItem->m_DeviceFlags); // Check if the driver opened properly if (m_pDeviceItem->m_openHandle <= 0) { wxString errMsg = _T("Failed to open driver. Will not use it! \n\t[ ") + m_pDeviceItem->m_strName + _T(" ]\n"); m_pCtrlObject->logMsg( errMsg ); return NULL; } else { wxString wxstr = wxString::Format(_("Driver %s opended.\n"), (const char *)m_pDeviceItem->m_strName.mbc_str() ); m_pCtrlObject->logMsg( wxstr ); } // Get Driver Level m_pDeviceItem->m_driverLevel = m_pDeviceItem->m_proc_CanalGetLevel(m_pDeviceItem->m_openHandle); // * * * Level I Driver * * * // Check if blocking driver is available if (NULL != m_pDeviceItem->m_proc_CanalBlockingReceive) { // * * * * Blocking version * * * * ///////////////////////////////////////////////////////////////////////////// // Device write worker thread ///////////////////////////////////////////////////////////////////////////// m_pwriteThread = new deviceCanalWriteThread; if (m_pwriteThread) { m_pwriteThread->m_pMainThreadObj = this; wxThreadError err; if (wxTHREAD_NO_ERROR == (err = m_pwriteThread->Create())) { m_pwriteThread->SetPriority(WXTHREAD_MAX_PRIORITY); if (wxTHREAD_NO_ERROR != (err = m_pwriteThread->Run())) { m_pCtrlObject->logMsg(_("Unable to run device write worker thread.\n") ); } } else { m_pCtrlObject->logMsg(_("Unable to create device write worker thread.\n") ); } } else { m_pCtrlObject->logMsg(_("Unable to allocate memory for device write worker thread.\n") ); } ///////////////////////////////////////////////////////////////////////////// // Device read worker thread ///////////////////////////////////////////////////////////////////////////// m_preceiveThread = new deviceCanalReceiveThread; if (m_preceiveThread) { m_preceiveThread->m_pMainThreadObj = this; wxThreadError err; if (wxTHREAD_NO_ERROR == (err = m_preceiveThread->Create())) { m_preceiveThread->SetPriority(WXTHREAD_MAX_PRIORITY); if (wxTHREAD_NO_ERROR != (err = m_preceiveThread->Run())) { m_pCtrlObject->logMsg(_("Unable to run device receive worker thread.\n") ); } } else { m_pCtrlObject->logMsg(_("Unable to create device receive worker thread.\n") ); } } else { m_pCtrlObject->logMsg(_("Unable to allocate memory for device receive worker thread.\n") ); } // Just sit and wait until the end of the world as we know it... while (!m_pDeviceItem->m_bQuit) { wxSleep(1); } m_preceiveThread->m_bQuit = true; m_pwriteThread->m_bQuit = true; m_preceiveThread->Wait(); m_pwriteThread->Wait(); } else { // * * * * Non blocking version * * * * bool bActivity; while (!TestDestroy() && !m_pDeviceItem->m_bQuit) { bActivity = false; ///////////////////////////////////////////////////////////////////////////// // Receive from device // ///////////////////////////////////////////////////////////////////////////// canalMsg msg; if (m_pDeviceItem->m_proc_CanalDataAvailable(m_pDeviceItem->m_openHandle)) { if (CANAL_ERROR_SUCCESS == m_pDeviceItem->m_proc_CanalReceive(m_pDeviceItem->m_openHandle, &msg)) { bActivity = true; // There must be room in the receive queue if (m_pCtrlObject->m_maxItemsInClientReceiveQueue > m_pCtrlObject->m_clientOutputQueue.GetCount()) { vscpEvent *pvscpEvent = new vscpEvent; if (NULL != pvscpEvent) { // Convert CANAL message to VSCP event vscp_convertCanalToEvent( pvscpEvent, &msg, m_pDeviceItem->m_pClientItem->m_guid.m_id ); pvscpEvent->obid = m_pDeviceItem->m_pClientItem->m_clientID; m_pCtrlObject->m_mutexClientOutputQueue.Lock(); m_pCtrlObject->m_clientOutputQueue.Append(pvscpEvent); m_pCtrlObject->m_semClientOutputQueue.Post(); m_pCtrlObject->m_mutexClientOutputQueue.Unlock(); } } } } // data available // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Send messages (if any) in the outqueue // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Check if there is something to send if (m_pDeviceItem->m_pClientItem->m_clientInputQueue.GetCount()) { bActivity = true; CLIENTEVENTLIST::compatibility_iterator nodeClient; m_pDeviceItem->m_pClientItem->m_mutexClientInputQueue.Lock(); nodeClient = m_pDeviceItem->m_pClientItem->m_clientInputQueue.GetFirst(); vscpEvent *pqueueEvent = nodeClient->GetData(); m_pDeviceItem->m_pClientItem->m_mutexClientInputQueue.Unlock(); canalMsg canalMsg; vscp_convertEventToCanal(&canalMsg, pqueueEvent); if (CANAL_ERROR_SUCCESS == m_pDeviceItem->m_proc_CanalSend(m_pDeviceItem->m_openHandle, &canalMsg)) { // Remove the node delete pqueueEvent; m_pDeviceItem->m_pClientItem->m_clientInputQueue.DeleteNode(nodeClient); } else { // Another try //m_pCtrlObject->m_semClientOutputQueue.Post(); vscp_deleteVSCPevent(pqueueEvent); m_pDeviceItem->m_pClientItem->m_clientInputQueue.DeleteNode(nodeClient); } } // events if (!bActivity) { ::wxMilliSleep(100); } bActivity = false; } // while working - non blocking } // if blocking/non blocking // Close CANAL channel m_pDeviceItem->m_proc_CanalClose(m_pDeviceItem->m_openHandle); // Library is unloaded in destructor // Remove messages in the client queues m_pCtrlObject->m_wxClientMutex.Lock(); m_pCtrlObject->removeClient(m_pDeviceItem->m_pClientItem); m_pCtrlObject->m_wxClientMutex.Unlock(); if (NULL != m_preceiveThread) { m_preceiveThread->Wait(); delete m_preceiveThread; } if (NULL != m_pwriteThread) { m_pwriteThread->Wait(); delete m_pwriteThread; } } else if (VSCP_DRIVER_LEVEL2 == m_pDeviceItem->m_driverLevel) { // Now find methods in library { wxString str; str = _("Loading level II driver: <"); str += m_pDeviceItem->m_strName; str += _(">"); str += _("\n"); m_pCtrlObject->logMsg(str); } // * * * * VSCP OPEN * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPOpen = (LPFNDLL_VSCPOPEN) m_wxdll.GetSymbol(_T("VSCPOpen")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPOpen.\n")); return NULL; } // * * * * VSCP CLOSE * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPClose = (LPFNDLL_VSCPCLOSE) m_wxdll.GetSymbol(_T("VSCPClose")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPClose.\n")); return NULL; } // * * * * VSCP BLOCKINGSEND * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPBlockingSend = (LPFNDLL_VSCPBLOCKINGSEND) m_wxdll.GetSymbol(_T("VSCPBlockingSend")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPBlockingSend.\n")); return NULL; } // * * * * VSCP BLOCKINGRECEIVE * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPBlockingReceive = (LPFNDLL_VSCPBLOCKINGRECEIVE) m_wxdll.GetSymbol(_T("VSCPBlockingReceive")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPBlockingReceive.\n")); return NULL; } // * * * * VSCP GETLEVEL * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPGetLevel = (LPFNDLL_VSCPGETLEVEL) m_wxdll.GetSymbol(_T("VSCPGetLevel")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetLevel.\n")); return NULL; } // * * * * VSCP GET DLL VERSION * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPGetDllVersion = (LPFNDLL_VSCPGETDLLVERSION) m_wxdll.GetSymbol(_T("VSCPGetDllVersion")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetDllVersion.\n")); return NULL; } // * * * * VSCP GET VENDOR STRING * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPGetVendorString = (LPFNDLL_VSCPGETVENDORSTRING) m_wxdll.GetSymbol(_T("VSCPGetVendorString")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetVendorString.\n")); return NULL; } // * * * * VSCP GET DRIVER INFO * * * * if (NULL == (m_pDeviceItem->m_proc_CanalGetdriverInfo = (LPFNDLL_VSCPGETVENDORSTRING) m_wxdll.GetSymbol(_T("VSCPGetDriverInfo")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetDriverInfo.\n")); return NULL; } // * * * * VSCP GET WEB PAGE TEMPLATE * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPGetWebPageTemplate = (LPFNDLL_VSCPGETWEBPAGETEMPLATE) m_wxdll.GetSymbol(_T("VSCPGetWebPageTemplate")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetWebPageTemplate.\n")); return NULL; } // * * * * VSCP GET WEB PAGE INFO * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPGetWebPageInfo = (LPFNDLL_VSCPGETWEBPAGEINFO) m_wxdll.GetSymbol(_T("VSCPGetWebPageInfo")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetWebPageInfo.\n")); return NULL; } // * * * * VSCP WEB PAGE UPDATE * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPWebPageupdate = (LPFNDLL_VSCPWEBPAGEUPDATE) m_wxdll.GetSymbol(_T("VSCPWebPageupdate")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPWebPageupdate.\n")); return NULL; } m_pCtrlObject->logMsg(_("Discovered all methods\n")); // Username, password, host and port can be set in configuration file. Read in them here // if they are. wxString strHost(_("127.0.0.1:9598")); wxStringTokenizer tkz(m_pDeviceItem->m_strParameter, _(";")); if (tkz.HasMoreTokens()) { CVSCPVariable *pVar; // Get prefix wxString prefix = tkz.GetNextToken(); // Check if username is specified in the configuration file pVar = m_pCtrlObject->m_VSCP_Variables.find(m_pDeviceItem->m_strName + _("_username")); if (NULL != pVar) { wxString str; if (VSCP_DAEMON_VARIABLE_CODE_STRING == pVar->getType()) { pVar->getValue( str ); m_pCtrlObject->m_driverUsername = str; } } // Check if password is specified in the configuration file pVar = m_pCtrlObject->m_VSCP_Variables.find(m_pDeviceItem->m_strName + _("_password")); if (NULL != pVar) { wxString str; if (VSCP_DAEMON_VARIABLE_CODE_STRING == pVar->getType()) { pVar->getValue( str ); m_pCtrlObject->m_driverPassword = str; } } // Check if host is specified in the configuration file pVar = m_pCtrlObject->m_VSCP_Variables.find(m_pDeviceItem->m_strName + _("_host")); if (NULL != pVar) { wxString str; if (VSCP_DAEMON_VARIABLE_CODE_STRING == pVar->getType()) { pVar->getValue( str ); strHost = str; } } } // Open up the driver m_pDeviceItem->m_openHandle = m_pDeviceItem->m_proc_VSCPOpen( m_pCtrlObject->m_driverUsername.mbc_str(), ( const char * )m_pCtrlObject->m_driverPassword.mbc_str(), ( const char * )strHost.mbc_str(), 0, ( const char * )m_pDeviceItem->m_strName.mbc_str(), ( const char * )m_pDeviceItem->m_strParameter.mbc_str() ); if ( 0 == m_pDeviceItem->m_openHandle ) { // Free the library m_pCtrlObject->logMsg( _T( "Unable to open the library.\n" ) ); return NULL; } ///////////////////////////////////////////////////////////////////////////// // Device write worker thread ///////////////////////////////////////////////////////////////////////////// m_pwriteLevel2Thread = new deviceLevel2WriteThread; if (m_pwriteLevel2Thread) { m_pwriteLevel2Thread->m_pMainThreadObj = this; wxThreadError err; if (wxTHREAD_NO_ERROR == (err = m_pwriteLevel2Thread->Create())) { m_pwriteLevel2Thread->SetPriority(WXTHREAD_MAX_PRIORITY); if (wxTHREAD_NO_ERROR != (err = m_pwriteLevel2Thread->Run())) { m_pCtrlObject->logMsg(_("Unable to run device write worker thread.")); } } else { m_pCtrlObject->logMsg(_("Unable to create device write worker thread.")); } } else { m_pCtrlObject->logMsg(_("Unable to allocate memory for device write worker thread.")); } ///////////////////////////////////////////////////////////////////////////// // Device read worker thread ///////////////////////////////////////////////////////////////////////////// m_preceiveLevel2Thread = new deviceLevel2ReceiveThread; if (m_preceiveLevel2Thread) { m_preceiveLevel2Thread->m_pMainThreadObj = this; wxThreadError err; if (wxTHREAD_NO_ERROR == (err = m_preceiveLevel2Thread->Create())) { m_preceiveLevel2Thread->SetPriority(WXTHREAD_MAX_PRIORITY); if (wxTHREAD_NO_ERROR != (err = m_preceiveLevel2Thread->Run())) { m_pCtrlObject->logMsg(_("Unable to run device receive worker thread.")); } } else { m_pCtrlObject->logMsg(_("Unable to create device receive worker thread.") ); } } else { m_pCtrlObject->logMsg(_("Unable to allocate memory for device receive worker thread.") ); } // Just sit and wait until the end of the world as we know it... while (!TestDestroy() && !m_pDeviceItem->m_bQuit) { wxSleep(200); } m_preceiveLevel2Thread->m_bQuit = true; m_pwriteLevel2Thread->m_bQuit = true; // Close channel m_pDeviceItem->m_proc_VSCPClose(m_pDeviceItem->m_openHandle); // Library is unloaded in destructor // Remove messages in the client queues m_pCtrlObject->m_wxClientMutex.Lock(); m_pCtrlObject->removeClient(m_pDeviceItem->m_pClientItem); m_pCtrlObject->m_wxClientMutex.Unlock(); if (NULL != m_preceiveLevel2Thread) { m_preceiveLevel2Thread->Wait(); delete m_preceiveLevel2Thread; } if (NULL != m_pwriteLevel2Thread) { m_pwriteLevel2Thread->Wait(); delete m_pwriteLevel2Thread; } } // // ===================================================================================== // return NULL; }
void * deviceThread(void *pData) { const char *dlsym_error; CDeviceItem *pDevItem = (CDeviceItem *)pData; if (NULL == pDevItem) { syslog(LOG_CRIT, "No device item defined. Aborting device thread!"); return NULL; } // Must have a valid pointer to the control object CControlObject *pCtrlObj = pDevItem->m_pCtrlObject; if (NULL == pCtrlObj) { syslog(LOG_CRIT, "No control object defined. Aborting device thread!"); return NULL; } // We need to create a clientobject and add this object to the list CClientItem *pClientItem = pDevItem->m_pClientItem = new CClientItem; if (NULL == pClientItem) { return NULL; } // This is now an active Client pClientItem->m_bOpen = true; if (VSCP_DRIVER_LEVEL1 == pDevItem->m_driverLevel) { pClientItem->m_type = CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL1; } else if (VSCP_DRIVER_LEVEL2 == pDevItem->m_driverLevel) { pClientItem->m_type = CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL2; } else if (VSCP_DRIVER_LEVEL3 == pDevItem->m_driverLevel) { pClientItem->m_type = CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL3; } char datebuf[80]; time_t now = time(NULL); vscp_getTimeString(datebuf, sizeof(datebuf), &now); pClientItem->m_strDeviceName = pDevItem->m_strName; pClientItem->m_strDeviceName += "|Started at "; pClientItem->m_strDeviceName += datebuf; syslog(LOG_DEBUG, "Devicethread: Starting %s", pClientItem->m_strDeviceName.c_str()); // Add the client to the Client List pthread_mutex_lock(&pCtrlObj->m_clientList.m_mutexItemList); if (!pCtrlObj->addClient(pClientItem, pDevItem->m_interface_guid.getClientID())) { // Failed to add client delete pDevItem->m_pClientItem; pDevItem->m_pClientItem = NULL; pthread_mutex_unlock(&pCtrlObj->m_clientList.m_mutexItemList); syslog(LOG_ERR, "Devicethread: Failed to add client. Terminating thread."); return NULL; } pthread_mutex_unlock(&pCtrlObj->m_clientList.m_mutexItemList); // Client now have GUID set to server GUID + channel id // If device has a non NULL GUID replace the client GUID preserving // the channel id with that GUID if (!pClientItem->m_guid.isNULL()) { memcpy( pClientItem->m_guid.m_id, pDevItem->m_interface_guid.getGUID(), 12); } void *hdll; if (VSCP_DRIVER_LEVEL3 != pDevItem->m_driverLevel) { // Load dynamic library hdll = dlopen(pDevItem->m_strPath.c_str(), RTLD_LAZY); if (!hdll) { syslog(LOG_ERR, "Devicethread: Unable to load dynamic library. path = %s", pDevItem->m_strPath.c_str()); return NULL; } } else { // Level III driver // Startup Level III driver std::string executable = pDevItem->m_strPath; pid_t pid = fork(); if (pid == -1) { syslog(LOG_ERR, "Failed to start level III driver %s (fork).", pDevItem->m_strName.c_str()); } else if (pid == 0) { // we're in child // Set process group to child process' pid. Then killing -pid // of the parent will kill the process and all of its children. setsid(); // Arguments: TODO // user // password // config parameters... // execvp( *argv, const_cast<char**>(argv) ); // Wait on child int status; waitpid(pid, &status, 0); } } if (VSCP_DRIVER_LEVEL1 == pDevItem->m_driverLevel) { // Now find methods in library syslog( LOG_INFO, "Loading level I driver: %s", pDevItem->m_strName.c_str()); // * * * * CANAL OPEN * * * * pDevItem->m_proc_CanalOpen = (LPFNDLL_CANALOPEN)dlsym(hdll, "CanalOpen"); const char *dlsym_error = dlerror(); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_DEBUG, "%s : Unable to get dl entry for CanalOpen.", pDevItem->m_strName.c_str()); return NULL; } // * * * * CANAL CLOSE * * * * pDevItem->m_proc_CanalClose = (LPFNDLL_CANALCLOSE)dlsym(hdll, "CanalClose"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalClose.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL GETLEVEL * * * * pDevItem->m_proc_CanalGetLevel = (LPFNDLL_CANALGETLEVEL)dlsym(hdll, "CanalGetLevel"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalGetLevel.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL SEND * * * * pDevItem->m_proc_CanalSend = (LPFNDLL_CANALSEND)dlsym(hdll, "CanalSend"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalSend.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL DATA AVAILABLE * * * * pDevItem->m_proc_CanalDataAvailable = (LPFNDLL_CANALDATAAVAILABLE)dlsym(hdll, "CanalDataAvailable"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalDataAvailable.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL RECEIVE * * * * pDevItem->m_proc_CanalReceive = (LPFNDLL_CANALRECEIVE)dlsym(hdll, "CanalReceive"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalReceive.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL GET STATUS * * * * pDevItem->m_proc_CanalGetStatus = (LPFNDLL_CANALGETSTATUS)dlsym(hdll, "CanalGetStatus"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalGetStatus.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL GET STATISTICS * * * * pDevItem->m_proc_CanalGetStatistics = (LPFNDLL_CANALGETSTATISTICS)dlsym(hdll, "CanalGetStatistics"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalGetStatistics.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL SET FILTER * * * * pDevItem->m_proc_CanalSetFilter = (LPFNDLL_CANALSETFILTER)dlsym(hdll, "CanalSetFilter"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalSetFilter.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL SET MASK * * * * pDevItem->m_proc_CanalSetMask = (LPFNDLL_CANALSETMASK)dlsym(hdll, "CanalSetMask"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalSetMask.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL GET VERSION * * * * pDevItem->m_proc_CanalGetVersion = (LPFNDLL_CANALGETVERSION)dlsym(hdll, "CanalGetVersion"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalGetVersion.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL GET DLL VERSION * * * * pDevItem->m_proc_CanalGetDllVersion = (LPFNDLL_CANALGETDLLVERSION)dlsym(hdll, "CanalGetDllVersion"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalGetDllVersion.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL GET VENDOR STRING * * * * pDevItem->m_proc_CanalGetVendorString = (LPFNDLL_CANALGETVENDORSTRING)dlsym(hdll, "CanalGetVendorString"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalGetVendorString.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // ****************************** // Generation 2 Methods // ****************************** // * * * * CANAL BLOCKING SEND * * * * pDevItem->m_proc_CanalBlockingSend = (LPFNDLL_CANALBLOCKINGSEND)dlsym(hdll, "CanalBlockingSend"); dlsym_error = dlerror(); if (dlsym_error) { syslog(LOG_ERR, "%s: Unable to get dl entry for CanalBlockingSend. Probably " "Generation 1 driver.", pDevItem->m_strName.c_str()); pDevItem->m_proc_CanalBlockingSend = NULL; } // * * * * CANAL BLOCKING RECEIVE * * * * pDevItem->m_proc_CanalBlockingReceive = (LPFNDLL_CANALBLOCKINGRECEIVE)dlsym(hdll, "CanalBlockingReceive"); dlsym_error = dlerror(); if (dlsym_error) { syslog(LOG_ERR, "%s: Unable to get dl entry for CanalBlockingReceive. " "Probably Generation 1 driver.", pDevItem->m_strName.c_str()); pDevItem->m_proc_CanalBlockingReceive = NULL; } // * * * * CANAL GET DRIVER INFO * * * * pDevItem->m_proc_CanalGetdriverInfo = (LPFNDLL_CANALGETDRIVERINFO)dlsym(hdll, "CanalGetDriverInfo"); dlsym_error = dlerror(); if (dlsym_error) { syslog(LOG_ERR, "%s: Unable to get dl entry for CanalGetDriverInfo. " "Probably Generation 1 driver.", pDevItem->m_strName.c_str()); pDevItem->m_proc_CanalGetdriverInfo = NULL; } // Open the device pDevItem->m_openHandle = pDevItem->m_proc_CanalOpen( (const char *)pDevItem->m_strParameter.c_str(), pDevItem->m_DeviceFlags); // Check if the driver opened properly if (pDevItem->m_openHandle <= 0) { syslog(LOG_ERR, "Failed to open driver. Will not use it! [%s] ", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level I Driver open.", pDevItem->m_strName.c_str()); } // Get Driver Level pDevItem->m_driverLevel = pDevItem->m_proc_CanalGetLevel(pDevItem->m_openHandle); // * * * Level I Driver * * * // Check if blocking driver is available if (NULL != pDevItem->m_proc_CanalBlockingReceive) { // * * * * Blocking version * * * * if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level I blocking version.", pDevItem->m_strName.c_str()); } ///////////////////////////////////////////////////////////////////////////// // Device write worker thread ///////////////////////////////////////////////////////////////////////////// if (pthread_create(&pDevItem->m_level1WriteThread, NULL, deviceLevel1WriteThread, pDevItem)) { syslog(LOG_CRIT, "%s: Unable to run the device write worker thread.", pDevItem->m_strName.c_str()); // pDevItem->m_openHandle = pDevItem->m_proc_CanalOpen(); dlclose(hdll); return NULL; } ///////////////////////////////////////////////////////////////////////////// // Device read worker thread ///////////////////////////////////////////////////////////////////////////// if (pthread_create(&pDevItem->m_level1ReceiveThread, NULL, deviceLevel1ReceiveThread, pDevItem)) { syslog(LOG_CRIT, "%s: Unable to run the device read worker thread.", pDevItem->m_strName.c_str()); pDevItem->m_bQuit = true; pthread_join(pDevItem->m_level1WriteThread, NULL); // pDevItem->m_openHandle = pDevItem->m_proc_CanalOpen(); dlclose(hdll); return NULL; } // Just sit and wait until the end of the world as we know it... while (!pDevItem->m_bQuit) { sleep(1); } // Signal worker threads to quit pDevItem->m_bQuit = true; if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level I work loop ended.", pDevItem->m_strName.c_str()); } // Wait for workerthreads to abort pthread_join(pDevItem->m_level1WriteThread, NULL); pthread_join(pDevItem->m_level1ReceiveThread, NULL); } else { // * * * * Non blocking version * * * * if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level I NON Blocking version.", pDevItem->m_strName.c_str()); } bool bActivity; while (pDevItem->m_bQuit) { bActivity = false; ///////////////////////////////////////////////////////////////////////////// // Receive from device ///////////////////////////////////////////////////////////////////////////// canalMsg msg; if (pDevItem->m_proc_CanalDataAvailable( pDevItem->m_openHandle)) { if (CANAL_ERROR_SUCCESS == pDevItem->m_proc_CanalReceive(pDevItem->m_openHandle, &msg)) { bActivity = true; // There must be room in the receive queue if (pCtrlObj->m_maxItemsInClientReceiveQueue > pCtrlObj->m_clientOutputQueue.size()) { vscpEvent *pvscpEvent = new vscpEvent; if (NULL != pvscpEvent) { // Set driver GUID if set /*if ( pDevItem->m_interface_guid.isNULL() ) { pDevItem->m_interface_guid.writeGUID( pvscpEvent->GUID ); } else { // If no driver GUID set use interface GUID pItem->m_guid.writeGUID( pvscpEvent->GUID ); }*/ // Convert CANAL message to VSCP event vscp_convertCanalToEvent( pvscpEvent, &msg, pClientItem->m_guid.m_id); pvscpEvent->obid = pClientItem->m_clientID; pthread_mutex_lock( &pCtrlObj->m_mutexClientOutputQueue); pCtrlObj->m_clientOutputQueue.push_back( pvscpEvent); sem_post(&pCtrlObj->m_semClientOutputQueue); pthread_mutex_unlock( &pCtrlObj->m_mutexClientOutputQueue); } } } } // data available // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Send messages (if any) in the output queue // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Check if there is something to send if (pClientItem->m_clientInputQueue.size()) { bActivity = true; std::deque<vscpEvent *>::iterator it; pthread_mutex_lock(&pClientItem->m_mutexClientInputQueue); vscpEvent *pqueueEvent = pClientItem->m_clientInputQueue.front(); pthread_mutex_lock(&pClientItem->m_mutexClientInputQueue); // Trow away Level II event on Level I interface if ((CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL1 == pClientItem->m_type) && (pqueueEvent->vscp_class > 512)) { // Remove the event and the node pClientItem->m_clientInputQueue.pop_front(); syslog(LOG_ERR, "Level II event on Level I queue thrown away. " "class=%d, type=%d", pqueueEvent->vscp_class, pqueueEvent->vscp_type); vscp_deleteVSCPevent(pqueueEvent); continue; } canalMsg canalMsg; vscp_convertEventToCanal(&canalMsg, pqueueEvent); if (CANAL_ERROR_SUCCESS == pDevItem->m_proc_CanalSend(pDevItem->m_openHandle, &canalMsg)) { // Remove the event and the node pClientItem->m_clientInputQueue.pop_front(); delete pqueueEvent; } else { // Another try // pCtrlObj->m_semClientOutputQueue.Post(); // vscp_deleteVSCPevent(pqueueEvent); TODO ???? } } // events if (!bActivity) { usleep(100000); // 100 ms } bActivity = false; } // while working - non blocking } // if blocking/non blocking if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level I Work loop ended.", pDevItem->m_strName.c_str()); } // Close CANAL channel pDevItem->m_proc_CanalClose(pDevItem->m_openHandle); if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level I Closed.", pDevItem->m_strName.c_str()); } level1_driver_exit: pDevItem->m_bQuit = true; pthread_join(pDevItem->m_level1WriteThread, NULL); pthread_join(pDevItem->m_level1ReceiveThread, NULL); dlclose(hdll); } else if (VSCP_DRIVER_LEVEL2 == pDevItem->m_driverLevel) { // Now find methods in library syslog(LOG_INFO, "Loading level II driver: <%s>", pDevItem->m_strName.c_str()); // * * * * VSCP OPEN * * * * if (NULL == (pDevItem->m_proc_VSCPOpen = (LPFNDLL_VSCPOPEN)dlsym(hdll, "VSCPOpen"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPOpen.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP CLOSE * * * * if (NULL == (pDevItem->m_proc_VSCPClose = (LPFNDLL_VSCPCLOSE)dlsym(hdll, "VSCPClose"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPClose.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP BLOCKINGSEND * * * * if (NULL == (pDevItem->m_proc_VSCPBlockingSend = (LPFNDLL_VSCPBLOCKINGSEND)dlsym(hdll, "VSCPBlockingSend"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPBlockingSend.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP BLOCKINGRECEIVE * * * * if (NULL == (pDevItem->m_proc_VSCPBlockingReceive = (LPFNDLL_VSCPBLOCKINGRECEIVE)dlsym( hdll, "VSCPBlockingReceive"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPBlockingReceive.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP GETLEVEL * * * * if (NULL == (pDevItem->m_proc_VSCPGetLevel = (LPFNDLL_VSCPGETLEVEL)dlsym(hdll, "VSCPGetLevel"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPGetLevel.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP GET DLL VERSION * * * * if (NULL == (pDevItem->m_proc_VSCPGetDllVersion = (LPFNDLL_VSCPGETDLLVERSION)dlsym(hdll, "VSCPGetDllVersion"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPGetDllVersion.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP GET VENDOR STRING * * * * if (NULL == (pDevItem->m_proc_VSCPGetVendorString = (LPFNDLL_VSCPGETVENDORSTRING)dlsym( hdll, "VSCPGetVendorString"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPGetVendorString.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP GET DRIVER INFO * * * * if (NULL == (pDevItem->m_proc_CanalGetdriverInfo = (LPFNDLL_VSCPGETVENDORSTRING)dlsym(hdll, "VSCPGetDriverInfo"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPGetDriverInfo.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP GET WEB PAGE TEMPLATE * * * * if (NULL == (pDevItem->m_proc_VSCPGetWebPageTemplate = (LPFNDLL_VSCPGETWEBPAGETEMPLATE)dlsym( hdll, "VSCPGetWebPageTemplate"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPGetWebPageTemplate.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP GET WEB PAGE INFO * * * * if (NULL == (pDevItem->m_proc_VSCPGetWebPageInfo = (LPFNDLL_VSCPGETWEBPAGEINFO)dlsym(hdll, "VSCPGetWebPageInfo"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPGetWebPageInfo.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP WEB PAGE UPDATE * * * * if (NULL == (pDevItem->m_proc_VSCPWebPageupdate = (LPFNDLL_VSCPWEBPAGEUPDATE)dlsym(hdll, "VSCPWebPageupdate"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPWebPageupdate.", pDevItem->m_strName.c_str()); return NULL; } if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: Discovered all methods\n", pDevItem->m_strName.c_str()); } // Username, password, host and port can be set in configuration file. // Read in them here if they are. std::string strHost("127.0.0.1"); short port = 9598; std::deque<std::string> tokens; vscp_split(tokens, pDevItem->m_strParameter, ";"); if (false == tokens.empty()) { CVariable variable; // Get prefix std::string prefix = tokens.front(); tokens.pop_front(); // Check if username is specified in the configuration file CUserItem *pAdminUser = pDevItem->m_pCtrlObject->m_userList.getUser(USER_ID_ADMIN); if (pCtrlObj->m_variables.find( pDevItem->m_strName + "_username", pAdminUser, variable)) { std::string str; if (VSCP_DAEMON_VARIABLE_CODE_STRING == variable.getType()) { str = variable.getValue(); pCtrlObj->m_driverUsername = str; } } // Check if password is specified in the configuration file if (pCtrlObj->m_variables.find( pDevItem->m_strName + "_password", pAdminUser, variable)) { std::string str; if (VSCP_DAEMON_VARIABLE_CODE_STRING == variable.getType()) { str = variable.getValue(); pCtrlObj->m_driverPassword = str; } } // Check if host is specified in the configuration file if (pCtrlObj->m_variables.find( pDevItem->m_strName + "_host", pAdminUser, variable)) { std::string str; if (VSCP_DAEMON_VARIABLE_CODE_STRING == variable.getType()) { str = variable.getValue(); strHost = str; } } // Check if host is specified in the configuration file if (pCtrlObj->m_variables.find( pDevItem->m_strName + "_port", pAdminUser, variable)) { std::string str; if (VSCP_DAEMON_VARIABLE_CODE_INTEGER == variable.getType()) { str = variable.getValue(); port = vscp_readStringValue(str); } } } // Open up the driver pDevItem->m_openHandle = pDevItem->m_proc_VSCPOpen( pCtrlObj->m_driverUsername.c_str(), (const char *)pCtrlObj->m_driverPassword.c_str(), (const char *)strHost.c_str(), port, (const char *)pDevItem->m_strName.c_str(), (const char *)pDevItem->m_strParameter.c_str()); if (0 == pDevItem->m_openHandle) { // Free the library syslog(LOG_ERR, "%s: [Device tread] Unable to open VSCP " "driver (check username/password/path/" "rights). Possible additional info from driver " "in syslog.", pDevItem->m_strName.c_str()); return NULL; } if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level II Open.", pDevItem->m_strName.c_str()); } ///////////////////////////////////////////////////////////////////////////// // Device write worker thread ///////////////////////////////////////////////////////////////////////////// if (pthread_create(&pDevItem->m_level2WriteThread, NULL, deviceLevel2WriteThread, pDevItem)) { syslog(LOG_CRIT, "%s: Unable to run the device Level II write worker thread.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; // TODO close dll } if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level II Write thread created.", pDevItem->m_strName.c_str()); } ///////////////////////////////////////////////////////////////////////////// // Device read worker thread ///////////////////////////////////////////////////////////////////////////// if (pthread_create(&pDevItem->m_level2ReceiveThread, NULL, deviceLevel2ReceiveThread, pDevItem)) { syslog(LOG_CRIT, "%s: Unable to run the device Level II read worker thread.", pDevItem->m_strName.c_str()); pDevItem->m_bQuit = true; pthread_join(pDevItem->m_level2WriteThread, NULL); dlclose(hdll); return NULL; // TODO close dll, kill other thread } if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level II Write thread created.", pDevItem->m_strName.c_str()); } // Just sit and wait until the end of the world as we know it... while (!pDevItem->m_bQuit) { sleep(1); } if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level II Closing.", pDevItem->m_strName.c_str()); } // Close channel pDevItem->m_proc_VSCPClose(pDevItem->m_openHandle); if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level II Closed.", pDevItem->m_strName.c_str()); } level2_driver_exit: pDevItem->m_bQuit = true; pthread_join(pDevItem->m_level2WriteThread, NULL); pthread_join(pDevItem->m_level2ReceiveThread, NULL); // Unload dll dlclose(hdll); if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level II Done waiting for threads.", pDevItem->m_strName.c_str()); } } else if (VSCP_DRIVER_LEVEL3 == pDevItem->m_driverLevel) { if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level III Start server loop.", pDevItem->m_strName.c_str()); } // Just sit and wait until the end of the world as we know it... while (!pDevItem->m_bQuit) { sleep(1); } if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level II End server loop.", pDevItem->m_strName.c_str()); } } // Remove messages in the client queues pthread_mutex_lock(&pCtrlObj->m_clientList.m_mutexItemList); pCtrlObj->removeClient(pClientItem); pthread_mutex_unlock(&pCtrlObj->m_clientList.m_mutexItemList); return NULL; }