Skip to content

Instantly share code, notes, and snippets.

@zed
Last active January 30, 2023 07:05
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zed/4459378be67a4b37f53430e0703cb700 to your computer and use it in GitHub Desktop.
Save zed/4459378be67a4b37f53430e0703cb700 to your computer and use it in GitHub Desktop.
Native messaging "ping_pong" example in C
/*** Native messaging "ping_pong" example in C.
*
* It is reimplementation of the corresponding Python example from
* https://github.com/mdn/webextensions-examples/tree/master/native-messaging
*
* # Python 3.x version
* # Read a message from stdin and decode it.
* def getMessage():
* rawLength = sys.stdin.buffer.read(4)
* if len(rawLength) == 0:
* sys.exit(0)
* messageLength = struct.unpack('@I', rawLength)[0]
* message = sys.stdin.buffer.read(messageLength).decode('utf-8')
* return json.loads(message)
*
* # Encode a message for transmission,
* # given its content.
* def encodeMessage(messageContent):
* encodedContent = json.dumps(messageContent).encode('utf-8')
* encodedLength = struct.pack('@I', len(encodedContent))
* return {'length': encodedLength, 'content': encodedContent}
*
* # Send an encoded message to stdout
* def sendMessage(encodedMessage):
* sys.stdout.buffer.write(encodedMessage['length'])
* sys.stdout.buffer.write(encodedMessage['content'])
* sys.stdout.buffer.flush()
*
* while True:
* receivedMessage = getMessage()
* if receivedMessage == "ping":
* sendMessage(encodeMessage("pong3"))
*
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
uint32_t message_length;
// read messages and send response
while (fread(&message_length, sizeof message_length, 1, stdin) == 1) {
// read message into buffer
char *buf = malloc(message_length);
if (!buf) {
perror("malloc");
return EXIT_FAILURE;
}
if (fread(buf, sizeof *buf, message_length, stdin) != message_length) {
perror("fread");
return EXIT_FAILURE;
}
// check we got the "ping" message (JSON string)
char expected[] = u8"\"ping\"";
const uint32_t expected_length = (sizeof expected) - 1; // - null byte
if (strncmp(buf, expected, expected_length)) {
fprintf(stderr, "error: expected '%s', got: '%.*s' instead\n", expected, message_length, buf);
return EXIT_FAILURE;
}
// write response (JSON prefixed with its utf-8 length)
char response[] = u8"\"pong\"";
const uint32_t response_length = (sizeof response) - 1; // - null byte
if (fwrite(&response_length, sizeof response_length, 1, stdout) != 1
|| fwrite(response, response_length, 1, stdout) != 1) {
perror("fwrite");
return EXIT_FAILURE;
}
fflush(stdout);
// cleanup
free(buf);
} // end while
if (ferror(stdin))
perror("can't read message length");
// return success on EOF
return ! feof(stdin);
}
@guest271314
Copy link

It is not a good idea to ignore error in C. Switch to Python if you need an executable pseudo-code kind-of feel (at least Python would raise exceptions).

I don't think the errors from from C reach native_message_process_host.cc. E.g., on Chromium when passing a message from client to host that is greater than 1024*1024 (new Array(458*458)) chrome.runtime.lastError logs {message: 'Error when communicating with the native messaging host.'}. To get the error message in native_message_process_host.cc I had to use

--enable-logging \
--log-level=0 \
--vmodule=native_message_process_host=0 \
--v=0 

then search for

[...:ERROR:native_message_process_host.cc(300)] Native Messaging host tried sending a message that is 1048821 bytes long.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment