I'm working on simple host program (c++/xcode/osx) that establishes a connection to a Bluetooth client and opens an RFCOMM channel for data transmission. When I send data from the BT client to the host I get my data mixed with random dumps from what looks to be a Bluetooth Audio Agent. Is it possible that I'm sharing my RFCOMM channel with the OS X Bluetooth Audio Agent?
My Bluetooth device needs to support both Serial (SPP) and Hands-Free (HFP) profiles. So I strongly believe that the issue is around the HFP or SCO profile polluting my RFCOMM channel with it's data. Is there a way to make sure that I only get my data coming through the channel?
Here's a condensed version of my project. When the client is connected it starts echoing the letter a. The host app prints what it receives from the client, and if the received data is an a it also logs OK!\n.
#include <IOBluetooth/IOBluetoothUserLib.h>
#include <IOBluetooth/IOBluetoothUtilities.h>
#include <IOBluetoothUI/IOBluetoothUI.h>
#include <IOBluetoothUI/IOBluetoothUIUserLib.h>
#include "testApp.h"
// Callback function create-connection
void bluetoothCreateConnection_c(void *userRefCon, IOBluetoothDeviceRef deviceRef, IOReturn status) {
printf("Created connection\n");
}
// Callback for RFCOMM events
void rfcommEventListener_c (IOBluetoothRFCOMMChannelRef channel_ref, void *userRefCon, IOBluetoothRFCOMMChannelEvent *event) {
if (event->eventType == kIOBluetoothRFCOMMNewDataEvent) {
const char *data_const = (const char *)event->u.data.dataPtr;
char *dataAsBytes = const_cast<char *>(data_const);
string in_s = (string)dataAsBytes;
printf("%s", dataAsBytes);
if(in_s == "a") {
printf("OK!\n");
}
}
}
void testApp::setup() {
BluetoothDeviceAddress *addr;
string s = "00-16-a4-00-72-3d"; // hardcoded BT address
CFStringRef str_addr;
str_addr = CFStringCreateWithCString(kCFAllocatorDefault, s.c_str(), kCFStringEncodingMacRoman);
IOBluetoothCFStringToDeviceAddress(str_addr, addr);
IOBluetoothDeviceRef dev = IOBluetoothDeviceCreateWithAddress(addr);
IOBluetoothDeviceOpenConnection(dev, &bluetoothCreateConnection_c, NULL);
printf("in openRFCOMMChannel\n");
CFArrayRef device_services = IOBluetoothDeviceGetServices(dev);
printf("Getting SDP service record\n");
IOBluetoothSDPServiceRecordRef service_record = (IOBluetoothSDPServiceRecordRef) CFArrayGetValueAtIndex(device_services, 0);
UInt8 channel_id;
IOBluetoothRFCOMMChannelRef channel_ref;
printf("Finding channel ID\n");
IOBluetoothSDPServiceRecordGetRFCOMMChannelID(service_record, &channel_id);
// Open channel and listen for RFCOMM data
IOBluetoothDeviceOpenRFCOMMChannelAsync(dev, &channel_ref, channel_id, &rfcommEventListener_c, NULL);
}
Here's the output from the program:
run
[Switching to process 41228]
Running…
in openRFCOMMChannel
2011-06-13 13:44:04.762 test (Debug)[41228:a0f] *** __NSAutoreleaseNoPool(): Object 0x1d27770 of class NSCFArray autoreleased with no pool in place - just leaking
Getting SDP service record
Finding channel ID
Created connection
aOK!
aaOK!
aaOK!
a!()*\251\253\274_BluetoothVersionNumber_PersistentServicesZHIDDevices_SCOAudioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionarya)*\251\253\274_BluetoothVersionNumber_PersistentServicesZHIDDevices_SCOAudioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionarya\251\253\274_BluetoothVersionNumber_PersistentServicesZHIDDevices_SCOAudioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionarya_BluetoothVersionNumber_PersistentServicesZHIDDevices_SCOAudioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryauetoothVersionNumber_PersistentServicesZHIDDevices_SCOAudioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryathVersionNumber_PersistentServicesZHIDDevices_SCOAudioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryasionNumber_PersistentServicesZHIDDevices_SCOAudioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaumber_PersistentServicesZHIDDevices_SCOAudioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionarya_PersistentServicesZHIDDevices_SCOAudioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryarsistentServicesZHIDDevices_SCOAudioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaentServicesZHIDDevices_SCOAudioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryarvicesZHIDDevices_SCOAudioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryasZHIDDevices_SCOAudioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaDevices_SCOAudioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaes_SCOAudioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaSCOAudioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryadioDevices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryavices_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionarya_DaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaemonNoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaoRoleSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaSwitchDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryahDeviceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaceList_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryat_!DaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaaemonControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaControllersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaollersConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryasConfigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaigurationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryationKey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaey_ControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaControllerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaollerPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaPowerState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaState_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionarya_BluetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryauetoothAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryathAutoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaoSeekHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaHIDDevices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryavices_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionarya_PersistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryarsistentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaentPortsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryartsZPANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaANDevices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaices]PairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaPairedDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryadDevices_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaces_PersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaPersistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaistentPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryatPortsServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryasServicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaicesOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryaOMstreamtyped\201\350\204#\204\204\204NSMutableDictionaryastreamtyped\201\350\204#\204\204\204NSMutableDictionaryaamtyped\201\350\204#\204\204\204NSMutableDictionaryaed\201\350\204#\204\204\204NSMutableDictionarya\204#\204\204\204NSMutableDictionarya\204NSMutableDictionaryaaeDictionaryaionaryayaNSDictionaryationaryaryaNSObjectajectaa\206\242a_00-14-51-cc-20-41_00-0a-95-3f-fe-8a\324a0-14-51-cc-20-41_00-0a-95-3f-fe-8a\324a51-cc-20-41_00-0a-95-3f-fe-8a\324a-20-41_00-0a-95-3f-fe-8a\324a1_00-0a-95-3f-fe-8a\324a0-0a-95-3f-fe-8a\324a95-3f-fe-8a\324a-fe-8a\324aa\324a\324aOK!
a\232a00-16-a4-00-17-7e_00-16-a4-00-72-3d_00-23-7f-49-98-a6_00-1a-10-04-13-9a\323a6-a4-00-17-7e_00-16-a4-00-72-3d_00-23-7f-49-98-a6_00-1a-10-04-13-9a\323a00-17-7e_00-16-a4-00-72-3d_00-23-7f-49-98-a6_00-1a-10-04-13-9a\323a-7e_00-16-a4-00-72-3d_00-23-7f-49-98-a6_00-1a-10-04-13-9a\323a00-16-a4-00-72-3d_00-23-7f-49-98-a6_00-1a-10-04-13-9a\323a6-a4-00-72-3d_00-23-7f-49-98-a6_00-1a-10-04-13-9a\323a00-72-3d_00-23-7f-49-98-a6_00-1a-10-04-13-9a\323a-3d_00-23-7f-49-98-a6_00-1a-10-04-13-9a\323a00-23-7f-49-98-a6_00-1a-10-04-13-9a\323a3-7f-49-98-a6_00-1a-10-04-13-9a\323a49-98-a6_00-1a-10-04-13-9a\323a-a6_00-1a-10-04-13-9a\323a00-1a-10-04-13-9a\323aa-10-04-13-9a\323a04-13-9a\323a-9a\323a\323aOK!
aYAgentPathXDriverID_IOAudioControls_W/System/Library/CoreServices/BluetoothAudioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244antPathXDriverID_IOAudioControls_W/System/Library/CoreServices/BluetoothAudioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244ahXDriverID_IOAudioControls_W/System/Library/CoreServices/BluetoothAudioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244averID_IOAudioControls_W/System/Library/CoreServices/BluetoothAudioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244a_IOAudioControls_W/System/Library/CoreServices/BluetoothAudioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244aAudioControls_W/System/Library/CoreServices/BluetoothAudioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244aControls_W/System/Library/CoreServices/BluetoothAudioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244aols_W/System/Library/CoreServices/BluetoothAudioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244aW/System/Library/CoreServices/BluetoothAudioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244atem/Library/CoreServices/BluetoothAudioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244aibrary/CoreServices/BluetoothAudioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244ay/CoreServices/BluetoothAudioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244aeServices/BluetoothAudioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244aices/BluetoothAudioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244aBluetoothAudioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244aoothAudioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244audioAgent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244agent.app/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244aapp/Contents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244aontents/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244ats/MacOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244acOS/BluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244aluetoothAudioAgent_00-16-a4-00-17-7e-SCO\244aothAudioAgent_00-16-a4-00-17-7e-SCO\244adioAgent_00-16-a4-00-17-7e-SCO\244aent_00-16-a4-00-17-7e-SCO\244a00-16-a4-00-17-7e-SCO\244a6-a4-00-17-7e-SCO\244a00-17-7e-SCO\244a-7e-SCO\244aCO\244aOK!
aN\332a\332aOK!
a%aOK!
aaOK!
a.aOK!
aIOAudioControlType_IOAudioControlSubType_IOAudioControlChannelID_IOAudioControlValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaioControlType_IOAudioControlSubType_IOAudioControlChannelID_IOAudioControlValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeatrolType_IOAudioControlSubType_IOAudioControlChannelID_IOAudioControlValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaype_IOAudioControlSubType_IOAudioControlChannelID_IOAudioControlValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaIOAudioControlSubType_IOAudioControlChannelID_IOAudioControlValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeadioControlSubType_IOAudioControlChannelID_IOAudioControlValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeantrolSubType_IOAudioControlChannelID_IOAudioControlValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaSubType_IOAudioControlChannelID_IOAudioControlValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaaIOAudioControlChannelID_IOAudioControlValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaioControlChannelID_IOAudioControlValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeatrolChannelID_IOAudioControlValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeahannelID_IOAudioControlValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmealID_IOAudioControlValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaIOAudioControlValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeadioControlValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeantrolValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaValue_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmea_IOAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaAudioControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaControlChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaolChannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeannelName_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaaaaaaaaaaaaaaaame_IOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaIOAudioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeadioLevelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeavelControlMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeantrolMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaMaxDB_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmea_IOAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaAudioLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaLevelControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaControlMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaolMaxValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaValue_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmea_IOAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaAudioLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaLevelControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaControlMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaolMinValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaValue_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmea_IOAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaAudioLevelControlMinDB_IOAudioControlUsagelevlvlmeaLevelControlMinDB_IOAudioControlUsagelevlvlmeaControlMinDB_IOAudioControlUsagelevlvlmeaolMinDB_IOAudioControlUsagelevlvlmeaaIOAudioControlUsagelevlvlmeaioControlUsagelevlvlmeatrolUsagelevlvlmeasagelevlvlmealevlvlmeavlmeaOK!
Ok, I'm pretty sure I found my problem. The data pointer that I copied over to a char * wasn't 0 terminated. I rewrote this:
const char *data_const = (const char *)event->u.data.dataPtr;
char *dataAsBytes = const_cast<char *>(data_const);
string in_s = (string)dataAsBytes;
To this:
const char *data_const = (const char *)data.dataPtr;
char *dataAsBytes = const_cast<char *>(data_const);
dataAsBytes[data.dataSize] = '\0';
printf("%s %i %i\n", dataAsBytes, data.dataSize);
Related
So I have this winsock application (a server, able to accept multiple clients), where in the main thread I setup the socket and create another thread where I listen for clients (listen_for_clients function).
I also constantly receive data from a device in the main thread, which I afterwards concatenate to char arrays (buffers) of Client objects (BroadcastSample function). Currently I create a thread for each connected client (ProcessClient function), where I initialize a Client object and push it to a global vector of clients after which I send data to this client through the socket whenever the buffer in the corresponding Client object exceeds 4000 characters.
Is there a way I can send data from the main thread to the separate client threads so I don't have to use structs/classes (also to send a green light if I want to send the already accumulated data) and also if I'm going to keep a global container of objects, what is a good way to remove a disconnected client object from it without crashing the program because another thread is using the same container?
struct Client{
int buffer_len;
char current_buffer[5000];
SOCKET s;
};
std::vector<Client*> clientBuffers;
DWORD WINAPI listen_for_clients(LPVOID Param)
{
SOCKET client;
sockaddr_in from;
int fromlen = sizeof(from);
char buf[100];
while(true)
{
client = accept(ListenSocket,(struct sockaddr*)&from,&fromlen);
if(client != INVALID_SOCKET)
{
printf("Client connected\n");
unsigned dwThreadId;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ProcessClient, (void*)client, 0, &dwThreadId);
}
}
closesocket(ListenSocket);
WSACleanup();
ExitThread(0);
}
unsigned __stdcall ProcessClient(void *data)
{
SOCKET ClientSocket = (SOCKET)data;
Client * a = new Client();
a->current_buffer[0] = '\0';
a->buffer_len = 0;
a->s = ClientSocket;
clientBuffers.push_back(a);
char szBuffer[255];
while(true)
{
if(a->buffer_len > 4000)
{
send(ClientSocket,a->current_buffer,sizeof(a->current_buffer),0);
memset(a->current_buffer,0,5000);
a->buffer_len = 0;
a->current_buffer[0] = '\0';
}
}
exit(1);
}
//function below is called only in main thread, about every 100ms
void BroadcastSample(Sample s)
{
for(std::vector<Client*>::iterator it = clientBuffers.begin(); it != clientBuffers.end(); it++)
{
strcat((*it)->current_buffer,s.to_string);
(*it)->buffer_len += strlen(s.to_string);
}
}
This link has some Microsoft documentation on MS-style mutexes (muticies?).
This other link has some general info on mutexes.
Mutexes are the general mechanism for protecting data which is accessed by multiple threads. There are data structures with built-in thread safety, but in my experience, they usually have caveats that you'll eventually miss. That's just my two cents.
Also, for the record, you shouldn't use strcat, but rather strncat. Also, if one of your client servicing threads accesses one of those buffers after strncat overwrites the old '\0' but before it appends the new one, you'll have a buffer overread (read past end of allocated buffer).
Mutexes will also solve your current busy-waiting problem. I'm not currently near a windows compiler, or I'd try to help more.
I am trying JackAudio with c++ on Windows 8.1 and it works.
I am using a simple client code that can be found on the git. This code should send a low pitch signal to one hear and a high pitch signal to the other but for me it sends both signals to both hear.
I don't know what is wrong since two are registered and both get access to the correct speakers.
/** #file simple_client.c
*
* #brief This simple client demonstrates the basic features of JACK
* as they would be used by many applications.
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <signal.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <jack/jack.h>
jack_port_t *output_port1, *output_port2;
jack_client_t *client;
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
typedef struct
{
float sine[TABLE_SIZE];
int left_phase;
int right_phase;
}
paTestData;
static void signal_handler(int sig)
{
jack_client_close(client);
fprintf(stderr, "signal received, exiting ...\n");
exit(0);
}
/**
* The process callback for this JACK application is called in a
* special realtime thread once for each audio cycle.
*
* This client follows a simple rule: when the JACK transport is
* running, copy the input port to the output. When it stops, exit.
*/
int
process(jack_nframes_t nframes, void *arg)
{
jack_default_audio_sample_t *out1, *out2;
paTestData *data = (paTestData*)arg;
int i;
out1 = (jack_default_audio_sample_t*)jack_port_get_buffer(output_port1, nframes);
out2 = (jack_default_audio_sample_t*)jack_port_get_buffer(output_port2, nframes);
for (i = 0; i<nframes; i++)
{
out1[i] = data->sine[data->left_phase]; // left
out2[i] = data->sine[data->right_phase]; // right
data->left_phase += 1;
if (data->left_phase >= TABLE_SIZE) data->left_phase -= TABLE_SIZE;
data->right_phase += 10; // higher pitch so we can distinguish left and right.
if (data->right_phase >= TABLE_SIZE) data->right_phase -= TABLE_SIZE;
}
return 0;
}
/**
* JACK calls this shutdown_callback if the server ever shuts down or
* decides to disconnect the client.
*/
void
jack_shutdown(void *arg)
{
exit(1);
}
int
main(int argc, char *argv[])
{
const char **ports;
const char *client_name;
const char *server_name = NULL;
jack_options_t options = JackNullOption;
jack_status_t status;
paTestData data;
int i;
/*if (argc >= 2) { // client name specified?
client_name = argv[1];
if (argc >= 3) { // server name specified?
server_name = argv[2];
int my_option = JackNullOption | JackServerName;
options = (jack_options_t)my_option;
}
}
else { // use basename of argv[0]
client_name = strrchr(argv[0], '/');
if (client_name == 0) {
client_name = argv[0];
}
else {
client_name++;
}
}*/
client_name = "mytest";
for (i = 0; i<TABLE_SIZE; i++)
{
data.sine[i] = 0.2 * (float)sin(((double)i / (double)TABLE_SIZE) * M_PI * 2.);
}
data.left_phase = data.right_phase = 0;
// open a client connection to the JACK server
client = jack_client_open(client_name, options, &status, server_name);
if (client == NULL) {
fprintf(stderr, "jack_client_open() failed, "
"status = 0x%2.0x\n", status);
if (status & JackServerFailed) {
fprintf(stderr, "Unable to connect to JACK server\n");
}
exit(1);
}
if (status & JackServerStarted) {
fprintf(stderr, "JACK server started\n");
}
if (status & JackNameNotUnique) {
client_name = jack_get_client_name(client);
fprintf(stderr, "unique name `%s' assigned\n", client_name);
}
// tell the JACK server to call `process()' whenever
//there is work to be done.
jack_set_process_callback(client, process, &data);
// tell the JACK server to call `jack_shutdown()' if
//it ever shuts down, either entirely, or if it
//just decides to stop calling us.
jack_on_shutdown(client, jack_shutdown, 0);
// create two ports
output_port1 = jack_port_register(client, "output1",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
output_port2 = jack_port_register(client, "output2",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
if ((output_port1 == NULL) || (output_port2 == NULL)) {
fprintf(stderr, "no more JACK ports available\n");
exit(1);
}
//Tell the JACK server that we are ready to roll. Our
// process() callback will start running now.
if (jack_activate(client)) {
fprintf(stderr, "cannot activate client");
exit(1);
}
// Connect the ports. You can't do this before the client is
// activated, because we can't make connections to clients
// that aren't running. Note the confusing (but necessary)
// orientation of the driver backend ports: playback ports are
// "input" to the backend, and capture ports are "output" from
// it.
ports = jack_get_ports(client, NULL, NULL,
JackPortIsPhysical | JackPortIsInput);
if (ports == NULL) {
fprintf(stderr, "no physical playback ports\n");
exit(1);
}
if (jack_connect(client, jack_port_name(output_port1), ports[0])) {
fprintf(stderr, "cannot connect output ports\n");
}
if (jack_connect(client, jack_port_name(output_port2), ports[1])) {
fprintf(stderr, "cannot connect output ports\n");
}
jack_free(ports);
// install a signal handler to properly quits jack client
#ifdef WIN32
signal(SIGINT, signal_handler);
signal(SIGABRT, signal_handler);
signal(SIGTERM, signal_handler);
#else
signal(SIGQUIT, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
#endif
// keep running until the Ctrl+C
while (1) {
#ifdef WIN32
Sleep(1000);
#else
sleep(1);
#endif
}
jack_client_close(client);
exit(0);
}
Did you ever figure this out? I'm quite new to coding with and configuring Jack myself but my hunch is, the problem is not in the code, rather it's a mixer issue. I suspect there's a setting somewhere that has put the jack server in a mono mode of sorts which would mean all output streams are multed (yes spell checker, multed is a word in the audio engineering world :) ) to all physical audio outputs. So... stream 1 would be connected to the left and right physical output, and stream 2 would also be connected to the physical left and right outputs.
There is nothing anywhere that would necessarily say that stream 1 goes to the left output and stream 2 goes to the right... in fact, if you're running an SDDS configuration the first stream might be the left output, and the 2nd might be the left center... you wouldn't get to the right channel until you hit the 5th stream (with the 2nd, 3rd, and 4th being left center, center, and right center respectively).
Again, this is just a guess but check to see if there's a mixer or "patch bay" style application on your platform that allows you to route streams to physical outputs. In the meantime, I'll give this code a go on my system (Debian unstable/w experimental 4.3 kernel) to see what happens.
Cheers, Joe
Pardon, me - it's an old question, but for the benefit of whoever reads it... I tested this program on my System and found it works correctly!
Question to the original poster: Would you object to having this example included in the JackD example repository (https://github.com/jackaudio/example-clients)? I feel that it's a very good example on how to use the audio streaming part of the JackD API. It would probably need some small rewrite as a generic platform C program; it would be under the same license as the other examples in the JackD example repo (GPL 2). I've sent a mail to the JackD developer's list (jack-devel#lists.jackaudio.org) asking what they think.
Anyway - shewhorn had the correct hunch - nothing wrong with your code, but when you tested your program there was something wrong with the port mappings on your system (i.e. how the ports were mapped to the physical ports on your soundcard). The way to fix it is outside your application: Use some mixer or patch bay style application to route your program's streams correctly. Not your (code's) fault, your program works fine and does what you intended.
I am using an Arduino Due and Visual Studio 2010. I am programming in C/C++. Below you see my programs and after this my explanations of what is going wrong.
This is the really simple code thats on my Arduino. Its sending a lot of A's to the PC.
void setup()
{
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
void loop()
{
Serial.println('A');
delay(1); // delay in between reads for stability
}
The further code for reading the Serial Port I found over here:
http://playground.arduino.cc/Interfacing/CPPWindows
And this is my modified version of this code at the moment:
Header:
#ifndef SERIALCLASS_H_INCLUDED
#define SERIALCLASS_H_INCLUDED
#define ARDUINO_WAIT_TIME 2000
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
class Serial
{
private:
//Serial comm handler
HANDLE hSerial;
//Connection status
bool connected;
//Get various information about the connection
COMSTAT status;
//Keep track of last error
DWORD errors;
public:
//Initialize Serial communication with the given COM port
Serial(char *portName);
//Close the connection
//NOTA: for some reason you can't connect again before exiting
//the program and running it again
~Serial();
//Read data in a buffer, if nbChar is greater than the
//maximum number of bytes available, it will return only the
//bytes available. The function return -1 when nothing could
//be read, the number of bytes actually read.
int ReadData(char *buffer, unsigned int nbChar);
//Writes data from a buffer through the Serial connection
//return true on success.
bool WriteData(char *buffer, unsigned int nbChar);
//Check if we are actually connected
bool IsConnected();
};
#endif // SERIALCLASS_H_INCLUDED
CPP:
#include "stdafx.h"
#include <stdio.h>
#include <tchar.h>
#include "SerialClass.h"
#include <string>
#include <windows.h>
#include <assert.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <conio.h>
using namespace System;
using namespace std;
// Serial::Serial looks, if Serial Connection from PC to the Device is proper and everything is working. Then it sets a few Parameters and waits
Serial::Serial(char *portName)
{
//We're not yet connected
this->connected = false;
//Try to connect to the given port throuh CreateFile
this->hSerial = CreateFileA(portName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
//Check if the connection was successfull
//if not...show error
if(this->hSerial==INVALID_HANDLE_VALUE)
{
//If not success full display an Error
if(GetLastError()==ERROR_FILE_NOT_FOUND){
//Print Error if neccessary
printf("ERROR: Handle was not attached. Reason: %s not available.\n", portName);
Sleep(2000);
}
else
{printf("ERROR!!!");}
}
// else = connection is working, then -> continue
else
{
//If connected we try to set the comm parameters
DCB dcbSerialParams = {0};
//Try to get the current Parameters
if (!GetCommState(this->hSerial, &dcbSerialParams))
{
//If impossible, show an error
printf("failed to get current serial parameters!");
}
else
{
//Define serial connection parameters for the arduino board
dcbSerialParams.BaudRate=CBR_9600;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
//Set the parameters and check for their proper application
if(!SetCommState(hSerial, &dcbSerialParams))
{
printf("ALERT: Could not set Serial Port parameters");
}
else
{
//If everything went fine we're connected
this->connected = true;
//We wait 2s as the arduino board will be reseting
Sleep(ARDUINO_WAIT_TIME);
}
}
}
}
//Has a look if SerialPort is still connected.
//If yes, it disconnects and closes the Serial Handler.
Serial::~Serial()
{
//Check if we are connected before trying to disconnect
if(this->connected)
{
//We're no longer connected
this->connected = false;
//Close the serial handler
CloseHandle(this->hSerial);
}
}
// reads data out of Serial Port
int Serial::ReadData(char *buffer, unsigned int nbChar)
{
//Number of bytes we'll have read
DWORD bytesRead;
//Number of bytes we'll really ask to read
unsigned int toRead;
//Use the ClearCommError function to get status info on the Serial port
ClearCommError(
this->hSerial, // Handle to the communications device, CreateFile Function returns this value
&this->errors, // a pointer to a variable that receives a mask indicating the type of rror
&this->status);// a pointer to a COMSTAT structure in which the devices status information is returned. if this parameter is NULL, no status information is returned
//Check if there is something to read
if(this->status.cbInQue>0) // cbInQue: Number of Bytes received by the Serial provider, but not yet read by a ReadFile operation
{
//If there is we check if there is enough data to read the required number
//of characters, if not we'll read only the available characters to prevent
//locking of the application.
if(this->status.cbInQue>nbChar)
{toRead = nbChar;}
else
{toRead = this->status.cbInQue;}
//Try to read the require number of chars, and return the number of read bytes on success
if(ReadFile(
this->hSerial, // Handle to a device
buffer, // a pointer to the buffer that receives the data read from a file or device
toRead, // NumberofBytesToRead: the maximum number of bytes to be read
&bytesRead, // NumberofBytesRead: a pointer to the variable that receives the number of bytes read when using a synchronours hFile parameter.
NULL) // Overlapped
&& bytesRead // Value of bytesRead after ReadFile function
!= 0)
{return bytesRead;
Sleep(1000);} // returns Value of BytesRead
}
//If nothing has been read, or that an error was detected return -1
return -1;
}
bool Serial::IsConnected() // simply returns connection status
{
//Simply return the connection status
return this->connected;
}
Main:
// application reads from the specified serial port and reports the collected data
int _tmain(int argc, _TCHAR* argv[])
{
printf("Welcome to the serial test app!\n\n");
Serial* SP = new Serial("\\\\.\\COM3"); // adjust as needed
if (SP->IsConnected())
printf("We're connected");
// defines how much Data will be catched
// don't forget to pre-allocate memory
char incomingData[1025] = "";
incomingData[1024]='\0';
int dataLength = 1024; // maximum Length of one DataBit/Word
int readResult = 0;
// gives out the Number! of DataBits that could be collected/catched
readResult = SP->ReadData(incomingData,dataLength);
printf("Bytes read: (-1 means no data available) %i\n",readResult);
// transforms the char incomingData into a String and prints it
std::string test(incomingData);
printf("%s \n", incomingData);
printf("Bytes read: (-1 means no data available) %i\n",readResult);
Sleep(10000);
}
So now here is my problem:
The programm works fine, as long as the Amount of Bits I am sending from the Arduino is less than DataLength. (here = 1024) I got those less bits just through setting the Delay from the Arduino programm quite high (~100ms).
Then I have a console window with an Output similar to this:
A
A
A
A
A
... goes on like this
But if the Arduino sends more than 1024 Bits (Delay ~ 1ms)/ the PC receices more Bits than the Value of DataLength, something in the Serial::ReadData Loop seems to get wrong.
My Console Output is than a little bit corrupted and some Bits look like this:
A
ßA
A A
A
... goes on similar to this.
What is wrong with my program? I thought that it could be, that one parameter of the ReadFile() Function is not right, but I do not know what to change and I am not 100% sure about this.
I am facing issue in passing data between c# and C++ (QT) application through named pipe communication. C# client application connects to NamedPipe server which is in c++ but message is not being parsed correctly on server. Example, I am sending value of short variable = 2 and c++ code parse byte array into unsigned int but value is coming always zero in server. Could you please let me know what I am doing wrong?
Client and server code:
NamedPipe Server code in C++ using QT Library
QLocalSocket *local_socket = _local_server->nextPendingConnection();
if (!local_socket->waitForReadyRead(gft::PROC_TIMEOUT)) {
qDebug() << "gft_plugin: timeout while waiting for data";
return;
}
int bytesavailable = local_socket->bytesAvailable();
QByteArray buffer;
QDataStream in(&buffer, QIODevice::ReadOnly);
buffer.append(local_socket->readAll());
unsigned int msg;
in >> msg;
unsigned int a_id = msg;
NamedPipe Client (C#)
var clientStream = new NamedPipeClientStream("localhost", "gft_plugin_server", PipeDirection.InOut);
clientStream.Connect();
if (clientStream.IsConnected)
{
_stop = false;
UInt16 a_id = 2;
byte[] b = BitConverter.GetBytes(a_id);
clientStream.Write(b, 0, b.Count());
clientStream.Flush();
}
else
{
MessageBox.Show("Could not connected");
}
I am trying to implement an authentication system using C++/QtTcpSocket for a personal project (A Multiplayer Chess Game).
My friend suggested a method for verifying a user but I wanted to ask if there was an easier or better way. Coming from a Python background and mostly doing this project to develop a deeper understanding of C++.
I will post the method my friend suggested and ask for maybe a better solution.
He built it in a kind of pseudo code fashion. The server is mostly built, I am now hoping to implement Authentication
*cheers
void process_packet(PACKET *pkt)
{
switch(pkt->PacketID)
{
case 0: // let's say packet id 0 is the logon packet; packet contents are username and password
{
//let's say packet size is 101 bytes; packet id was already received, so get the other 100 bytes
unsigned char BUFFER[101] = {0}; // i always add an extra byte to the end of the buffer to allow for off-by-one errors ^_^
int result = recv_packet(pkt->cSocket, 100, BUFFER);
if(result <= 0)
return; // connection error; no packet data was received
unsigned char *UserName = BUFFER+0; //+0 is not neccessary, but the username starts at the beginning. just getting the point across.
unsigned char *PassWord = BUFFER+50;
//side note: if we did "unsigned long *blah = BUFFER+4" or something, we would have to make sure the byte order is right. network byte order is BIG ENDIAN
// WINDOWS byte order is LITTLE ENDIAN
result = QueryDatabase("SELECT username, password FROM chess_players WHERE username = '%s'", FILTER_INVALID_CHARS(UserName));
// check result
unsigned char ServerResponse[2] = {0};
if(result['password'] == PassWord)
{
ServerResponse[0] = 1; // packet id will be 1. the next byte can be 1 or 0 to indicate logon success or failure.
ServerResponse[1] = true; // so packet 0x0101 mean logon success, packet 0x0100 means logon failure
send_packet(pkt->cSocket, ServerResponse, 2);
} else {
ServerResponse[0] = 1;
ServerResponse[1] = false;
send_packet(pkt->cSocket, ServerResponse, 2);
}
}
break;
default:
{
// received an unknown packet id; send a packet to the client that indicates an error_status_t
unsigned char *ServerResponse[2] = {0};
ServerResponse[0] = 2; // packet id 2 means server error
ServerResponse[1] = 0; // error code 0 means 'unknown packet id'
send_packet(pkt_cSocket, ServerResponse, 2);
}
break;
}
delete pkt; // must delete pkt, was created with 'new' in get_client_packets()
}
This seems rather C-stylish and not like the Qt way of doing things.
There is no general answer to your question but my suggestions are the following:
Listen to the newConnection() signal of the QTcpServer. Your handler has to call the nextPendingConnection() to get the next client waiting in the queue. The first thing you will do is probably your user authentication.
Once authenticated, you keep the QTcpSocket in your list of active connections.
Take a look at e.g. the fortune client/server examples how to actually write/read packets.
You might also want to look into the stream operators << to serialize your objects. This is much easier and less error prone than the low-level method you posted. ALso, QDataStream will take care of host and network byte orders automatically.
If you have followed the fortune client/server examples, you should have a QTcpServer (Rfserver) with a QThread subclass (Rfdevice, its instance variable is called thread in the following code) that contains a QTcpSocket (listenSocket).
Having said that, in your server class, listen for incoming connections, my setup looks like this:
void Rfserver::incomingConnection(int socketDescriptor){
if(thread){ //if thread exists, there is probably still an open connection
if(thread->listenSocket){//if thread exists and the listenSocket is filled, there is definately an open connection
if(thread->listenSocket->state() == QAbstractSocket::UnconnectedState){
//but alas, it could just be in the unconnected state, if so kill it.
this->disconnect();
thread->terminate();
thread=0;
connected=false;
}//otherwise, do nothing, because the software is happily connected to a device
}
}
if(!thread){ //if no thread exists, we are by no means connected
thread = new rfdevice(socketDescriptor, this); //set up a new thread
//this first connection communicates the string from your socket to the server parent...use it if you want.
connect( thread, SIGNAL(RemoteButton(QString)),this,SLOT(remoteButton(QString)),Qt::BlockingQueuedConnection);
connect( thread, SIGNAL(error(QTcpSocket::SocketError)),this,SLOT(tcpError(QTcpSocket::SocketError)),Qt::AutoConnection);
connect( thread, SIGNAL(finished()), this, SLOT(threadZero())); //I have a threadZero function that deletes all the data then schedules the socket for deletion.
thread->start();
connected=true;
QString *welcome = new QString("Enter your password:\r\n");
echoCommand(welcome); //this is a function you will implement that sends the welcome message to the pending device.
}
}
Okay, so now, when a device tries to connect to the server the device is presented with "Enter your password:\r\n". Your device will respond to this with a password and username perhaps. But the Qt side of things would look like this:
/*
FUNCTION:read
this is a polling runloop that listens for data as long as the socket is connected or connecting. If a
write is ever scheduled, it will be called from this runloop..
*/
void Rfdevice::read(void){
while((listenSocket->state() == QAbstractSocket::ConnectedState) || (listenSocket->state() == QAbstractSocket::ConnectingState)){
//if there is data available to send write it to the socket
if(dataToSend) this->write();
if(listenSocket->waitForReadyRead(50)) readBytes();
//wait for 50ms for data from the device
//if there is ever data available to be read, read it.
}
}
Your device responds with a username/password in the format username---password\r\n. Then the socket does this:
/*
FUNCTION:readBytes
this is like a callback function because it only gets called when there is data available for read.
It basically converts the data to a string.
*/
void Rfdevice::readBytes(void){
QByteArray newData;
newData = listenSocket->readAll();
QString *recieved = new QString(newData);
QStringList userAndPass = recieved.split("---");//this is your delimiter
QString username = userAndPass.at(0);
QString password = userAndPass.at(1);
//NOW, check the username and password vs your SQL or wherever it's saved.
}
The pseudo-code is pretty complete on the particulars. Hopefully you can put it all together! Let me know if you need more code.