@@ -50,7 +50,7 @@ class ZModemMux {
50
50
final Stream <Uint8List > stdout;
51
51
52
52
/// The sink to write data to the underlying data channel.
53
- final StreamSink stdin;
53
+ final StreamSink < List < int >> stdin;
54
54
55
55
/// The callback to receive data that should be written to the terminal.
56
56
ZModemInputHandler ? onTerminalInput;
@@ -71,7 +71,7 @@ class ZModemMux {
71
71
/// space is available in local buffers.
72
72
late final StreamSubscription <Uint8List > _stdoutSubscription;
73
73
74
- late final _terminalInputSink = StreamController <List <int >>(
74
+ late final _terminalSink = StreamController <List <int >>(
75
75
// onPause: _stdoutSubscription.pause,
76
76
// onResume: _stdoutSubscription.resume,
77
77
)
@@ -93,16 +93,13 @@ class ZModemMux {
93
93
/// buffered if a ZModem session is active.
94
94
void terminalWrite (String input) {
95
95
if (_session == null ) {
96
- print ('-->t: ${input }' );
97
96
stdin.add (utf8.encode (input) as Uint8List );
98
97
}
99
98
}
100
99
101
100
/// This is the entry point of multiplexing, dispatching data to ZModem or
102
101
/// terminal depending on the current state.
103
102
void _handleStdout (Uint8List chunk) {
104
- print ('<--: ${chunk .dump ()}' );
105
-
106
103
if (_session != null ) {
107
104
_handleZModem (chunk);
108
105
return ;
@@ -112,7 +109,7 @@ class ZModemMux {
112
109
return ;
113
110
}
114
111
115
- _terminalInputSink .add (chunk);
112
+ _terminalSink .add (chunk);
116
113
}
117
114
118
115
/// Detects a ZModem session in [chunk] and starts it if found. Returns true
@@ -122,12 +119,11 @@ class ZModemMux {
122
119
chunk.listIndexOf (_zmodemReceiverInit);
123
120
124
121
if (index != null ) {
125
- _terminalInputSink .add (Uint8List .sublistView (chunk, 0 , index));
122
+ _terminalSink .add (Uint8List .sublistView (chunk, 0 , index));
126
123
127
124
_session = ZModemCore (
128
- onTrace: print,
129
125
onPlainText: (text) {
130
- _terminalInputSink .add ([text]);
126
+ _terminalSink .add ([text]);
131
127
},
132
128
);
133
129
@@ -138,32 +134,29 @@ class ZModemMux {
138
134
return false ;
139
135
}
140
136
141
- void _handleZModem (Uint8List chunk) {
142
- print ('_handleZModem' );
143
- // print('bytes: ${chunk.map((e) => e.toRadixString(16)).toList()}');
144
-
137
+ void _handleZModem (Uint8List chunk) async {
145
138
for (final event in _session! .receive (chunk)) {
146
- print ('event: $event ' );
147
-
148
139
/// remote is sz
149
140
if (event is ZFileOfferedEvent ) {
150
141
_handleZFileOfferedEvent (event);
151
142
} else if (event is ZFileDataEvent ) {
152
143
_handleZFileDataEvent (event);
153
144
} else if (event is ZFileEndEvent ) {
154
- _handleZFileEndEvent (event);
145
+ await _handleZFileEndEvent (event);
155
146
} else if (event is ZSessionFinishedEvent ) {
156
- _handleZSessionFinishedEvent (event);
147
+ await _handleZSessionFinishedEvent (event);
157
148
}
158
149
159
150
/// remote is rz
160
151
else if (event is ZReadyToSendEvent ) {
161
- _handleFileRequestEvent (event);
152
+ await _handleFileRequestEvent (event);
162
153
} else if (event is ZFileAcceptedEvent ) {
163
- _handleFileAcceptedEvent (event);
154
+ await _handleFileAcceptedEvent (event);
164
155
} else if (event is ZFileSkippedEvent ) {
165
156
_handleFileSkippedEvent (event);
166
157
}
158
+
159
+ _flush ();
167
160
}
168
161
169
162
_flush ();
@@ -174,7 +167,6 @@ class ZModemMux {
174
167
175
168
if (onFileOffer == null ) {
176
169
_session! .skipFile ();
177
- _flush ();
178
170
return ;
179
171
}
180
172
@@ -185,37 +177,38 @@ class ZModemMux {
185
177
_receiveSink! .add (event.data as Uint8List );
186
178
}
187
179
188
- void _handleZFileEndEvent (ZFileEndEvent event) async {
180
+ Future < void > _handleZFileEndEvent (ZFileEndEvent event) async {
189
181
await _closeReceiveSink ();
190
182
}
191
183
192
- void _handleZSessionFinishedEvent (ZSessionFinishedEvent event) async {
184
+ Future <void > _handleZSessionFinishedEvent (ZSessionFinishedEvent event) async {
185
+ _flush ();
193
186
await _reset ();
194
187
}
195
188
196
- void _handleFileRequestEvent (ZReadyToSendEvent event) async {
189
+ Future < void > _handleFileRequestEvent (ZReadyToSendEvent event) async {
197
190
_fileOffers ?? = (await onFileRequest? .call ())? .iterator;
198
191
199
192
_moveToNextOffer ();
200
193
}
201
194
202
- void _handleFileAcceptedEvent (ZFileAcceptedEvent event) async {
195
+ Future < void > _handleFileAcceptedEvent (ZFileAcceptedEvent event) async {
203
196
final data = _fileOffers! .current.accept (event.offset);
204
197
var bytesSent = 0 ;
205
198
206
- final subscription = data.listen (
207
- (chunk) {
208
- bytesSent += chunk.length;
209
- print ('bytesSent: $bytesSent ' );
210
- _session! .sendFileData (chunk);
211
- _flush ();
212
- },
213
- onDone: () {
214
- print ('bytesSent fin: $bytesSent ' );
215
- _session! .finishSending (event.offset + bytesSent);
216
- _flush ();
217
- },
199
+ await stdin.addStream (
200
+ data.transform (
201
+ StreamTransformer <Uint8List , Uint8List >.fromHandlers (
202
+ handleData: (chunk, sink) {
203
+ bytesSent += chunk.length;
204
+ _session! .sendFileData (chunk);
205
+ sink.add (_session! .dataToSend ());
206
+ },
207
+ ),
208
+ ),
218
209
);
210
+
211
+ _session! .finishSending (event.offset + bytesSent);
219
212
}
220
213
221
214
void _handleFileSkippedEvent (ZFileSkippedEvent event) {
@@ -225,16 +218,12 @@ class ZModemMux {
225
218
226
219
/// Sends next file offer if available, or closes the session if not.
227
220
void _moveToNextOffer () {
228
- print ('_offerNextFileIfNeeded' );
229
-
230
221
if (_fileOffers? .moveNext () != true ) {
231
- print ('no more files' );
232
222
_closeSession ();
233
223
return ;
234
224
}
235
225
236
226
_session! .offerFile (_fileOffers! .current.info);
237
- _flush ();
238
227
}
239
228
240
229
/// Creates a [ZModemOffer] ƒrom the info from remote peer that can be used
@@ -258,20 +247,24 @@ class ZModemMux {
258
247
259
248
void _createReceiveSink () {
260
249
_receiveSink = StreamController <Uint8List >(
261
- // onPause: _stdoutSubscription.pause,
262
- onResume: _stdoutSubscription.resume,
250
+ onPause: () {
251
+ // _stdoutSubscription.pause();
252
+ },
253
+ onResume: () {
254
+ // _stdoutSubscription.resume();
255
+ },
263
256
);
264
257
}
265
258
266
259
Future <void > _closeReceiveSink () async {
260
+ _stdoutSubscription.resume ();
267
261
await _receiveSink? .close ();
268
262
_receiveSink = null ;
269
263
}
270
264
271
265
/// Requests remote to close the session.
272
- Future < void > _closeSession () async {
266
+ void _closeSession () {
273
267
_session! .finishSession ();
274
- _flush ();
275
268
}
276
269
277
270
/// Clears all ZModem state.
@@ -284,15 +277,14 @@ class ZModemMux {
284
277
/// Sends all pending data packets to the remote. No data is automatically
285
278
/// sent to the remote without calling this method.
286
279
void _flush () {
287
- final dataToSend = _session! .dataToSend ();
288
- if (dataToSend.isNotEmpty) {
289
- // print('-->: ${dataToSend.dump()}');
280
+ final dataToSend = _session? .dataToSend ();
281
+ if (dataToSend != null && dataToSend.isNotEmpty) {
290
282
stdin.add (dataToSend);
291
283
}
292
284
}
293
285
}
294
286
295
- extension on List <int > {
287
+ extension ListExtension on List <int > {
296
288
String dump () {
297
289
return map ((e) => e.toRadixString (16 ).padLeft (2 , '0' )).join (' ' );
298
290
}
0 commit comments