[NativeMessaging] Unable to send json response from C app to WebExtension

Hi,

I’m currentlty migrating a legacy addon to new WebExtension design.
We are using native messaging towards an application written in C.
I started my project from the ‘ping pong’ example from GitHub.
I replaced the Python script by our C application.

I have no problem to get message from WebExtension -> C app.
The problem arises when sending back response from C app to WebExtension.

Actually when testing, I see in the console ‘Sending: ping’ but not ‘Received: pong’

Here is the snippet code of C application for response:

========== Code ====================

char responseBuf[64] = { 0 };
unsigned int responseLen;


/* sending json response to the WebExtension */
strcpy(responseBuf, ““pong””);

responseLen = strlen(responseBuf);
fwrite(&responseLen, 1, 4, stdout);
fwrite(responseBuf, 1, responseLen, stdout);
fflush(stdout);

May I missed something on response making ?

Any help would be appreciated, because I have been stuck for days on this problem.

Thanks.

Writing the length:

fwrite(reinterpret_cast<char*>(&data), sizeof(uint32_t), 1, stdout)

So change fwrite(&responseLen, 1, 4, stdout); to fwrite(&responseLen, 4, 1, stdout);

The 4 in place of the 1, and 1 in place of the 4.

Hi noitidart

Thanks for your fast reply.

In fact,

The C program is blocked when retrieving the incoming message.

Here is the code:

/** Reading incoming message from WebExtension via stdin ***/
while (carac = fgetc(stdin), !feof(stdin))
{
if ((char)carac != ‘\r’ && (char)carac != ‘\n’) {
sprintf(szTraceInfo, “cnt: %d, ascii: %d, carac: ‘%c’”, cnt, carac, carac);
trace_line(szTraceInfo);
cnt++;
}
else {
break;
}
}

sprintf(szTraceInfo, “About to sleep for: %d ms.”, 2500);
trace_line(szTraceInfo);
sys_Sleep(2500);

In the log file generated I never see: ‘About to sleep for …’

I will search in this direction

If you need some place to check, this is how I do things, C++:

#include <iostream>
#include <fstream>
#include <string>

// logging
template <typename T> bool debug_log(T s) {
	// 
	return true;
}

// messaging
bool read_u32(uint32_t* data) {
	return std::fread(reinterpret_cast<char*>(data), sizeof(uint32_t), 1, stdin) == 1;
}

bool read_string(std::string &str, uint32_t length) {
	str.resize(length);
	return std::fread(&str[0], sizeof(char), str.length(), stdin) == length;
}

bool write_u32(uint32_t data) {
	return std::fwrite(reinterpret_cast<char*>(&data), sizeof(uint32_t), 1, stdout) == 1;
}

bool write_string(const std::string &str) {
	return std::fwrite(&str[0], sizeof(char), str.length(), stdout) == str.length();
}

bool get_message(std::string& str) {
	uint32_t length;
	debug_log("reading length");
	if (!read_u32(&length)) {
		debug_log("failed to read length");
		return false;
	}
	debug_log("reading string");
	if (!read_string(str, length)) {
		debug_log("failed to read string");
		return false;
	}
	debug_log("read string: [" + str + "]");
	debug_log(str.length());
	return true;
}

bool send_message(const std::string& str) {
	debug_log("writing length");
	if (!write_u32(str.length())) {
		debug_log("failed to write length");
		return false;
	}
	debug_log("writing string");
	if (!write_string(str)) {
		debug_log("failed to write string");
		return false;
	}
	debug_log("flushing");
	if (std::fflush(stdout) != 0) {
		debug_log("failed to flush");
		return false;
	}
	return true;
}

// main
int main(void) {
	std::string str;
	while (get_message(str)) {
		if (str == "\"ping\"") {
			send_message("\"pong\"");
		} else {
			debug_log("not a ping");
		}
	}

	return 0;
}

Thanks for providing code.

I will move to C++ then.

Regards.

Hi noitidart,

Your program works like a charm !!

Again thanks a lot !

So awesome to hear! My pleasure. All credit to @arai for teaching me! :slight_smile:

If you ever figure out what was wrong with your initial code, please do share that, I’m curious. :slight_smile:

Hi noitidart

I have not searched yet what is wrong wrong with my code.

I think the code is hanging on ‘fgetc’ call because no more characters are sent
after “ping”.
There should be an EOF at the end of flow data for 'feof() to exit the loop.

I will tell you when i have time.

Regards.

1 Like

Yes, I can use a while loop, but not relying on ‘feof()’.

1°) Read the input length first: always 4 bytes.
1°) Then, read actual data with the counter of bytes provided in step 1°) in a while loop