bool CVSCPBTDetectWrkTread::sendEvent( vscpEventEx& eventEx ) { vscpEvent *pEvent = new vscpEvent(); if ( NULL != pEvent ) { if ( vscp_convertVSCPfromEx( pEvent, &eventEx ) ) { // OK send the event m_pObj->m_mutexReceiveQueue.Lock(); m_pObj->m_receiveList.push_back( pEvent ); m_pObj->m_semReceiveQueue.Post(); m_pObj->m_mutexReceiveQueue.Unlock(); } else { vscp_deleteVSCPevent( pEvent ); #ifndef WIN32 syslog( LOG_ERR, "%s", ( const char * ) "Faild to convert event." ); #endif return false; } } return true; }
void *daemonVSCPThread::Entry() { int sock_mc; // socket descriptor struct sockaddr_in mc_addr; // socket address structure unsigned short mc_port = vscp_readStringValue( m_pCtrlObject->m_strMulticastAnnounceAddress ) ; // multicast port unsigned char mc_ttl = m_pCtrlObject->m_ttlMultiCastAnnounce; // time to live (hop count) #ifdef WIN32 WSADATA wsaData; // Windows socket DLL structure // Load Winsock 2.0 DLL if ( WSAStartup( MAKEWORD( 2, 0 ), &wsaData ) != 0 ) { fprintf( stderr, "WSAStartup() failed" ); m_pCtrlObject->logMsg( _( "Automation multicast announce WSAStartup() failed\n" ), DAEMON_LOGMSG_NORMAL, DAEMON_LOGTYPE_GENERAL ); return NULL; } // create a socket for sending to the multicast address if ( ( sock_mc = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ) { perror( "socket() failed" ); m_pCtrlObject->logMsg( _( "Automation multicast announce sock() failed\n" ), DAEMON_LOGMSG_NORMAL, DAEMON_LOGTYPE_GENERAL ); return NULL; } // set the TTL (time to live/hop count) for the send if ( ( setsockopt( sock_mc, IPPROTO_IP, IP_MULTICAST_TTL, ( const char* )&mc_ttl, sizeof( mc_ttl ) ) ) < 0 ) { perror( "setsockopt() failed" ); m_pCtrlObject->logMsg( _( "Automation multicast announce setsockopt() failed\n" ), DAEMON_LOGMSG_NORMAL, DAEMON_LOGTYPE_GENERAL ); return NULL; } // construct a multicast address structure memset( &mc_addr, 0, sizeof( mc_addr ) ); mc_addr.sin_family = AF_INET; mc_addr.sin_addr.s_addr = inet_addr( VSCP_MULTICAST_IPV4_ADDRESS_STR ); mc_addr.sin_port = htons( mc_port ); #else // create a socket for sending to the multicast address if ( ( sock_mc = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ) { perror( "socket() failed" ); return NULL; } // set the TTL (time to live/hop count) for the send if ( ( setsockopt( sock_mc, IPPROTO_IP, IP_MULTICAST_TTL, ( void* )&mc_ttl, sizeof( mc_ttl ) ) ) < 0 ) { perror( "setsockopt() failed" ); return NULL; } // construct a multicast address structure memset( &mc_addr, 0, sizeof( mc_addr ) ); mc_addr.sin_family = AF_INET; mc_addr.sin_addr.s_addr = inet_addr( VSCP_MULTICAST_IPV4_ADDRESS_STR ); mc_addr.sin_port = htons( mc_port ); #endif // 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 CClientItem *pClientItem = new CClientItem; if ( NULL == pClientItem ) return NULL; // This is an active client pClientItem->m_bOpen = true; pClientItem->m_type = CLIENT_ITEM_INTERFACE_TYPE_CLIENT_INTERNAL; pClientItem->m_strDeviceName = _("Internal Daemon VSCP Worker Client. Started at "); wxDateTime now = wxDateTime::Now(); pClientItem->m_strDeviceName += now.FormatISODate(); pClientItem->m_strDeviceName += _(" "); pClientItem->m_strDeviceName += now.FormatISOTime(); // Add the client to the Client List m_pCtrlObject->m_wxClientMutex.Lock(); m_pCtrlObject->addClient( pClientItem ); m_pCtrlObject->m_wxClientMutex.Unlock(); // Clear the filter (Allow everything ) vscp_clearVSCPFilter( &pClientItem->m_filterVSCP ); char szName[ 128 ]; #ifdef WIN32 LPHOSTENT lpLocalHostEntry; #else struct hostent *lpLocalHostEntry; #endif gethostname ( szName, sizeof ( szName ) ); lpLocalHostEntry = gethostbyname ( szName ); if ( NULL == lpLocalHostEntry ) { return NULL; } // Get all local addresses for interface int cntAddr = -1; void *pAddr; unsigned long localaddr[ 16 ]; // max 16 local addresses do { cntAddr++; localaddr[ cntAddr ] = 0; pAddr = lpLocalHostEntry->h_addr_list[ cntAddr ]; if ( NULL != pAddr ) localaddr[ cntAddr ] = * ( ( unsigned long * ) pAddr ); } while ( ( NULL != pAddr ) && ( cntAddr < 16 ) ); // * * * L O O P * * * CLIENTEVENTLIST::compatibility_iterator nodeClient; while ( !TestDestroy() && !m_bQuit ) { // Automation if ( m_pCtrlObject->m_automation.isAutomationEnabled() ) { // Check if automation event should be sent and send it if // that is the case vscpEventEx eventEx; if ( m_pCtrlObject->m_automation.doWork( &eventEx ) ) { m_pCtrlObject->logMsg( wxString::Format( _( "Automation event sent: Class=%d Type=%d\n" ), eventEx.vscp_class, eventEx.vscp_type ), DAEMON_LOGMSG_DEBUG, DAEMON_LOGTYPE_GENERAL ); // Yes event should be sent eventEx.obid = pClientItem->m_clientID; pClientItem->m_guid.writeGUID( eventEx.GUID ); if ( ( VSCP_CLASS1_PROTOCOL == eventEx.vscp_class ) && ( VSCP_TYPE_PROTOCOL_SEGCTRL_HEARTBEAT == eventEx.vscp_type ) ) { // crc8 of VSCP daemon GUID should be indata byte 0 eventEx.data[ 0 ] = vscp_calcCRC4GUIDArray( m_pCtrlObject->m_guid.getGUID() ); // Send event on multicast information channel sendMulticastEventEx( sock_mc, &eventEx, mc_port ); } else if ( ( VSCP_CLASS1_INFORMATION == eventEx.vscp_class ) && ( VSCP_TYPE_INFORMATION_NODE_HEARTBEAT == eventEx.vscp_type ) ) { // Send event on multicast information channel sendMulticastEventEx( sock_mc, &eventEx, mc_port ); } else if ( ( VSCP_CLASS2_INFORMATION == eventEx.vscp_class ) && ( VSCP2_TYPE_INFORMATION_HEART_BEAT == eventEx.vscp_type ) ) { // Copy in server name. memcpy( eventEx.data, m_pCtrlObject->m_strServerName.mbc_str(), MAX( 64, m_pCtrlObject->m_strServerName.Length() ) ); // Send event on multicast information channel sendMulticastEventEx( sock_mc, &eventEx, mc_port ); } vscpEvent *pnewEvent = new vscpEvent; if ( NULL != pnewEvent ) { // Convert event to correct format vscp_convertVSCPfromEx( pnewEvent, &eventEx ); // Statistics pClientItem->m_statistics.cntTransmitData += eventEx.sizeData; pClientItem->m_statistics.cntTransmitFrames++; // There must be room in the send queue if ( m_pCtrlObject->m_maxItemsInClientReceiveQueue > m_pCtrlObject->m_clientOutputQueue.GetCount() ) { m_pCtrlObject->m_mutexClientOutputQueue.Lock(); m_pCtrlObject->m_clientOutputQueue.Append ( pnewEvent ); m_pCtrlObject->m_semClientOutputQueue.Post(); m_pCtrlObject->m_mutexClientOutputQueue.Unlock(); } } } } /////////////////////////////////////////////////////////////////////// // Input queue /////////////////////////////////////////////////////////////////////// int rv = pClientItem->m_clientInputQueue.GetCount(); // Wait for incoming event if ( wxSEMA_TIMEOUT == pClientItem->m_semClientInputQueue.WaitTimeout( 100 ) ) continue; if ( pClientItem->m_clientInputQueue.GetCount() ) { pClientItem->m_mutexClientInputQueue.Lock(); nodeClient = pClientItem->m_clientInputQueue.GetFirst(); vscpEvent *pEvent = nodeClient->GetData(); pClientItem->m_clientInputQueue.DeleteNode( nodeClient ); // Remove the node pClientItem->m_mutexClientInputQueue.Unlock(); if ( NULL == pEvent ) continue; //***************************************** // First check for HIGH END SERVER PROBE (27) // and send out HIGH END SERVER RESPONSE (28) if // received. //***************************************** if ( ( VSCP_CLASS1_PROTOCOL == pEvent->vscp_class ) && ( VSCP_TYPE_PROTOCOL_HIGH_END_SERVER_PROBE == pEvent->vscp_type ) ) { for ( int i=0; i<cntAddr; i++ ) { // Yes this is a "HIGH END SERVER PROBE" // We should send a "HIGH END SERVER RESPONSE" vscpEvent *pnewEvent = new vscpEvent; if ( NULL != pnewEvent ) { pnewEvent->obid = pClientItem->m_clientID; pnewEvent->head = 0; pnewEvent->vscp_class = 0; pnewEvent->vscp_type = 28; pnewEvent->sizeData = 8; pClientItem->m_guid.writeGUID(pnewEvent->GUID); pnewEvent->pdata = new unsigned char[ 8 ]; if ( NULL != pnewEvent->pdata ) { pnewEvent->pdata[ 0 ] = VSCP_DAEMON_SERVER_CAPABILITIES_7; pnewEvent->pdata[ 1 ] = VSCP_DAEMON_SERVER_CAPABILITIES_6; pnewEvent->pdata[ 2 ] = ( localaddr[ i ] >> 24 ); pnewEvent->pdata[ 3 ] = ( localaddr[ i ] >> 16 ); pnewEvent->pdata[ 4 ] = ( localaddr[ i ] >> 8 ); pnewEvent->pdata[ 5 ] = ( localaddr[ i ] & 0xff ); pnewEvent->pdata[ 6 ] = 0x25; // TODO Change can be multiple servers pnewEvent->pdata[ 7 ] = 0x7E; } // Statistics pClientItem->m_statistics.cntTransmitData += pEvent->sizeData; pClientItem->m_statistics.cntTransmitFrames++; // There must be room in the send queue if ( m_pCtrlObject->m_maxItemsInClientReceiveQueue > m_pCtrlObject->m_clientOutputQueue.GetCount() ) { m_pCtrlObject->m_mutexClientOutputQueue.Lock(); m_pCtrlObject->m_clientOutputQueue.Append ( pnewEvent ); m_pCtrlObject->m_semClientOutputQueue.Post(); m_pCtrlObject->m_mutexClientOutputQueue.Unlock(); } } } // for each server address }
static void ev_handler( struct ns_connection *nc, int ev, void *p ) { struct ns_mqtt_message *msg = ( struct ns_mqtt_message * )p; Cmqttobj *pmqttobj = ( Cmqttobj *)nc->mgr->user_data; switch ( ev ) { case NS_CONNECT: ns_set_protocol_mqtt( nc ); ns_send_mqtt_handshake( nc, "vscpd" ); break; case NS_MQTT_CONNACK: if ( msg->connack_ret_code != NS_MQTT_CONNACK_ACCEPTED ) { printf( "Got mqtt connection error: %d\n", msg->connack_ret_code ); pmqttobj->m_bQuit = true; return; } pmqttobj->m_bConnected = true; if ( pmqttobj->m_bSubscribe ) { ns_mqtt_subscribe( nc, pmqttobj->m_topic_list, 1, 42 ); } else { ; } break; case NS_MQTT_PUBACK: printf( "Message publishing acknowledged (msg_id: %d)\n", msg->message_id ); break; case NS_MQTT_SUBACK: printf( "Subscription acknowledged, forwarding to '/test'\n" ); break; case NS_MQTT_PUBLISH: { printf( "Got incoming message %s: %.*s\n", msg->topic, ( int )msg->payload.len, msg->payload.p ); vscpEventEx eventEx; if ( !strcmp( msg->topic, pmqttobj->m_topic.ToAscii() ) ) { wxString str = wxString::FromAscii( ( const char * )msg->payload.p ); if ( vscp_setVscpEventExFromString( &eventEx, str ) ) { vscpEvent *pEvent = new vscpEvent; if ( NULL != pEvent ) { pEvent->sizeData = 0; pEvent->pdata = NULL; if ( vscp_doLevel2FilterEx( &eventEx, &pmqttobj->m_vscpfilter ) ) { if ( vscp_convertVSCPfromEx( pEvent, &eventEx ) ) { pmqttobj->m_mutexReceiveQueue.Lock(); pmqttobj->m_receiveList.push_back( pEvent ); pmqttobj->m_semReceiveQueue.Post(); pmqttobj->m_mutexReceiveQueue.Unlock(); } else { } } else { vscp_deleteVSCPevent( pEvent ); } } } } } break; case NS_CLOSE: printf( "Connection closed\n" ); pmqttobj->m_bConnected = false; pmqttobj->m_bQuit = true; } }
void * CWrkReadThread::Entry() { pcap_t *fp; char errbuf[ PCAP_ERRBUF_SIZE ]; //uint8_t packet[ 512 ]; // First log on to the host and get configuration // variables if (m_srv.doCmdOpen(m_pObj->m_host, m_pObj->m_username, m_pObj->m_password) <= 0) { return NULL; } // Find the channel id m_srv.doCmdGetChannelID(&m_pObj->m_ChannelIDtx); // It is possible that there is configuration data the server holds // that we need to read in. // We look for // prefix_interface Communication interface to work on // prefix_localmac MAC address to use for outgoing packets // prefix_filter to find a filter. A string is expected. // prefix_mask to find a mask. A string is expected. /* // Interface wxString varInterface; if (m_srv.getVariableString(m_pObj->m_prefix + _T("_interface"), &varInterface)) { m_pObj->m_interface = varInterface; } wxString varLocalMac; if (m_srv.getVariableString(m_pObj->m_prefix + _T("_localmac"), &varLocalMac)) { varLocalMac.MakeUpper(); wxStringTokenizer tkz(varLocalMac, ":\n"); for (int i = 0; i < 6; i++) { if (tkz.HasMoreTokens()) break; wxString str = _("0X") + tkz.GetNextToken(); m_pObj->m_localMac[ i ] = readStringValue(str); m_pObj->m_localGUIDtx.setAt((9 + i), m_pObj->m_localMac[ i ]); m_pObj->m_localGUIDrx.setAt((9 + i), m_pObj->m_localMac[ i ]); } } */ // We want to use our own Ethernet based GUID for this interface //wxString strGUID; //m_pObj->m_localGUIDtx.toString(strGUID); //m_srv.doCmdSetGUID((const char *) strGUID.ToAscii()); // Open the adapter if ((fp = pcap_open_live(m_pObj->m_interface.ToAscii(), // name of the device 65536, // portion of the packet to capture. It doesn't matter in this case 1, // promiscuous mode (nonzero means promiscuous) 1000, // read timeout errbuf // error buffer )) == NULL) { //fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", argv[1]); return NULL; } int rv; struct pcap_pkthdr *header; const u_char *pkt_data; while (!TestDestroy() && !m_pObj->m_bQuit && (rv = pcap_next_ex(fp, &header, &pkt_data)) >= 0) { // Check for timeout if (0 == rv) continue; // Check if this is VSCP if ((0x25 == pkt_data[ 12 ]) && (0x7e == pkt_data[ 13 ])) { // We have a packet - send it as a VSCP event vscpEventEx eventex; eventex.head = pkt_data[ 15 ] & 0xe0; // Priority eventex.GUID[ 0 ] = 0xff; // Ethernet predefined GUID eventex.GUID[ 1 ] = 0xff; eventex.GUID[ 2 ] = 0xff; eventex.GUID[ 3 ] = 0xff; eventex.GUID[ 4 ] = 0xff; eventex.GUID[ 5 ] = 0xff; eventex.GUID[ 6 ] = 0xff; eventex.GUID[ 7 ] = 0xfe; eventex.GUID[ 8 ] = pkt_data[ 6 ]; // Source MAC address eventex.GUID[ 9 ] = pkt_data[ 7 ]; eventex.GUID[ 10 ] = pkt_data[ 8 ]; eventex.GUID[ 11 ] = pkt_data[ 9 ]; eventex.GUID[ 12 ] = pkt_data[ 10 ]; eventex.GUID[ 13 ] = pkt_data[ 11 ]; eventex.GUID[ 14 ] = pkt_data[ 19 ]; // Device sub address eventex.GUID[ 15 ] = pkt_data[ 20 ]; eventex.timestamp = (pkt_data[ 21 ] << 24) + (pkt_data[ 22 ] << 16) + (pkt_data[ 23 ] << 8) + pkt_data[ 24 ]; eventex.obid = (pkt_data[ 25 ] << 24) + (pkt_data[ 26 ] << 16) + (pkt_data[ 27 ] << 8) + pkt_data[ 28 ]; eventex.vscp_class = (pkt_data[ 29 ] << 8) + pkt_data[ 30 ]; eventex.vscp_type = (pkt_data[ 31 ] << 8) + pkt_data[ 32 ]; eventex.sizeData = (pkt_data[ 33 ] << 8) + pkt_data[ 34 ]; // If the packet is smaller then the set datasize just // disregard it if ((eventex.sizeData + 35) > (uint16_t) header->len) continue; for (int i = 0; i < eventex.sizeData; i++) { eventex.data[ i ] = pkt_data[ 35 + i ]; } vscpEvent *pEvent = new vscpEvent; if (NULL != pEvent) { vscp_convertVSCPfromEx(pEvent, &eventex); if (vscp_doLevel2FilterEx( &eventex, &m_pObj->m_vscpfilter)) { m_pObj->m_mutexReceiveQueue.Lock(); m_pObj->m_receiveList.push_back(pEvent); m_pObj->m_semReceiveQueue.Post(); m_pObj->m_mutexReceiveQueue.Unlock(); } else { vscp_deleteVSCPevent(pEvent); } } } } // work loop // Close listner pcap_close(fp); // Close the channel //m_srv.doCmdClose(); return NULL; }