Bonjour DNS-SD callback not being called, where's a mistake in my code? - windows

I'm trying to learn how to use Bonjour using this blog article as a reference:
http://marknelson.us/2011/10/25/dns-service-discovery-on-windows/
I've download sample project linked at the bottom of that page, it works like charm. Now I'm trying to reproduce service discovery from scratch in my console application:
#include <iostream>
#include <assert.h>
#include "dns/dns_sd.h"
class CDnsSd
{
public:
bool discoverAsync ();
private:
static void DNSSD_API onDiscoveryFinished (DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
DNSServiceErrorType errorCode, const char *serviceName, const char *regtype,
const char *replyDomain, void *context);
};
bool CDnsSd::discoverAsync()
{
DNSServiceRef client = NULL;
const DNSServiceErrorType err = DNSServiceBrowse( &client, 0, 0, ""_services._dns-sd._udp"", "", onDiscoveryFinished, this );
return err == kDNSServiceErr_NoError;
}
void DNSSD_API CDnsSd::onDiscoveryFinished( DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context )
{
std::cout << __FUNCTION__;
}
void main ()
{
CDnsSd dnsSd;
const bool ret = dnsSd.discoverAsync();
assert(ret);
Sleep(10000000);
}
DNSServiceBrowse returns kDNSServiceErr_NoError, but the callback is never called. What's wrong?

You need a main loop processing Bonjour events. Look at the link you provided carefully. It's there in the "Driving the Callbacks" section.

I had to call the method named DNSServiceProcessResult to make it work for my part.
I hope it helped

Related

callbacks fails when std::bind and std::function used

There are two class server and client. client calls method datas() on server. The server responds to the caller with the datalist using datacallback().
I see compile time error in function clientfun2 when serverobj.datas() is called. Please help to fix it.
#include <iostream>
#include <functional>
#include <memory>
#include <string>
#include <vector>
enum Status { SUCCESS, FAILED, UNKOWN };
typedef std::vector<std::string> datalist;
class server {
public:
typedef std::function<void(int, Status, const datalist&)> Callback;
void datas(int request_id, Callback datacallback) {
datalist data; //here data is inserted and set to caller
std::cout << "Invoked datas method\n";
datacallback(123, SUCCESS, data); // sending back to caller
}
};
class client {
public:
void clientfun1(int req_id, Status status, datalist& datas) {
std::cout << "Invoked clientfun1\n";
}
void clientfun2(server serverobj) {
serverobj.datas(123,
std::bind(&client::clientfun1, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3)); /*Here the error comming pls help to fix */
}
};
int main() {
server serverobj;
client clientobj;
clientobj.clientfun2(serverobj);
}
****Error in text format****
bind.cc: In member function ‘void client::clientfun2(server)’:
bind.cc:30:76: error: no matching function for call to ‘server::datas(int, std::_Bind_helper<false, void (client::*)(int, Status, std::vector<std::__cxx11::basic_string<char> >&), client*, const std::_Placeholder<1>&, const std::_Placeholder<2>&, const std::_Placeholder<3>&>::type)’
std::placeholders::_2, std::placeholders::_3));
^
bind.cc:14:8: note: candidate: void server::datas(int, server::Callback)
void datas(int request_id, Callback datacallback) {
^
bind.cc:14:8: note: no known conversion for argument 2 from ‘std::_Bind_helper<false, void (client::*)(int, Status, std::vector<std::__cxx11::basic_string<char> >&), client*, const std::_Placeholder<1>&, const std::_Placeholder<2>&, const std::_Placeholder<3>&>::type {aka std::_Bind<std::_Mem_fn<void (client::*)(int, Status, std::vector<std::__cxx11::basic_string<char> >&)>(client*, std::_Placeholder<1>, std::_Placeholder<2>, std::_Placeholder<3>)>}’ to ‘server::Callback {aka std::function<void(int, Status, const std::vector<std::__cxx11::basic_string<char> >&)>}’
If we take the std::function and the actual function right next to each other it's easy to see a difference (reformatted to show it better):
// vvvvv
typedef std::function<void(int , Status , const datalist&)> Callback;
void clientfun1( int req_id, Status status, datalist& datas) {
// ^^^^^
Now we can see that for the std::function object the last argument is a reference to a constant datalist, while in the clientfun1 function it's not constant.
That makes the two function types different, leading to your error.

Convert "Tcl_Obj* const objv[]" to "char** argv"

I'm using Tcl 8.6 and I'm trying to do something like this to add functions to the tcl interpreter
Tcl_Interp* interp,
void init() {
interp = Tcl_CreateInterp();
}
void add_tcl_function(char* cmd, function<int(int,char**)> F) {
obj2argv* o2a = new obj2argv;
auto lambda_proc = [&](
ClientData cdata,
Tcl_Interp* interp,
int objc,
Tcl_Obj* const objv[])
{
o2a->set(objc, objv);
F(objc, o2a->get_argv());
};
auto lamba_delete = [&](
delete o2a;
};
Tcl_CreateObjCommand(interp, cmd, lamda_proc, NULL, lamda_delete);
}
What I'm wondering is how to convert "Tcl_Obj* const objv[]" to "char** argv"?
I was thinking about creating a class:
class obj2argv {
obj2argv();
void set(int objc, Tcl_Obj* const objv[]);
char** get_argv();
private:
//...
};
any ideas on how to implement set() and get_argv()?
Is there an easier way to do this?
Thanks.
obj2argv* o2a = new obj2argv;
If you're interfacing a function that's fundamentally working with const char** for arguments, you should register the function with Tcl_CreateCommand and let Tcl handle the mapping to strings for you. It already has all the mechanisms required.
More formally, you are dealing with a gluing function with this signature:
typedef int (Tcl_CmdProc) (ClientData clientData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
The CONST84 should be read as being plain const in all new code, and ClientData is a pointer-sized value that Tcl just hands around and never inspects (same as with your existing code).
If you are going to do the mapping yourself, Tcl_GetString takes a Tcl_Obj* and returns the char* representation of it. The representation should be usually treated as const; it simply isn't formally typed as such for historical reasons.
I wanted to add some more information:
I gave up on using lambda's because when I added capture list it won't convert the lambda to a function pointer for some reason. So I went with the traditional approach (see below). EXCEPT: I still have not idea why the TCL document says
typedef int Tcl_CmdProc(
ClientData clientData,
Tcl_Interp *interp,
int argc,
const char *argv[]);
But the compiler requires this to compile:
typedef int Tcl_CmdProc(
ClientData clientData,
Tcl_Interp *interp,
int argc,
Tcl_Obj* const* argv);
The Code:
int cmd_dispatch(
ClientData clientData,
Tcl_Interp* interp,
int argc,
Tcl_Obj* const* argv)
{
function<int(int,char**)> F = *(function<int(int,char**)>*)clientData;
return F(argc, (char**) argv); // <= CAST DOESN'T SEEM RIGHT
}
void cmd_delete(ClientData clientData)
{
}
void add_tcl_function(const char* cmd, function<int(int,char**)> F) {
Tcl_CreateObjCommand(interp, cmd, cmd_dispatch, (void*)&F, cmd_delete);
}
VERSION 2:
struct cmd_data {
//Tcl_Interp* interp,
function<int(int,char**)> F;
int argc;
char* argv[MAX_ARGS];
};
int cmd_dispatch(
ClientData clientData,
Tcl_Interp* interp,
int argc,
Tcl_Obj* const* objv)
{
auto cmd_data1 = (struct cmd_data*) clientData;
cmd_data1->argc = argc;
for(int i=0; ((i < argc) && (i < MAX_ARGS)); i++) {
cmd_data1->argv[i] = Tcl_GetString(objv[i]);
// Who owns object returned by Tcl_GetString?
// memory leak? or invalid after return from function?
// garbage collected by tcl interp?
}
return cmd_data1->F(argc, cmd_data1->argv);
}
void cmd_delete(ClientData clientData)
{
auto cmd_data1 = (struct cmd_data*) clientData;
if (cmd_data1) {
delete cmd_data1;
}
}
void add_tcl_function(const char* cmd, function<int(int,char**)> F) {
auto cmd_data1 = new struct cmd_data;
cmd_data1->F = F;
Tcl_CreateObjCommand(interp, cmd, cmd_dispatch, (void*)cmd_data1, cmd_delete);
}
void init_tcl_commands() {
auto lambda_hello = [&](int argc ,char** argv) -> int {
cout << "HELLO WORLD!\n";
return 0;
};
tcl_backend::add_tcl_function("hello", lambda_hello);
}

proc_create() example for kernel module

Can someone give me proc_create() example?
Earlier they used create_proc_entry() in the kernel but now they are using proc_create().
This example will create a proc entry which enables reading access. I think you can enable other kinds of access by changing the mode argument passed to the function. I haven't passed a parent directory because there is no need to. The structure file_operations is where you setup your reading and writing callbacks.
struct proc_dir_entry *proc_file_entry;
static const struct file_operations proc_file_fops = {
.owner = THIS_MODULE,
.open = open_callback,
.read = read_callback,
};
int __init init_module(void){
proc_file_entry = proc_create("proc_file_name", 0, NULL, &proc_file_fops);
if(proc_file_entry == NULL)
return -ENOMEM;
return 0;
}
You can check this example for more details: https://www.linux.com/learn/linux-training/37985-the-kernel-newbie-corner-kernel-debugging-using-proc-qsequenceq-files-part-1
Here is a 'hello_proc' code, which makes use of the newer 'proc_create()' interface.
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
static int hello_proc_show(struct seq_file *m, void *v) {
seq_printf(m, "Hello proc!\n");
return 0;
}
static int hello_proc_open(struct inode *inode, struct file *file) {
return single_open(file, hello_proc_show, NULL);
}
static const struct file_operations hello_proc_fops = {
.owner = THIS_MODULE,
.open = hello_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int __init hello_proc_init(void) {
proc_create("hello_proc", 0, NULL, &hello_proc_fops);
return 0;
}
static void __exit hello_proc_exit(void) {
remove_proc_entry("hello_proc", NULL);
}
MODULE_LICENSE("GPL");
module_init(hello_proc_init);
module_exit(hello_proc_exit);
This code has been taken from http://pointer-overloading.blogspot.com/2013/09/linux-creating-entry-in-proc-file.html
This reply is just an update to #Alhaad Gokhale's great answer. The hello world module, as of kernels > 5.6 looks like this:
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
static int hello_proc_show(struct seq_file *m, void *v) {
seq_printf(m, "Hello proc!\n");
return 0;
}
static int hello_proc_open(struct inode *inode, struct file *file) {
return single_open(file, hello_proc_show, NULL);
}
static const struct proc_ops hello_proc_fops = {
.proc_open = hello_proc_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
static int __init hello_proc_init(void) {
proc_create("hello_proc", 0, NULL, &hello_proc_fops);
return 0;
}
static void __exit hello_proc_exit(void) {
remove_proc_entry("hello_proc", NULL);
}
MODULE_LICENSE("GPL");
module_init(hello_proc_init);
module_exit(hello_proc_exit);
Key differences to note are:
struct proc_ops replaces struct file_operations.
member name changes from .open, .read to .proc_open, .proc_read...
Need to remove the .owner line.
Further information:
This patch
This more detailed SO answer on changes.

The value of ESP was not properly saved.... and C/C++ calling conventions

I am writing an application using the OpenCV libraries, the Boost libraries and a pieve of code that I have downloaded from this LINK. I have created a project under the same solution with Thunk32 and I have the following files:
MainProject.cpp
#include "stdafx.h"
int main( int argc, char** argv )
{
IplImage *img = cvLoadImage( "C:/Users/Nicolas/Documents/Visual Studio 2010/Projects/OpenCV_HelloWorld/Debug/gorilla.jpg" );
Window::WindowType1 *win = new Window::WindowType1("Something");
cvNamedWindow( "window", CV_WINDOW_AUTOSIZE );
cvShowImage( "window", img );
cvSetMouseCallback( "oonga", (CvMouseCallback)win->simpleCallbackThunk.getCallback(), NULL );
while( true )
{
int c = waitKey( 10 );
if( ( char )c == 27 )
{ break; }
}
return 0;
}
Window.h
class Window {
public:
Window();
virtual ~Window();
//virtual void mouseHandler( int event, int x, int y, int flags, void *param );
private:
void assignMouseHandler( CvMouseCallback mouseHandler );
class WindowWithCropMaxSquare;
class WindowWithCropSelection;
class WindowWithoutCrop;
public:
typedef WindowWithCropMaxSquare WindowType1;
typedef WindowWithCropSelection WindowType2;
typedef WindowWithoutCrop WindowType3;
protected:
};
class Window::WindowWithCropMaxSquare : public Window {
public:
indev::Thunk32<WindowType1, void _cdecl ( int, int, int, int, void* )> simpleCallbackThunk;
WindowWithCropMaxSquare( char* name );
~WindowWithCropMaxSquare();
void _cdecl mouseHandler( int event, int x, int y, int flags, void *param );
private:
protected:
};
and Window.cpp
#include "stdafx.h"
Window::Window()
{
}
Window::~Window()
{
}
void Window::assignMouseHandler( CvMouseCallback mouseHandler )
{
}
Window::WindowWithCropMaxSquare::WindowWithCropMaxSquare( char* name )
{
simpleCallbackThunk.initializeThunk(this, &Window::WindowWithCropMaxSquare::mouseHandler); // May throw std::exception
}
Window::WindowWithCropMaxSquare::~WindowWithCropMaxSquare()
{
}
void _cdecl Window::WindowWithCropMaxSquare::mouseHandler( int event, int x, int y, int flags, void *param )
{
printf("entered mousehandler");
}
Now, when I run this, If I don't move the mouse inside the window, it's ok and the callback has been successfully passed to the cvSetMouseCallback function. The cvSetMouseCallback function has three parameters 1. the name of the window, 2. the CvMouseCallback and the NULL character. The CvMouseCallback is defined as
typedef void (CV_CDECL *CvMouseCallback )(int event, int x, int y, int flags, void* param);
and the CV_CDECL is just a redefinition of the _cdecl calling convention.
#define CV_CDECL __cdecl
Now, my mouseHandler function is a class member function, which I assume conforms to the _thiscall calling convention.
My question is, why do I get the following error just when I put my mouse on the window, if it has managed to get into the method at least once? I guess there's a change the second moment my mouse moves within the windoow. Can anyone help me please?
Here's an image with what I am doing:
That thunk code uses the __stdcall convention, not __cdecl. In this case, since cvSetMouseCallback takes a void* which it passes through to the callback, I would recommend that you use a static callback function and use this data pointer to pass the this pointer. You may then put your logic in this static function or else just call an instance version of the callback using the pointer that was passed in.
class Window {
public:
void _cdecl staticMouseHandler( int event, int x, int y, int flags, void *param ) {
((MouseHandler*)param)->mouseHandler(event, x, y, flags, NULL);
}
// ...
}
// ...
cvSetMouseCallback( "oonga", &Window::staticMouseHandler, win );

boost::asio tcp async_read never returns

I am trying to convert some existing code to use boost's asio tcp sockets instead of our current implementation. I am able to get a very similar example (of a chat client/server) from the boost site working, but when I attempt to put the code into my own program it stops working.
What I am doing:
Start a server process
The server process makes an empty socket and uses it to listen (with a tcp::acceptor) for TCP connections on a port (10010 for example)
Start a client process
Have the client process create a socket connect to the server's port
When the server sees a client is connecting, it starts listening for data(with async_read) on the socket and creates another empty socket to listen for another TCP connection on the port
When the client sees that the server has connected, it sends 100 bytes of data (with async_write) and waits for the socket to tell it the send is finished...when that happens it prints a message and shuts down
When the server gets notified that its has data that has been read, it prints a message and shuts down
Obviously, I have greatly trimmed this code down from what I'm trying to implement, this is as small as I could make something that reproduces the problem. I'm running on windows and have a visual studio solution file you can get. There's some memory leaks, thread safety problems, and such, but that's because I'm taking stuff out of existing code, so don't worry about them.
Anyway, here's the files one header with some common stuff, a server, and a client.
Connection.hpp:
#ifndef CONNECTION_HPP
#define CONNECTION_HPP
#include
#include
#include
class ConnectionTransfer
{
public:
ConnectionTransfer(char* buffer, unsigned int size) :
buffer_(buffer), size_(size) {
}
virtual ~ConnectionTransfer(void){}
char* GetBuffer(){return buffer_;}
unsigned int GetSize(){return size_;}
virtual void CallbackForFinished() = 0;
protected:
char* buffer_;
unsigned int size_;
};
class ConnectionTransferInProgress
{
public:
ConnectionTransferInProgress(ConnectionTransfer* ct):
ct_(ct)
{}
~ConnectionTransferInProgress(void){}
void operator()(const boost::system::error_code& error){Other(error);}
void Other(const boost::system::error_code& error){
if(!error)
ct_->CallbackForFinished();
}
private:
ConnectionTransfer* ct_;
};
class Connection
{
public:
Connection(boost::asio::io_service& io_service):
sock_(io_service)
{}
~Connection(void){}
void AsyncSend(ConnectionTransfer* ct){
ConnectionTransferInProgress tip(ct);
//sock_->async_send(boost::asio::buffer(ct->GetBuffer(),
// static_cast(ct->GetSize())), tip);
boost::asio::async_write(sock_, boost::asio::buffer(ct->GetBuffer(),
static_cast(ct->GetSize())), boost::bind(
&ConnectionTransferInProgress::Other, tip, boost::asio::placeholders::error));
}
void AsyncReceive(ConnectionTransfer* ct){
ConnectionTransferInProgress tip(ct);
//sock_->async_receive(boost::asio::buffer(ct->GetBuffer(),
// static_cast(ct->GetSize())), tip);
boost::asio::async_read(sock_, boost::asio::buffer(ct->GetBuffer(),
static_cast(ct->GetSize())), boost::bind(
&ConnectionTransferInProgress::Other, tip, boost::asio::placeholders::error));
}
boost::asio::ip::tcp::socket& GetSocket(){return sock_;}
private:
boost::asio::ip::tcp::socket sock_;
};
#endif //CONNECTION_HPP
BoostConnectionClient.cpp:
#include "Connection.hpp"
#include
#include
#include
#include
using namespace boost::asio::ip;
bool connected;
bool gotTransfer;
class FakeTransfer : public ConnectionTransfer
{
public:
FakeTransfer(char* buffer, unsigned int size) : ConnectionTransfer(buffer, size)
{
}
void CallbackForFinished()
{
gotTransfer = true;
}
};
void ConnectHandler(const boost::system::error_code& error)
{
if(!error)
connected = true;
}
int main(int argc, char* argv[])
{
connected = false;
gotTransfer = false;
boost::asio::io_service io_service;
Connection* conn = new Connection(io_service);
tcp::endpoint ep(address::from_string("127.0.0.1"), 10011);
conn->GetSocket().async_connect(ep, ConnectHandler);
boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));
while(!connected)
{
boost::this_thread::sleep(boost::posix_time::millisec(1));
}
std::cout (angle brackets here) "Connected\n";
char data[100];
FakeTransfer* ft = new FakeTransfer(data, 100);
conn->AsyncReceive(ft);
while(!gotTransfer)
{
boost::this_thread::sleep(boost::posix_time::millisec(1));
}
std::cout (angle brackets here) "Done\n";
return 0;
}
BoostConnectionServer.cpp:
#include "Connection.hpp"
#include
#include
#include
#include
using namespace boost::asio::ip;
Connection* conn1;
bool conn1Done;
bool gotTransfer;
Connection* conn2;
class FakeAcceptor
{
public:
FakeAcceptor(boost::asio::io_service& io_service, const tcp::endpoint& endpoint)
:
io_service_(io_service),
acceptor_(io_service, endpoint)
{
conn1 = new Connection(io_service_);
acceptor_.async_accept(conn1->GetSocket(),
boost::bind(&FakeAcceptor::HandleAccept, this, conn1,
boost::asio::placeholders::error));
}
void HandleAccept(Connection* conn, const boost::system::error_code& error)
{
if(conn == conn1)
conn1Done = true;
conn2 = new Connection(io_service_);
acceptor_.async_accept(conn2->GetSocket(),
boost::bind(&FakeAcceptor::HandleAccept, this, conn2,
boost::asio::placeholders::error));
}
boost::asio::io_service& io_service_;
tcp::acceptor acceptor_;
};
class FakeTransfer : public ConnectionTransfer
{
public:
FakeTransfer(char* buffer, unsigned int size) : ConnectionTransfer(buffer, size)
{
}
void CallbackForFinished()
{
gotTransfer = true;
}
};
int main(int argc, char* argv[])
{
boost::asio::io_service io_service;
conn1Done = false;
gotTransfer = false;
tcp::endpoint endpoint(tcp::v4(), 10011);
FakeAcceptor fa(io_service, endpoint);
boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));
while(!conn1Done)
{
boost::this_thread::sleep(boost::posix_time::millisec(1));
}
std::cout (angle brackets here) "Accepted incoming connection\n";
char data[100];
FakeTransfer* ft = new FakeTransfer(data, 100);
conn1->AsyncReceive(ft);
while(!gotTransfer)
{
boost::this_thread::sleep(boost::posix_time::millisec(1));
}
std::cout (angle brackets here) "Success!\n";
return 0;
}
I've searched around a bit, but haven't had much luck. As far as I can tell, I'm almost exactly matching the sample, so it must be something small that I'm overlooking.
Thanks!
In your client code, your ConnectHandler() callback function just sets a value and then returns, without posting any more work to the io_service. At that point, that async_connect() operation is the only work associated with the io_service; so when ConnectHandler() returns, there is no more work associated with the io_service. Thus the background thread's call to io_service.run() returns, and the thread exits.
One potential option would be to call conn->AsyncReceive() from within ConnectHandler(), so that the async_read() gets called prior to the ConnectHandler() returning and thus the background thread's call to io_service.run() won't return.
Another option, the more trivial one, would be to instantiate an io_service::work instance prior to creating your thread to call io_service::run (technically, you could do this at any point prior to the io_service.run() call's returning):
...
// some point in the main() method, prior to creating the background thread
boost::asio::io_service::work work(io_service)
...
This is documented in the io_service documentation:
Stopping the io_service from running out of work
Some applications may need to prevent an io_service object's run() call from returning when there is no more work to do. For example, the io_service may be being run in a background thread that is launched prior to the application's asynchronous operations. The run() call may be kept running by creating an object of type io_service::work:
http://www.boost.org/doc/libs/1_43_0/doc/html/boost_asio/reference/io_service.html

Resources