help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Help fixing NativeMessaging host: read 32-bit message length in nati


From: guest271314
Subject: Re: Help fixing NativeMessaging host: read 32-bit message length in native byte order
Date: Sat, 24 Jun 2023 07:40:21 -0700

Unfortunately that code produces "Invalid byte sequence in conversion
input".

I have something like this I am testing now. We can isolate the message
length from the message using read -r -n1.

That sendMessage currently sends the (same) message to the client the
number of time the length is.

So technically we can avoid reading the length altogether, just isolate the
first read from the data.

The issue below is since I am only reading the length once then calling
getMessage for subsequent messages the length winds up in data.txt.

Ideally we would concatenate "$message" to a string then send the message
to the client after the while loop in getMessage does not read any more
from stdin. I am not sure how to do that right now, as getMessage in the
"while true" loop is keeping the connection active and "sendMessage"
following the "while true" loop never sends the message.

getMessage() {
  while IFS= read -r -n1 message; do
    echo -n "$message" >> data.txt
    sendMessage '"Message from Bash Native Messaging host"'
    break
  done
}

sendMessage () {
  # ...
}

main() {
  read -r -n1 uint32
  # length=$(dd bs=4 count=1 | od -An -td4)
  # length=$((length))      # trim leading spaces
  echo -n "$uint32" >> length.txt
  while true; do
    getMessage
  done
}

main

On Sat, Jun 24, 2023 at 7:02 AM Greg Wooledge <greg@wooledge.org> wrote:

> On Fri, Jun 23, 2023 at 10:20:33PM -0700, guest271314 wrote:
> > > Chrome starts each native messaging host in a separate process and
> > communicates with it using standard input (stdin) and standard output
> > (stdout). The same format is used to send messages in both directions;
> each
> > message is serialized using JSON, UTF-8 encoded and is preceded with
> 32-bit
> > message length in native byte order.
>
> Reading that 4-byte binary number value is the hard part, because bash
> does not handle NUL bytes gracefully.  In bash, all input values are
> strings, which are stored as "C strings" internally (NUL being the string
> value terminator).  Bash has no means of storing binary values without
> doing some kind of encoding.  Not even "declare -i" causes binary storage
> to be used internally.  Everything is still a string.
>
> The only way to read this value would be to have some external program
> do it, and spit out a text encoding that bash can read.  Given that
> the 4 bytes are the prefix of a larger data stream, we need to ensure
> that *only* those 4 bytes are read, and that the rest of the stream
> is untouched.  The tool of choice for that is dd(1).
>
> So then, the next requirement is something which can take those 4 bytes
> of binary data and turn them into a textual representation of a number.
> And we don't want to use a "real" scripting language like perl or python
> or tcl, because if we're doing that, we would just write the entire
> project in that language, rather than in a hybrid of bash + other.
>
> My mind goes first to od(1).
>
> The GNU man page for od(1) is lacking some critical information, but the
> POSIX od(1p) gives me what I need.
>
> unicorn:~$ printf '\x00\x03\x01\x00' | od -An -td4
>        66304
>
> My system is amd64, which is little endian, so the 4-byte number that
> I wrote out with printf is indeed 66304 in base 10.  So that od call
> gives the correct value.
>
> Putting the pieces together, you might write something like this:
>
> length=$(dd bs=4 count=1 | od -An -td4)
> length=$((length))      # trim leading spaces
> IFS= read -rN"$length" json
>
> Then of course you'll need to use something which can decode the JSON
> for you.  jq(1) is popular in bash scripts.
>
>


reply via email to

[Prev in Thread] Current Thread [Next in Thread]