streamreaderchrome-native-messaging

Sending byte[] array to Host using Chrome Native Messaging


I am trying to send a JSON object that contains a byte[] to a "Console Application" using a Chrome Extention by NativeMessaging.

I have no problems with some of the calls, but I get a problem when I try to send a byte array.

Behavior is following:

  1. ChromeExtention creates a JSON object that contains a list and a byte[].
  2. NativeApp receives it but remains somehow blocked.

reader.Read(buffer, 0, buffer.Length);

I will post here a version of code that I hope it helps.

Native App.

Program.cs

public static void Main(string[] args)
        {
            m_Logger = LogManager.Setup().GetCurrentClassLogger();
            m_Logger.Info("App Started!");
            try
            {

                    JObject command = Read();
                    if (command != null)
                    {
                        var ceCommand = command.ToObject<CommandModel>();

                        if (ceCommand == null)
                        {
                            m_Logger.Warn("Could not deserialize command from extention");

                            return;
                        }
                        
                        //do other things
                    }
                }

            }
            catch (Exception ex)
            {               
                throw;
            }
        }
        
          public static JObject Read()
        {
            try
            {
                m_Logger.Debug("Read started");
                var stdin = Console.OpenStandardInput();
                m_Logger.Debug("StDin initialized");
                var length = 0;

                var lengthBytes = new byte[4];
                stdin.Read(lengthBytes, 0, 4);
                length = BitConverter.ToInt32(lengthBytes, 0);
                m_Logger.Debug($"Message length: {length}");

                var buffer = new char[length];
                m_Logger.Debug($"Buffer lenght: {buffer.Length}");
                using (var reader = new StreamReader(stdin))
                {
                    m_Logger.Debug("Reading from stream...");
                    while (reader.Peek() >= 0)
                    {
                        m_Logger.Debug("We are in reading process...please wait");
                        int result = reader.Read(buffer, 0, buffer.Length);
                        m_Logger.Debug($"Read {result} numer of chars");
                    }
                    m_Logger.Debug("Read finished");
                }
                var stringMessage = new string(buffer);

                m_Logger.Info($"Recieved from CE {stringMessage}");

                return JsonConvert.DeserializeObject<JObject>(stringMessage);
            }
            catch (Exception ex)
            {
                m_Logger.Error(ex, $"Error at reading input data");

                return null;
            }
        }

        public static void Write(JToken data)
        {
            var json = new JObject();
            json["data"] = data;

            var bytes = System.Text.Encoding.UTF8.GetBytes(json.ToString(Formatting.None));

            var stdout = Console.OpenStandardOutput();
            stdout.WriteByte((byte)((bytes.Length >> 0) & 0xFF));
            stdout.WriteByte((byte)((bytes.Length >> 8) & 0xFF));
            stdout.WriteByte((byte)((bytes.Length >> 16) & 0xFF));
            stdout.WriteByte((byte)((bytes.Length >> 24) & 0xFF));
            stdout.Write(bytes, 0, bytes.Length);
            stdout.Flush();
        }

        /// <summary>
        /// Copies the contents of input to output. Doesn't close either stream.
        /// </summary>
        public static string ByteToString(byte[] array, int count)
        {
            char[] chars = Encoding.UTF8.GetChars(array, 0, count);

            return new string(chars);
        }

I deducted that the problem is at reader.Read(buffer, 0, buffer.Length); based on logs that look like this

2022-11-17 16:34:14.9604 INFO  App Started!
2022-11-17 16:34:15.0837 DEBUG  Read started
2022-11-17 16:34:15.0837 DEBUG  StDin initialized
2022-11-17 16:34:15.0837 DEBUG  Message length: 1862
2022-11-17 16:34:15.0837 DEBUG  Buffer lenght: 1862
2022-11-17 16:34:15.0837 DEBUG  Reading from stream...
2022-11-17 16:34:15.0837 DEBUG  We are in reading process...please wait
2022-11-17 16:34:15.0837 DEBUG  Read 1862 numer of chars
2022-11-17 16:34:44.2786 DEBUG  Read finished
2022-11-17 16:34:44.2787 DEBUG  Message length: 0
2022-11-17 16:34:44.2787 DEBUG  Buffer lenght: 0
2022-11-17 16:34:44.2786 INFO  Recieved from CE {"CommandId":2,"CommandValue":"{\"ImportCertificates\":[],\"byteArray\":\"MIIKWAIBAzCCChQGCSqGSIb3DQEHAaCCCgUEggoBMIIJ/TCCBe4GCSqGSIb3DQEHAaCCBd8EggXbMIIF1zCCBdMGCyqGSIb3DQEMCgECoIIE7jCCBOowHAYKKoZIhvcNAQwBAzAOBAjslY0EWPiyRwICB9AEggTItTgbudKRaEBCdOn1rMgGUoGjVIOxTgT/5Oo5D0gfBe/0yorvQKenVimcfDmWCXZGlsvou5Km7g3yjmK7PTZh3IUuX86bJeyECrJBZa+4ZXyrbkVV7R2GEwy99ACOkevHxBZ7H6deVKdRFDsCSC+cdLpsSGoNNi3Coowqw8i7lzXDPzph64L2Rre7cky/QJdkXKIEUGjxKYUR4cpOOmlLXfbQMR3fOChT5FrxbOnTRTAvVELtwFTh8Gxq55Et8rLgIktQ2eL8FIx43sGspukhZvm5bH05aEwVz5df0T3e3cMsZ13t4oc72phNKx9HiZmPvmi4lUdBwn6qXEJSRg+P5MWGD41StCAoZ/pDtMTPSV5DalLpDpKF6XfxByOSXfn27KYWFZoiEdxCmabS7eomqeD03uWEzWbgPW1hha69Bg1DcmSYZgDfISugtow6p+ozQSjaNnELlbz1SsiBMPbkoNj944IxSKkHgfiqwOyQm3JqHGjDH6Hp9OB3RyuQHoeWLrW9ulmWvnT/Dn+LC0T26YHeVeTO30U86r9ElBiv4iXa5JdflWqFecbjQC1Xs29yBkkFRNrfgJ4Txd/xOz0rhzFxZmcIwiJsQgh+WxSWLG3em02xmtyO7Rcxc6g+onVpEFXKiaYDqTWNDKE2wDSDPZauheyiiluj42gi5A086rSjuqqyidzWQb6FKYs73ZUM8drnYK36RT7zG8TFpV3RdrXbnui8eFRZ4bFHNlptHTwvqpZY/sDDP1R1q1EgrckMbZhOpHhKW/1GRd95eHlSGJPdTROtR3uEARZD0+1zBarw68p1k650DWua88cMrOQPKH1X8Ce++KIdFG2RtfI2P3lhPsD0gdpet0gDEC1peUXfrZVQYD3G8IfEjpYgDpgPa6zjblScidem628MPz4dnTnWrp1S7P2ILlGYinb9uCzSR17IvPoVITQvXk9KpTp1uzuWTnRQHMfUyNvgjHSAOwt3bmx5kEyC/04ujhUvQkiyPMCrDtiO/fLYkrWuqOLNr74l/VAJYU06YR7yNMfG1kEpRYkf96v0s3XK1tZEQBt26lZFPIMl/NOHYpbCfxCGZkpOGIFDojjo72p4VUuyGD/MZ41B99jcNVB2/Sqmc9XwALl/jjkJz6+aCmvLUePeLmhg2Bxrjkmf8iDfDnKByXM5lam3D\"}","SessionKey":"QXCUUKNB0T"}
2022-11-17 16:34:44.2787 DEBUG  Reading from stream...
2022-11-17 16:34:44.2787 DEBUG  Read finished
2022-11-17 16:34:44.2787 INFO  Recieved from CE 

However this is not a problem if byteArray property is smaller in size

2022-11-17 16:32:49.7558 INFO  App Started!
2022-11-17 16:32:49.8809 DEBUG  Read started
2022-11-17 16:32:49.8809 DEBUG  StDin initialized
2022-11-17 16:32:49.8809 DEBUG  Message length: 546
2022-11-17 16:32:49.8809 DEBUG  Buffer lenght: 546
2022-11-17 16:32:49.8809 DEBUG  Reading from stream...
2022-11-17 16:32:49.8809 DEBUG  We are in reading process...please wait
2022-11-17 16:32:49.8809 DEBUG  Read 546 numer of chars
2022-11-17 16:32:49.8809 DEBUG  Read finished
2022-11-17 16:32:49.8809 INFO  Recieved from CE {"CommandId":2,"CommandValue":"{\"ImportCertificates\":[],\"byteArray\":\"test/wqewq+./qweqeq//eqwq\"}","SessionKey":"0SZFlRVrQR"}

As you can see here from logs app does the full flow without a problem from Starting and reading and parsing my message.

I suspected that is something regarding the size of the array, but from what I've read you can send up to 1mb of data in one NativeMessage call, data that I want to send is about 4Kb. Not even close to the max allowed size.

Any ideas on what I am doing wrong?

I will post here also the Javascript code that send this, but I don't believe problem relies in Javascript code.

export const syncCertificates = async () => {
   var requestToHost = await api.getInfo(); 
   var responsefromHost = await nativeService.syncCertificates(requestToHost);

   return certUploadResponse;
} 

export const syncCertificates = async (certs) => {
     var command = commands[1];
     await sendNativeMessageV2(command.Id, certs);
}

async function sendNativeMessageV2(command, commandValue) {
     commandInProgress = command;
     var sessionKey = await storage.getSessionKey();

     var message =
     {
          "CommandId": command,
          "CommandValue": JSON.stringify(commandValue),
          "SessionKey": sessionKey
     }
     return new Promise((resolve, reject) => {
          chrome.runtime.sendNativeMessage('com.allianz.usercertificateautoenrollment', message,
               async function (result) {
                    var response = await onNativeMessage(result);
                    resolve(response);
               }
          );
     });
}

Solution

  • After more investigations I found this Why is my C# native messaging host hanging when reading a message sent by a Firefox browser extension?

    Changing the loop as answered here did the trick.

    Change the loop as follows:

    using (var reader = new StreamReader(stdin))
    {
      var offset = 0;
      while (offset < length && reader.Peek() >= 0)
      {
        offset += reader.Read(buffer, offset, length - offset);
      }
    }