-
-
Save zed/4459378be67a4b37f53430e0703cb700 to your computer and use it in GitHub Desktop.
| /*** 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).
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.
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.
Echo input message