zim32 / mysql.dart

MySQL client for Dart written in Dart
BSD 3-Clause "New" or "Revised" License
64 stars 17 forks source link

Support for proper error handling while performing initial handshake #25

Closed MHShetty closed 2 years ago

MHShetty commented 2 years ago

I'm currently trying to connect my Windows Flutter app to a MySQL 8 server hosted on my local machine.

I am able to connect to it via my console, but the same isn't true for the Flutter app. Later found out that this issue was mainly related to not having the correct IP for my device (it was earlier set to the IP of my phone for testing purposes).

This was initially hard to detect, since no logs except a RangeError was thrown while reading the packets received from the MySQL server.

Here are some logs for the same (have added some additional logging in the library code that might be helpful):

flutter: Isconnected: false
flutter: TypedDataView(cid: 152)
flutter: protocolVersion: 255
flutter: Server version: jHost 'REPLACED_WITH_XYZ' is not allowed to connect to this MySQL server
[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: RangeError (byteOffset): Invalid value: Not in inclusive range 0..67: 72
#0      _ByteDataView.getUint32 (dart:typed_data-patch/typed_data_patch.dart:4864:7)
#1      new MySQLPacketInitialHandshake.decode (package:mysql_client/src/mysql_protocol/packet/packet_initial_handshake.dart:48:35)
#2      new MySQLPacket.decodeInitialHandshake (package:mysql_client/src/mysql_protocol/mysql_packet.dart:112:49)
#3      MySQLConnection._processInitialHandshake (package:mysql_client/src/mysql_client/connection.dart:261:32)
#4      MySQLConnection._processSocketData (package:mysql_client/src/mysql_client/connection.dart:154:13)
#5      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:113:17)
#6      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:110:42)
#7      _rootRunUnary (dart:async/zone.dart:1434:47)
#8      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#9      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#10     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#11     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#12     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:774:19)
#13     _StreamController._add (dart:async/stream_controller.dart:648:7)
#14     _StreamController.add (dart:async/stream_controller.dart:596:5)
#15     _Socket._onData (dart:io-patch/socket_patch.dart:2314:41)
#16     _rootRunUnary (dart:async/zone.dart:1442:13)
#17     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#18     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#19     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#20     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#21     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:774:19)
#22     _StreamController._add (dart:async/stream_controller.dart:648:7)
#23     _StreamController.add (dart:async/stream_controller.dart:596:5)
#24     new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1839:33)
#25     _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1322:14)
#26     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
#27     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)

flutter: Isconnected: false

Having a better error handling mechanism by preferably going through some official documentation related would be really helpful to improve the library. (Reference: https://dev.mysql.com/doc/internals/en/packet-ERR_Packet.html)

Please do let me know if I could help you'll with a PR for the same.

Thanks for building this library!

zim32 commented 2 years ago

Good day. There is separate logging branch. You can see readme Troubleshooting how to deal with logging. This timeout bug happens a lot.but I can no reproduce it locally. If you can provide logging information after switching to logging branch I will be very happy

zim32 commented 2 years ago

Also you can try to disable TLS connection, by passing secure: false, and see does it helps

MHShetty commented 2 years ago

Hi @zim32,

Actually the logs I have posted in the last answer are mainly related to the RangeError that gets thrown as the (MySQLPacketInitialHandshake.decode) factory method incorrectly parses the error packet as a valid packet containing the information it is otherwise trying to retrieve.

The actual format of the packet seems to be the one mentioned here: https://dev.mysql.com/doc/internals/en/packet-ERR_Packet.html

Please try comparing the above format to the (additional) logs shared earlier (The offset of protocolVersion yields 255).

flutter: Isconnected: false
flutter: TypedDataView(cid: 152)
flutter: protocolVersion: 255
flutter: Server version: jοΏ½Host 'REPLACED_WITH_XYZ' is not allowed to connect to this MySQL server
[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: RangeError (byteOffset): Invalid value: Not in inclusive range 0..67: 72
#0      _ByteDataView.getUint32 (dart:typed_data-patch/typed_data_patch.dart:4864:7)
#1      new MySQLPacketInitialHandshake.decode (package:mysql_client/src/mysql_protocol/packet/packet_initial_handshake.dart:48:35)
#2      new MySQLPacket.decodeInitialHandshake (package:mysql_client/src/mysql_protocol/mysql_packet.dart:112:49)
#3      MySQLConnection._processInitialHandshake (package:mysql_client/src/mysql_client/connection.dart:261:32)
#4      MySQLConnection._processSocketData (package:mysql_client/src/mysql_client/connection.dart:154:13)
#5      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:113:17)
#6      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:110:42)
#7      _rootRunUnary (dart:async/zone.dart:1434:47)
#8      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#9      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#10     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#11     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#12     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:774:19)
#13     _StreamController._add (dart:async/stream_controller.dart:648:7)
#14     _StreamController.add (dart:async/stream_controller.dart:596:5)
#15     _Socket._onData (dart:io-patch/socket_patch.dart:2314:41)
#16     _rootRunUnary (dart:async/zone.dart:1442:13)
#17     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#18     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#19     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#20     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#21     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:774:19)
#22     _StreamController._add (dart:async/stream_controller.dart:648:7)
#23     _StreamController.add (dart:async/stream_controller.dart:596:5)
#24     new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1839:33)
#25     _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1322:14)
#26     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
#27     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)

flutter: Isconnected: false

You'll might want to add some code to handle that correctly, so this issue is mainly for that. You'll can mark this as fixed once this issue gets resolved. Please do let me know if I could help you'll with a quick PR for the same.

You can see readme Troubleshooting how to deal with logging.

At the moment, I'm facing issues with connecting to MySQL database with the same timeout error you just mentioned, but we could probably discuss that on a separate issue once I'm back with the logs.

Also you can try to disable TLS connection, by passing secure: false, and see does it helps

I had tried disabling secure connection too, as stated by you another issue, doesn't seem to unfortunately help.

Thanks for the quick response @zim32!

zim32 commented 2 years ago

At least in logging branch I can see raw bytes, coming from your mysql server. I can then compare it with what I have locally and spot the difference

zim32 commented 2 years ago

Without this information it is very hard to find out the problem

MHShetty commented 2 years ago

Oh sure, I'll just share them soon for this issue too in that case πŸ‘

MHShetty commented 2 years ago

Here are the logs from the logging branch: (@zim32)

Launching lib\main.dart on Windows in debug mode...
Building Windows application...
Debug service listening on ws://127.0.0.1:55172/MiqCaU64CtY=/ws
Syncing files to device Windows...
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection.createConnection (package:mysql_client/src/mysql_client/connection.dart:83:12)
flutter: β”‚ #1   init (package:test_project/sql.dart:11:39)
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Establishing socket connection
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection.createConnection (package:mysql_client/src/mysql_client/connection.dart:83:12)
flutter: β”‚ #1   init (package:test_project/sql.dart:11:39)
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Establishing socket connection
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
flutter: Isconnected: false
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection.createConnection (package:mysql_client/src/mysql_client/connection.dart:85:12)
flutter: β”‚ #1   <asynchronous suspension>
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Socket connection established
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection.createConnection (package:mysql_client/src/mysql_client/connection.dart:85:12)
flutter: β”‚ #1   <asynchronous suspension>
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Socket connection established
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection._processSocketData (package:mysql_client/src/mysql_client/connection.dart:163:12)
flutter: β”‚ #1   MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:123:17)
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Processing socket data. Current state is _MySQLConnectionState.waitInitialHandshake
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection._processInitialHandshake (package:mysql_client/src/mysql_client/connection.dart:279:12)
flutter: β”‚ #1   MySQLConnection._processSocketData (package:mysql_client/src/mysql_client/connection.dart:167:13)
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Processing initial handshake
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: RangeError (byteOffset): Invalid value: Not in inclusive range 0..67: 72
#0      _ByteDataView.getUint32 (dart:typed_data-patch/typed_data_patch.dart:4864:7)
#1      new MySQLPacketInitialHandshake.decode (package:mysql_client/src/mysql_protocol/packet/packet_initial_handshake.dart:42:35)
#2      new MySQLPacket.decodeInitialHandshake (package:mysql_client/src/mysql_protocol/mysql_packet.dart:112:49)
#3      MySQLConnection._processInitialHandshake (package:mysql_client/src/mysql_client/connection.dart:281:32)
#4      MySQLConnection._processSocketData (package:mysql_client/src/mysql_client/connection.dart:167:13)
#5      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:123:17)
#6      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:120:42)
#7      _rootRunUnary (dart:async/zone.dart:1434:47)
#8      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#9      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#10     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#11     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#12     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:774:19)
#13     _StreamController._add (dart:async/stream_controller.dart:648:7)
#14     _StreamController.add (dart:async/stream_controller.dart:596:5)
#15     _Socket._onData (dart:io-patch/socket_patch.dart:2314:41)
#16     _rootRunUnary (dart:async/zone.dart:1442:13)
#17     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#18     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#19     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#20     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#21     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:774:19)
#22     _StreamController._add (dart:async/stream_controller.dart:648:7)
#23     _StreamController.add (dart:async/stream_controller.dart:596:5)
#24     new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1839:33)
#25     _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1322:14)
#26     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
#27     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
MHShetty commented 2 years ago

Also, please note that the timeout related issue (Issue #26) is entirely different from this issue that is related to error handling in case of an unexpected host name. The issue over here is that the factory method MySQLPacketInitialHandshake.decode tries to incorrectly pass the error packet as a valid packet (based on its format).

The error packet is much shorter and hence the RangeError that gets thrown.

The documented for the error packet (as mentioned in the earlier comments) is here: https://dev.mysql.com/doc/internals/en/packet-ERR_Packet.html

zim32 commented 2 years ago

Could you also provide code, where you are establishing connection? You can mask user password if you want

zim32 commented 2 years ago

Hm.. I gues the problem is here https://github.com/zim32/mysql.dart/blob/main/lib/src/mysql_protocol/packet/packet_initial_handshake.dart#L39

I guess length of decoded string is not equal to bytes in your case. Seems like you server version string contains some unusual characters. I need to rewrite this piece of code

zim32 commented 2 years ago

I have fixed decoding strings. Latest changes are in main branch. Can you point dart pub to main branch and test it? It should work.

MHShetty commented 2 years ago

Hi @zim32,

Really sorry for the late reply, actually I got really busy with some other work and email notifications didn't notify me of the message that you had shared around 2 days ago.

I tried testing the code (after changing the ref to main under your package name and git pubspec.yaml and running pub get successfully) and it still shows the same error unfortunately:

[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: RangeError (byteOffset): Invalid value: Not in inclusive range 0..67: 72
#0      _ByteDataView.getUint32 (dart:typed_data-patch/typed_data_patch.dart:4864:7)
#1      new MySQLPacketInitialHandshake.decode (package:mysql_client/src/mysql_protocol/packet/packet_initial_handshake.dart:42:35)
#2      new MySQLPacket.decodeInitialHandshake (package:mysql_client/src/mysql_protocol/mysql_packet.dart:112:49)
#3      MySQLConnection._processInitialHandshake (package:mysql_client/src/mysql_client/connection.dart:261:32)
#4      MySQLConnection._processSocketData (package:mysql_client/src/mysql_client/connection.dart:154:13)
#5      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:113:17)
#6      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:110:42)
#7      _rootRunUnary (dart:async/zone.dart:1434:47)

Not really sure about the encoding change, but the from what I am able to understand, the issue seems to be with parsing an error packet as a valid packet. We might need to write some code to handle that (based on the design of the library).

Please try tracing the data packets received while supplying the actual IP of your machine instead of localhost (or maybe a IP that's not a part of the network) while trying to connect to a local MySQL instance, and then logging. The packet that gets delivered then seems to be of the format of an error packet mentioned here in the docs - https://dev.mysql.com/doc/internals/en/packet-ERR_Packet.html

Thanks a lot for sharing your valuable time!

zim32 commented 2 years ago

First packet is always initial handshake. It can not be error packet

zim32 commented 2 years ago

I can not understand why there are two Establishing connection in your logs.

MHShetty commented 2 years ago

First packet is always initial handshake. It can not be error packet

It doesn't seem to be the first packet here.. Tried logging again.

I can not understand why there are two Establishing connection in your logs.

Really sorry for that.. actually I had written some debug code that might have caused double initialization back then.

Here are the latest logs:

flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection.createConnection (package:mysql_client/src/mysql_client/connection.dart:83:12)
flutter: β”‚ #1   init (package:test_project/sql.dart:11:39)
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Establishing socket connection
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
flutter: Isconnected: false
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection.createConnection (package:mysql_client/src/mysql_client/connection.dart:85:12)
flutter: β”‚ #1   <asynchronous suspension>
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Socket connection established
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection._processSocketData (package:mysql_client/src/mysql_client/connection.dart:163:12)
flutter: β”‚ #1   MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:123:17)
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Processing socket data. Current state is _MySQLConnectionState.waitInitialHandshake
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection._processInitialHandshake (package:mysql_client/src/mysql_client/connection.dart:280:12)
flutter: β”‚ #1   MySQLConnection._processSocketData (package:mysql_client/src/mysql_client/connection.dart:167:13)
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Processing initial handshake
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: RangeError (byteOffset): Invalid value: Not in inclusive range 0..67: 72
#0      _ByteDataView.getUint32 (dart:typed_data-patch/typed_data_patch.dart:4864:7)
#1      new MySQLPacketInitialHandshake.decode (package:mysql_client/src/mysql_protocol/packet/packet_initial_handshake.dart:42:35)
#2      new MySQLPacket.decodeInitialHandshake (package:mysql_client/src/mysql_protocol/mysql_packet.dart:112:49)
#3      MySQLConnection._processInitialHandshake (package:mysql_client/src/mysql_client/connection.dart:282:32)
#4      MySQLConnection._processSocketData (package:mysql_client/src/mysql_client/connection.dart:167:13)
#5      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:123:17)
#6      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:120:42)
#7      _rootRunUnary (dart:async/zone.dart:1434:47)
#8      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#9      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#10     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#11     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#12     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:774:19)
#13     _StreamController._add (dart:async/stream_controller.dart:648:7)
#14     _StreamController.add (dart:async/stream_controller.dart:596:5)
#15     _Socket._onData (dart:io-patch/socket_patch.dart:2314:41)
#16     _rootRunUnary (dart:async/zone.dart:1442:13)
#17     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#18     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#19     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#20     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#21     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:774:19)
#22     _StreamController._add (dart:async/stream_controller.dart:648:7)
#23     _StreamController.add (dart:async/stream_controller.dart:596:5)
#24     new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1839:33)
#25     _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1322:14)
#26     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
#27     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)

It still seems to because of incorrectly parsing a valid packet as an error packet.

zim32 commented 2 years ago

Ok let's go deeper. On logging branch, open lib/src/mysql_client/connection.dart file and change

Find line at the top: final loggingLevel = Level.debug;

And change it to: final loggingLevel = Level.verbose;

Then test again and copy-paste logs please.

MHShetty commented 2 years ago

Sure @zim32, just changed the the logging to verbose by re-built the app.

Here are the latest logs now:

Launching lib\main.dart on Windows in debug mode...
Building Windows application...
Debug service listening on ws://127.0.0.1:52784/zdk3EvYGJWY=/ws
Syncing files to device Windows...
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection.createConnection (package:mysql_client/src/mysql_client/connection.dart:83:12)
flutter: β”‚ #1   init (package:test_project/sql.dart:11:39)
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Establishing socket connection
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
flutter: Isconnected: false
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection.createConnection (package:mysql_client/src/mysql_client/connection.dart:85:12)
flutter: β”‚ #1   <asynchronous suspension>
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Socket connection established
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection._processSocketData (package:mysql_client/src/mysql_client/connection.dart:163:12)
flutter: β”‚ #1   MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:123:17)
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Processing socket data. Current state is _MySQLConnectionState.waitInitialHandshake
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection._processInitialHandshake (package:mysql_client/src/mysql_client/connection.dart:280:12)
flutter: β”‚ #1   MySQLConnection._processSocketData (package:mysql_client/src/mysql_client/connection.dart:167:13)
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Processing initial handshake
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: RangeError (byteOffset): Invalid value: Not in inclusive range 0..67: 72
#0      _ByteDataView.getUint32 (dart:typed_data-patch/typed_data_patch.dart:4864:7)
#1      new MySQLPacketInitialHandshake.decode (package:mysql_client/src/mysql_protocol/packet/packet_initial_handshake.dart:42:35)
#2      new MySQLPacket.decodeInitialHandshake (package:mysql_client/src/mysql_protocol/mysql_packet.dart:112:49)
#3      MySQLConnection._processInitialHandshake (package:mysql_client/src/mysql_client/connection.dart:282:32)
#4      MySQLConnection._processSocketData (package:mysql_client/src/mysql_client/connection.dart:167:13)
#5      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:123:17)
#6      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:120:42)
#7      _rootRunUnary (dart:async/zone.dart:1434:47)
#8      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#9      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#10     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#11     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#12     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:774:19)
#13     _StreamController._add (dart:async/stream_controller.dart:648:7)
#14     _StreamController.add (dart:async/stream_controller.dart:596:5)
#15     _Socket._onData (dart:io-patch/socket_patch.dart:2314:41)
#16     _rootRunUnary (dart:async/zone.dart:1442:13)
#17     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#18     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#19     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#20     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#21     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:774:19)
#22     _StreamController._add (dart:async/stream_controller.dart:648:7)
#23     _StreamController.add (dart:async/stream_controller.dart:596:5)
#24     new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1839:33)
#25     _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1322:14)
#26     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
#27     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)

Not really sure, I don't think there are any separate or additional log statements at this stage unfortunately (specifically for verbose).

zim32 commented 2 years ago

No changes. Very strange. There should be more info

zim32 commented 2 years ago

I thinks flutter is making some magic and ignores you change

zim32 commented 2 years ago

Is it possible that flutter reverts all local changes before building?

zim32 commented 2 years ago

Ok I will try to setup flutter and test

MHShetty commented 2 years ago

Hey @zim32,

Sorry for the unexpected delay.

I tried re-building the app too. Not really certain about how things are working behind the hood.

Here are some additional logs for the same that might help:

Launching lib\main.dart on Windows in debug mode...
Building Windows application...
Debug service listening on ws://127.0.0.1:55706/d4Soajcr17M=/ws
Syncing files to device Windows...
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection.createConnection (package:mysql_client/src/mysql_client/connection.dart:83:12)
flutter: β”‚ #1   init (package:test_project/sql.dart:11:39)
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Establishing socket connection
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection.createConnection (package:mysql_client/src/mysql_client/connection.dart:85:12)
flutter: β”‚ #1   <asynchronous suspension>
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Socket connection established
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection._processSocketData (package:mysql_client/src/mysql_client/connection.dart:163:12)
flutter: β”‚ #1   MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:123:17)
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Processing socket data. Current state is _MySQLConnectionState.waitInitialHandshake
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
flutter: β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
flutter: β”‚ #0   MySQLConnection._processInitialHandshake (package:mysql_client/src/mysql_client/connection.dart:280:12)
flutter: β”‚ #1   MySQLConnection._processSocketData (package:mysql_client/src/mysql_client/connection.dart:167:13)
flutter: β”œβ”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„β”„
flutter: β”‚ πŸ› Processing initial handshake
flutter: └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
flutter: Buffer: [255, 106, 4, 72, 111, 115, 116, 32, 39, 73, 78, 84, 77, 85, 77, 49, 76, 65, 80, 48, 53, 56, 56, 39, 32, 105, 115, 32, 110, 111, 116, 32, 97, 108, 108, 111, 119, 101, 100, 32, 116, 111, 32, 99, 111, 110, 110, 101, 99, 116, 32, 116, 111, 32, 116, 104, 105, 115, 32, 77, 121, 83, 81, 76, 32, 115, 101, 114, 118, 101, 114]
flutter: byteData: TypedDataView(cid: 152)
flutter: protocolVersion: 255
flutter: serverVersion: jHost 'SOME_RANDOM_NAME' is not allowed to connect to this MySQL server
[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: RangeError (byteOffset): Invalid value: Not in inclusive range 0..67: 72
#0      _ByteDataView.getUint32 (dart:typed_data-patch/typed_data_patch.dart:4864:7)
#1      new MySQLPacketInitialHandshake.decode (package:mysql_client/src/mysql_protocol/packet/packet_initial_handshake.dart:49:35)
#2      new MySQLPacket.decodeInitialHandshake (package:mysql_client/src/mysql_protocol/mysql_packet.dart:112:49)
#3      MySQLConnection._processInitialHandshake (package:mysql_client/src/mysql_client/connection.dart:282:32)
#4      MySQLConnection._processSocketData (package:mysql_client/src/mysql_client/connection.dart:167:13)
#5      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:123:17)
#6      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:120:42)
#7      _rootRunUnary (dart:async/zone.dart:1434:47)
#8      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#9      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#10     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#11     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#12     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:774:19)
#13     _StreamController._add (dart:async/stream_controller.dart:648:7)
#14     _StreamController.add (dart:async/stream_controller.dart:596:5)
#15     _Socket._onData (dart:io-patch/socket_patch.dart:2314:41)
#16     _rootRunUnary (dart:async/zone.dart:1442:13)
#17     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#18     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#19     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#20     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#21     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:774:19)
#22     _StreamController._add (dart:async/stream_controller.dart:648:7)
#23     _StreamController.add (dart:async/stream_controller.dart:596:5)
#24     new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1839:33)
#25     _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1322:14)
#26     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
#27     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)

I modified the factory method MySQLPacketInitialHandshake.decode to log the buffer, byteData, protocolVersion, etc. values. (since the error pointed there)

(connectionID wasn't included as the code crashes while trying to obtain it mainly because of the bad/unexpected format of the packet)

Here's the modified code of the factory method (for reference):

  factory MySQLPacketInitialHandshake.decode(Uint8List buffer) {
    final byteData = ByteData.sublistView(buffer);
    int offset = 0;

    print("Buffer: $buffer");
    print("byteData: $byteData");

    // protocol version
    final protocolVersion = byteData.getUint8(offset);
    offset += 1;

    print("protocolVersion: $protocolVersion");

    // server version
    final serverVersion = buffer.getAsciNullTerminatedString(offset);
    offset += serverVersion.length + 1;

    print("serverVersion: $serverVersion");

    // connection id
    final connectionID = byteData.getUint32(offset, Endian.little);
    offset += 4;

    // auth-plugin-data-part-1
    final authPluginDataPart1 =
        Uint8List.sublistView(buffer, offset, offset + 8);
    offset += 9; // 8 + filler;

    // capability flags (lower 2 bytes)
    final capabilitiesBytesData = ByteData(4);
    capabilitiesBytesData.setUint8(3, buffer[offset]);
    capabilitiesBytesData.setUint8(2, buffer[offset + 1]);
    offset += 2;

    // character set
    final charset = byteData.getUint8(offset);
    offset += 1;

    final statusFlags = Uint8List.sublistView(buffer, offset, offset + 2);
    offset += 2;

    // capability flags (upper 2 bytes)
    capabilitiesBytesData.setUint8(1, buffer[offset]);
    capabilitiesBytesData.setUint8(0, buffer[offset + 1]);
    offset += 2;

    final capabilityFlags = capabilitiesBytesData.getUint32(0, Endian.big);

    // length of auth-plugin-data
    int authPluginDataLength = 0;

    if (capabilityFlags & mysqlCapFlagClientPluginAuth != 0) {
      authPluginDataLength = byteData.getUint8(offset);
    }

    offset += 1;

    // reserved
    offset += 10;

    Uint8List? authPluginDataPart2;

    if (capabilityFlags & mysqlCapFlagClientSecureConnection != 0) {
      int length = max(13, authPluginDataLength - 8);

      authPluginDataPart2 =
          Uint8List.sublistView(buffer, offset, offset + length);

      offset += length;
    }

    String? authPluginName;

    if (capabilityFlags & mysqlCapFlagClientPluginAuth != 0) {
      authPluginName = buffer.getAsciNullTerminatedString(offset);
    }

    return MySQLPacketInitialHandshake(
      authPluginDataPart1: authPluginDataPart1,
      authPluginDataPart2: authPluginDataPart2,
      authPluginName: authPluginName,
      capabilityFlags: capabilityFlags,
      charset: charset,
      connectionID: connectionID,
      protocolVersion: protocolVersion,
      serverVersion: serverVersion,
      statusFlags: statusFlags,
    );
  }

Please do let me know if any additional information is required

zim32 commented 2 years ago

It really error packet coming first. Where is on mysql documentation they say that instead of initial handshake, error packet can arrive...

zim32 commented 2 years ago

Ok I need to refactor error handling in this library, because right now it is impossible to catch async errors. With this fix I will handle error packets and it will fix this issue too

MHShetty commented 2 years ago

Yes that's true @zim32. We might want to add some error checking mechanism checks for an error packet and throws the appropriate exception for the same. (For quick reference: https://dev.mysql.com/doc/internals/en/packet-ERR_Packet.html)

Thanks for considering the feedback @zim32!

MHShetty commented 2 years ago

Also, I have resolved the issue on my end by using localhost instead of directly hardcoding the IP on the same machine. This happened while I was trying to test my Flutter app on my phone. I'm currently facing issues with some timeout related error sent by the server itself (the other issue that I had filed). I assume it's because of some unexpected config. I'll add additional information on that thread for the same soon. Thanks for your valuable time @zim32!

zim32 commented 2 years ago

I need some advice. In case of MySQL server sends err packet, should I close connection or leave it open and ready for communication? I can not find any guidance about what to do after receiving error packet...

MHShetty commented 2 years ago

Hi @zim32,

should I close connection or leave it open and ready for communication? I can not find any guidance about what to do after receiving error packet

Yes, I think it should be done in a safe manner to avoid leaving the library in a bad/unexpected state.


Just did some testing for the same. It seems that the connection anyways closes after the error occurs.

Trying to connect again after this, using the connect method throws a MySQLClientException containing the message Can not connect: status is not fresh.

Trying to disconnect after the that, using the disconnect method throws a different exception,

Here are the logs for the same:

[ERROR:flutter/shell/common/shell.cc(93)] Dart Unhandled Exception: Bad state: StreamSink is closed, stack trace: #0      _StreamSinkImpl.add (dart:io/io_sink.dart:134:7)
#1      _Socket.add (dart:io-patch/socket_patch.dart:2193:38)
#2      MySQLConnection.close (package:mysql_client/src/mysql_client/connection.dart:976:13)
#3      disconnect (package:test_project/sql.dart:28:23)
#4      _TestPageState.build (package:test_project/main.dart:42:9)
#5      StatefulElement.build (package:flutter/src/widgets/framework.dart:4919:27)
#6      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4806:15)
#7      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#8      Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)

We might need to make sure that the connection gets safely closed based on the design of library.

zim32 commented 2 years ago

It does not close connection after every error right now. MySQL protocol is a mess. Some errors related f.e. to syntax error, should not close connection, I think. Because, why I should close entire connection if it can just continue to make queries? Some errors, mainly logical errors related to bad packet parsing or unexpected packet types should close connection.

Don't know how to do it better

MHShetty commented 2 years ago

Not really certain about how the protocol is designed, but it does close the connection my end once it shares an error packet (probably done by the server).

Thinking about it again, a bad handshake otherwise too implies that the connection wasn't successful, so it's technically better to close the connection/local stream in case of an error packet during the initial handshake.

Not really sure why does it not close on your end, will need to investigate this further.

If you are able to reproduce this issue on your end, please try calling connect again and disconnect to test the behavior.

zim32 commented 2 years ago

I am almost done with error handling. There will be an update in readme about it.

zim32 commented 2 years ago

Ok. All changes are now in dart pub. Release v0.0.20

MHShetty commented 2 years ago

Hi @zim32,

The latest release seems to be completely broken on my end unfortunately.

flutter: Error: Null check operator used on a null value
flutter: #0      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:127:25)
#1      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:124:26)
#2      Future.doWhile.<anonymous closure> (dart:async/future.dart:702:26)
#3      _rootRunUnary (dart:async/zone.dart:1434:47)
#4      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#5      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#6      _CustomZone.bindUnaryCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1281:26)
#7      _rootRunUnary (dart:async/zone.dart:1434:47)
#8      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
<asynchronous suspension>
#9      _CustomZone.bindUnaryCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1281:12)
<asynchronous suspension>
zim32 commented 2 years ago

Oh. One moment. Connection is not covered by tests. Need to cover it

zim32 commented 2 years ago

Fixed in 0.0.21

MHShetty commented 2 years ago

Hi @zim32,

Just tested the latest changes. The error is thrown by the library as expected now πŸ‘

Apart from that,

Not really sure, but I think the error message isn't being parsed correctly. (Reason: The opening single quotes for the message seems to be missing here; and I remember seeing HOST as a part of the error message back then [uncertain if it's a part of the protocol or something]).

flutter: Error: MySQLServerException [1130]: XYZ123' is not allowed to connect to this MySQL server
flutter: #0      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:128:9)
#1      MySQLConnection.connect.<anonymous closure> (package:mysql_client/src/mysql_client/connection.dart:124:26)
#2      Future.doWhile.<anonymous closure> (dart:async/future.dart:702:26)
#3      _rootRunUnary (dart:async/zone.dart:1434:47)
#4      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#5      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#6      _CustomZone.bindUnaryCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1281:26)
#7      _rootRunUnary (dart:async/zone.dart:1434:47)
#8      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
<asynchronous suspension>
#9      _CustomZone.bindUnaryCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1281:12)
<asynchronous suspension>
zim32 commented 2 years ago

I never encounter incorrect error message parsing. F.e. if I change my username I got proper error message:

MySQLServerException [1045]: Access denied for user 'fake'@'172.18.0.1' (using password: YES)

MHShetty commented 2 years ago

Oh unsure in that case then.. Could be an issue with my installation of MySQL.

Either ways, I think the required changes have been pushed to the repository (based on the title of the issue) along with making a release for the same, so we could safely close this issue now.

Thanks a lot for coming out with this library and for providing your valuable time and assistance @zim32!

zim32 commented 2 years ago

Hm. I think I figured out. This is issue with encoding as usual. I've pushed to main branch. If you can test it, by switchig to main branch it will be super cool