Native messaging "ping_pong" example in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*** 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); | |
} |
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
If there are errors the Native Messaging host will either not send the message or exit. I wrote the same code in Python, C++, C, and JavaScript.