Multipart messages passing in ZMQ - c++

I am trying to do a multipart message passing in ZeroMQ. More specifically, I want to pass an int followed by a pointer to a vector vector<T>*. I came up with the following code:
zmq::zmq_msg_t msg1;
zmq::zmq_msg_init_data ( &msg1, i, sizeof( i ), NULL, NULL );
zmq::zmq_send ( publisher_, &msg, ZMQ_SNDMORE );
zmq::zmq_msg_t msg2;
zmq::zmq_msg_init_data ptr, sizeof( ptr ), NULL, NULL );
zmq::zmq_send ( s, &msg, 0 );
I am not sure if this will work since it seems that the data parameter in the zmq_send method is of type void* and I am sending just a value.
Also, can anyone tell me how do I separately receive these two messages on the other side? Zero-copy and Multi-part Messages only shows how to get the messages when the number of messages to get is unknown. But in my case it is two. Is there an easier way to do this?

Related

(Windows HID API) HidD_GetPreparsedData() failing in WM_INPUT message handler due to incorrect handle?

I am trying to write custom handling for an Apple Magic Trackpad 2 (ultimately any Windows Precision Touchpad) into a Windows Desktop application. I am using this project as a guide, as it accomplishes similar goals. I am at the point where I have registered the HID touchpad, and am able to receive WM_INPUT messages, which I am handling in the code below. Note, I did have to download open-source drivers in order for the touchpad to work correctly and trigger WM_INPUT messages.
afx_msg void CSimulatorWnd::OnRawInput( UINT nInputCode, HRAWINPUT hRawInput )
{
/*----------------------------------------------------------
Local variables
----------------------------------------------------------*/
HIDP_CAPS hid_capabilities;
UINT data_size = 0;
PHIDP_PREPARSED_DATA preparsed_data = NULL; // allocated by HidD_GetPreparsedData
PRAWINPUT raw_data_buffer = NULL;
RAWINPUTDEVICELIST * connected_devices = NULL;
// add vars that need to be de-allocated here
#define free_and_return() free( raw_data_buffer ); \
if( preparsed_data ){ HidD_FreePreparsedData( preparsed_data ); } \
return;
// get the required raw data size (returns 0 if successful)
if( GetRawInputData( hRawInput, RID_INPUT, NULL, &data_size, sizeof( RAWINPUTHEADER ) ) != 0
|| data_size == 0 )
{
free_and_return();
}
// allocate space in the input data buffer
raw_data_buffer = (RAWINPUT *)malloc( data_size );
// get the raw data (returns the required buffer size from above if successful)
if( GetRawInputData( hRawInput, RID_INPUT, raw_data_buffer, &data_size, sizeof( RAWINPUTHEADER ) ) != data_size )
{
free_and_return();
}
// only handle registered HIDs
if( raw_data_buffer->header.dwType != RIM_TYPEHID )
{
free_and_return();
}
// get pre-parsed HID data. need this structure
if( !HidD_GetPreparsedData( raw_data_buffer->header.hDevice, &preparsed_data ) )
{
// NOTE: raw_data_buffer->header.hDevice = 0x000000004ddd0ce9,
// returning a ERROR_INVALID_HANDLE for some reason.
//
// Below is the information for the HID I registered.
// The handle is correct. The printout below was from
// enumerating over available devices from GetRawInputDeviceList()
// and the output from GetRawInputDeviceInfo()
//
// *********** HID INFO ***********
// HNDL: 000000004DDD0CE9
// Product ID: 613
// Vendor ID: 35088
// Version Number: 1
// Usage Page: 0X0000000D
// Usage: 0X00000005
// ********************************
DWORD error = GetLastError();
free_and_return();
}
// get multi-touch HID capabilities and data
// https://learn.microsoft.com/en-us/windows-hardware/design/component-guidelines/supporting-usages-in-multitouch-digitizer-drivers
HidP_GetCaps( preparsed_data, &hid_capabilities );
// free dynamically allocated memory
free_and_return();
} /* CSimulatorWnd::OnRawInput() */
Right now, I am at the stage of trying to use the hidpi.h API calls to get raw x, y, contact, etc. data. In order to access any of this, I need preparsed data output by HidD_GetPreparsedData(). Unfortunately, that function is failing, and returning an error code stating the provided handle (from the raw data) is wrong.
Am I missing something? As I commented, the handle I'm passing in looks correct, matching that of the device I registered.
I fixed it! I am not sure as to why I couldn't use HidD_GetPreparsedData(), but getting the data with GetRawInputDeviceInfo(), using the RIDI_PREPARSEDDATA param, worked just fine.
RAWINPUTHEADER.hDevice handle is not usable with HidD_GetPreparsedData() API. This handle could be used only with GetRawInputDeviceInfo() (as you already found).
To use HidD_GetPreparsedData() and other HIDClass support routines you need:
Get HID device file name via ::GetRawInputDeviceInfo(raw_data_buffer->header.hDevice, RIDI_DEVICENAME, ..) call.
Open device file via ::CreateFile(device_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, nullptr, nullptr) call to get a real HIDs device_handle.
Now you can use HidD_GetPreparsedData().
Also you can use WriteFile API on that handle to send output reports to a HID collection. Details are here and here.

Connect with an already created named pipe with boost

I'm looking in to using third party libraries for IPC communication using named pipes on Windows. I've been using the Win32 API for this for the last few years. I was interested in replacing my implementation with a tried and true open source library.
I noticed that boost::process has an implementation of an async_pipe which would allow me to use it with boost::asio which would be really helpful for my application.
What I'm trying to do is create the named pipe on the server, which is a C# application.
Once the pipe has been created, connect to it with a client using the boost::process::async_pipe.
The problem I'm having is I don't see an API in boost::process that would allow me to connect with an already created named pipe. The constructors for async_pipe create the pipe instead of connecting to an already created pipe.
Below is the code I'm currently using in the client which is erroneously creating the pipe
boost::asio::io_context ctx;
std::vector<char> buffer( 8196, 0 );
boost::process::async_pipe pipe{ ctx, R"(\\.\pipe\TestPipe)" };
boost::asio::async_read( pipe, boost::asio::buffer( buffer ),
[ &buffer ]( const boost::system::error_code& ec, std::size_t size )
{
if ( ec )
std::cout << "Error: " << ec.message( ) << '\n';
else
{
std::string message{ std::begin( buffer ), std::begin( buffer ) + size };
std::cout << "Received message: " << message << '\n';
}
} );
ctx.run( );
I'm unsure if I can use boost::process to achieve what I want. I'm wondering if there is a way I could use CreateFileW to connect with the named pipe and then pass the HANDLE to async_pipe but I haven't found any documentation regarding that.
Question
How can I connect with an already created named pipe using boost
OK, so I was going about it the wrong way.
After reading this issue on Github Link I realized I needed to use a stream_handle instead. Note, the pipe must be opened in OVERLAPPED mode for this to work.
Creating the stream_handle
static boost::asio::windows::stream_handle OpenPipe( io_context& context )
{
constexpr const wchar_t* pipeName{ LR"(\\.\pipe\TestPipe)" };
return { context, CreateFileW( pipeName,
GENERIC_READ | GENERIC_WRITE,
0, nullptr,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
nullptr ) };
}
Once the stream_handle is created you can use the async functions it provides for communication.
Using the stream_handle
std::vector<char> buffer( 8196, 0 );
pipe.async_read_some( boost::asio::buffer( buffer ),
[ &buffer ]( auto ec, auto size ) { } );

ZeroMQ with NORM - address already in use error was thrown on 2nd .bind() - why?

I'm using ZeroMQ with NACK-Oriented Reliable Multicast ( NORM ) norm:// protocol. The documentation contains only a Python code, so here is my C++ code:
PUB Sender :
string sendHost = "norm://2,127.0.0.1:5556";// <NormNodeId>,<addr:port>
string tag = "MyTag";
string sentMessage = "HelloWorld";
string fullMessage = tag + sentMessage;
zmq::context_t *context = new zmq::context_t( 20 );
zmq::socket_t publisher( *context, ZMQ_PUB );
zmq_connect( publisher, sendHost.c_str() );
zmq_send( publisher,
fullMessage.c_str(),
fullMessage.size(),
0
);
SUB Receiver :
char message[256];
string receiveHost = "norm://1,127.0.0.1:5556";// <NormNodeId>,<addr:port>
string tag = "MyTag";
zmq::context_t *context = new zmq::context_t( 20 );
zmq::socket_t subscriber( *context, ZMQ_SUB );
zmq_bind( subscriber, receiveHost.c_str() );
zmq_setsockopt( subscriber, ZMQ_SUBSCRIBE, tag.c_str(), tag.size() );
zmq_recv( subscriber,
message,
256,
0
);
cout << bytesReceived << endl;
cout << message << endl;
The problem I'm facing is that according to the documentation both .bind() and .connect() are interchangeable.
In my case they both do a .bind(), which causes ZeroMQ to throw an error saying the second bind fails, due to address already in use error.
... they both do a bind, which causes ZeroMQ to throw an error saying the second bind fails
Yes, this is a correct state to fail.
The first .bind() "takes ownership" of the port and this is an exclusive role.
The interchangeability of { .bind() | .connect() } is to be understood so that it does not matter which side .bind()-s and which one .connect()-s.
Until this moment, I saw no one interpreting this property in such a manner, that both sides would try to .connect() ( a non-existent .bind()-(not)-exposed Access Point ), the less to try to .bind() an already "occupied" port ( in case of residing on the same localhost ), or to remain in a nox-et-solitudo state, for the cases that either of the .bind()-s establishes such a .connect()-ready state on both ports on different localhost-s, which both after that remain in a silent solitude ( forever ), as there is ( and will be ) no attempt to make any .connect()-ion going live and operational.
No, you need just 1 .bind(), that may since that moment handle 0+ future .connect()-requests, arriving to establish a live-channel PUB/SUB, for any respective <transport-class> protocol, including the newly added norm://.
Anyways, welcome norm:// to the Family of ZeroMQ protocols.
Confused ?
May enjoy a further 5-seconds read
about the main conceptual differences in [ ZeroMQ hierarchy in less than a five seconds ] or other posts and discussions here.

Libevent writes to the socket only after second buffer_write

Libevent is great and I love it so far. However, on a echo server, the write only sends to the socket on a second write. My writing is from another thread, a pump thread that talks to a db and does some minimal data massaging.
I verified this by setting up a callback for the write:
bufferevent_setcb( GetBufferEvent(), DataAvailable, DataWritten, HandleSocketError, this );
calling bufferevent_flush( m_bufferEvent, EV_READ|EV_WRITE, BEV_NORMAL ) doesn't seem to have any effect.
Here is the setup, just in case I blew it somewhere. I have dramatically simplified the overhead in my code base in order to obtain some help. This includes initialization of sockets, my thread init, etc. This is a multi-threaded app, so there may be some problem there. I start with this:
m_LibEventInstance = event_base_new();
evthread_use_windows_threads();
m_listener = evconnlistener_new_bind( m_LibEventInstance,
OnAccept,
this,
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_CLOSE_ON_EXEC | LEV_OPT_REUSEABLE,
-1,// no maximum number of backlog connections
(struct sockaddr*)&ListenAddress, socketSize );
if (!m_listener) {
perror("Couldn't create listener");
return false;
}
evconnlistener_set_error_cb( m_listener, OnSystemError );
AFAIK, this is copy and paste from samples so it should work. My OnAccept does the following:
void OnAccept( evconnlistener* listenerObj, evutil_socket_t newConnectionId, sockaddr* ClientAddr, int socklen, void* context )
{
// We got a new connection! Set up a bufferevent for it.
struct event_base* base = evconnlistener_get_base( listenerObj );
struct bufferevent* bufferEvent = bufferevent_socket_new( base, newConnectionId, BEV_OPT_CLOSE_ON_FREE );
bufferevent_setcb( GetBufferEvent(), DataAvailable, DataWritten,
HandleSocketError, this );
// We have to enable it before our callbacks will be called.
bufferevent_enable( GetBufferEvent(), EV_READ | EV_WRITE );
DisableNagle( m_connectionId );
}
Now, I simply respond to data coming in and store it in a buffer for later processing. This is a multi-threaded application, so I will process the data later, massage it, or return a response to the client.
void DataAvailable( struct bufferevent* bufferEventObj, void* arg )
{
const U32 MaxBufferSize = 8192;
MyObj* This = (MyObj*) arg;
U8 data[ MaxBufferSize ];
size_t numBytesreceived;
/* Read 8k at a time and send it to all connected clients. */
while( 1 )
{
numBytesreceived = bufferevent_read( bufferEventObj, data, sizeof( data ) );
if( numBytesreceived <= 0 ) // nothing to send
{
break;
}
if( This )
{
This->OnDataReceived( data, numBytesreceived );
}
}
}
the last thing that happens, once I look up my data, package into a buffer, and then on a threaded timeslice I do this:
bufferevent_write( m_bufferEvent, buffer, bufferOffset );
It never, ever sends the first time. To get it to send, I have to send a second buffer full of data.
This behavior is killing me and I have spent a lot of hours on it. Any ideas?
//-------------------------------------------------------
I finally gave up and used this hack instead... there just was not enough info to tell me why libevent wasn't writing to the socket. This works just fine.
int result = send( m_connectionId, (const char* )buffer, bufferOffset, 0 );
I met the problem, too! I spent one day on this problem. At last, I solved it.
When the thread you call event_base_dispatch, it will be asleep until any semaphore wakes it up. So, when it sleeps, you call bufferevent_write, the bufferevent's fd adds to the event list, but it won't be epoll until next time. So you must send semaphore to wake up the dispatch thread after you called bufferevent_write. The way you can use is set up an event bind pair socket and add it to event_base. Then send 1 byte anytime when you need to wake up the disptach thread.

Problem using MIDI streams in Windows

I'm writing a Windows program using C++ and the Windows API, and, am trying to queue MIDI messages in a MIDI stream, but am receiving a strange error when I try to do so. If I use midiOutShortMsg to send a non-queued MIDI message to the stream, it works correctly. However, midiStreamOut always returns error code 68, which is #defined to MCIERR_WAVE_OUTPUTUNSPECIFIED. midiOutGetErrorText gives the following description of the error:
The current MIDI Mapper setup refers to a MIDI device that is not installed on the system. Use MIDI Mapper to edit the setup.
I am using Windows 7 (64-bit) and have tried opening the MIDI stream with device IDs of both MIDI_MAPPER and all four MIDI output devices on my system, and still receive the exact same error message.
Here is the code to open the MIDI stream:
UINT device_id = MIDI_MAPPER; //Also tried 0, 1, 2 and 3
midiStreamOpen( &midi, &device_id, 1, ( DWORD_PTR )hwnd, 0, CALLBACK_WINDOW );
Here is the code to send the MIDI message:
MIDIHDR header;
MIDIEVENT *event;
event = ( MIDIEVENT * )malloc( sizeof( *event ) );
event->dwDeltaTime = delta_time;
event->dwStreamID = 0;
event->dwEvent = ( MEVT_F_SHORT | MEVT_SHORTMSG ) << 24 | ( msg & 0x00FFFFFF );
header.lpData = ( LPSTR )event;
header.dwBufferLength = sizeof( *event );
header.dwBytesRecorded = sizeof( *event );
header.dwUser = 0;
header.dwFlags = 0;
header.dwOffset = 0;
midiOutPrepareHeader( ( HMIDIOUT )midi, &header, sizeof( header ) );
midiStreamOut( midi, &header, sizeof( header ) );
How can I resolve this problem?
The problem was that I was using the entire event structure as the buffer for the MIDI stream. It turns out that the fourth member of the structure, dwParms, should actually be omitted from short messages. To correct the code in the posted question, two of the lines of code could be changed to the following:
header.dwBufferLength = sizeof( *event ) - sizeof( event->dwParms );
header.dwBytesRecorded = sizeof( *event ) - sizeof( event->dwParms );
When adding multiple events to the stream, it's actually a lot easier to just use an array of DWORDs rather than even bothering with the MIDIEVENT structures.
For anyone else doing MIDI programming using the Windows API, beware that some of the MSDN documentation is misleading, inadequate or completely wrong.
The documentation for the MIDIEVENT structure says the following:
dwParms
If dwEvent specifies MEVT_F_SHORT, do not use this member in the stream buffer.
This is ambiguous because it is not clear that "use" is intended to mean "include" rather than "specify".
Here are two other flaws in the documentation that programmers need to be aware of:
dwEvent
Event code and event parameters or length. [...] The high byte of this member contains flags and an event code. Either the MEVT_F_LONG or MEVT_F_SHORT flag must be specified. The MEVT_F_CALLBACK flag is optional.
When the header files are checked, the MEVT_F_ preprocessor definitions actually specify complete DWORDs rather than just the individual flags, so in my code in the question, the line specifying this member should have been as follows:
event->dwEvent = MEVT_F_SHORT | MEVT_SHORTMSG << 24 | ( msg & 0x00FFFFFF );
In addition to this, it has also turned out that the memory containing the MIDIHDR structure should be retained until the buffer has finished playing, so it should be allocated on the heap rather than the stack for most implementations.