Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/teraterm/ttpfile/zmodem.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3833 - (show annotations) (download) (as text)
Wed Mar 31 13:44:49 2010 UTC (3 years, 1 month ago) by yutakapon
File MIME type: text/x-csrc
File size: 26689 byte(s)
zmodem.log のログトレース強化(解析用)
1 /* Tera Term
2 Copyright(C) 1994-1998 T. Teranishi
3 Copyright(C) 2010 Tera Term Project
4 All rights reserved. */
5
6 /*
7 "ZMODEM.LOG"の見方:
8  "B"の直後の二桁が Header Type を示す。
9
10 2A 2A 18 42 30 31 30 30 30 30 30 30 32 33 62 65 **.B0100000023be
11 35 30 0D 8A 11
12
13 2A 2A 18 42 30 31 30 30 30 30 30 30 32 33 62 65 **.B0100000023be
14 ^^^^^^^^ZPAD+ZPAD+ZDLE
15 ^^ZHEX
16 ^^^^ZRINIT(2桁で表す)
17 35 30 0D 8A 11
18 ^^^^^CRC
19 */
20
21 /* TTFILE.DLL, ZMODEM protocol */
22 #include "teraterm.h"
23 #include "tttypes.h"
24 #include "ttftypes.h"
25 #include <stdio.h>
26 #include <stdarg.h>
27
28 #include <sys/types.h>
29 #include <sys/stat.h>
30
31 #include "tt_res.h"
32
33 #include "dlglib.h"
34 #include "ftlib.h"
35 #include "ttcommon.h"
36 #include "ttlib.h"
37
38 #define NormalTimeOut 10
39 #define TCPIPTimeOut 0
40 #define IniTimeOut 10
41 #define FinTimeOut 3
42
43 #define ZPAD '*'
44 #define ZDLE 0x18
45 #define ZDLEE 0x58
46 #define ZBIN 'A'
47 #define ZHEX 'B'
48 #define ZBIN32 'C'
49
50 #define ZRQINIT 0
51 #define ZRINIT 1
52 #define ZSINIT 2
53 #define ZACK 3
54 #define ZFILE 4
55 #define ZSKIP 5
56 #define ZNAK 6
57 #define ZABORT 7
58 #define ZFIN 8
59 #define ZRPOS 9
60 #define ZDATA 10
61 #define ZEOF 11
62 #define ZFERR 12
63 #define ZCRC 13
64 #define ZCHALLENGE 14
65 #define ZCOMPL 15
66 #define ZCAN 16
67 #define ZFREECNT 17
68 #define ZCOMMAND 18
69 #define ZSTDERR 19
70
71 #define ZCRCE 'h'
72 #define ZCRCG 'i'
73 #define ZCRCQ 'j'
74 #define ZCRCW 'k'
75 #define ZRUB0 'l'
76 #define ZRUB1 'm'
77
78 #define ZF0 3
79 #define ZF1 2
80 #define ZF2 1
81 #define ZF3 0
82 #define ZP0 0
83 #define ZP1 1
84 #define ZP2 2
85 #define ZP3 3
86
87 #define CANFDX 0x01
88 #define CANOVIO 0x02
89 #define CANBRK 0x04
90 #define CANCRY 0x08
91 #define CANLZW 0x10
92 #define CANFC32 0x20
93 #define ESCCTL 0x40
94 #define ESC8 0x80
95
96 #define ZCBIN 1
97 #define ZCNL 2
98
99 /* ログファイル用バッファ */
100 #define LOGBUFSIZE 256
101
102 static char recvbuf[LOGBUFSIZE];
103 static char sendbuf[LOGBUFSIZE];
104
105 static void add_recvbuf(char *fmt, ...)
106 {
107 va_list arg;
108 char buf[128];
109
110 va_start(arg, fmt);
111 vsnprintf(buf, sizeof(buf), fmt, arg);
112 strncat_s(recvbuf, sizeof(recvbuf), buf, _TRUNCATE);
113 va_end(arg);
114 }
115
116
117 static void show_recvbuf(PFileVar fv)
118 {
119 char *s;
120
121 s = recvbuf;
122 strncat_s(recvbuf, sizeof(recvbuf), "\015\012", _TRUNCATE);
123 _lwrite(fv->LogFile, s, strlen(s));
124
125 memset(recvbuf, 0, sizeof(recvbuf));
126 }
127
128 static void add_sendbuf(char *fmt, ...)
129 {
130 va_list arg;
131 char buf[128];
132
133 va_start(arg, fmt);
134 vsnprintf(buf, sizeof(buf), fmt, arg);
135 strncat_s(sendbuf, sizeof(sendbuf), buf, _TRUNCATE);
136 va_end(arg);
137 }
138
139 static void show_sendbuf(PFileVar fv)
140 {
141 char *s;
142
143 s = sendbuf;
144 strncat_s(sendbuf, sizeof(sendbuf), "\015\012", _TRUNCATE);
145 _lwrite(fv->LogFile, s, strlen(s));
146
147 memset(sendbuf, 0, sizeof(sendbuf));
148 }
149
150 static char *hdrtype_name(int type)
151 {
152 static char *s[] = {
153 "ZRQINIT",
154 "ZRINIT",
155 "ZSINIT",
156 "ZACK",
157 "ZFILE",
158 "ZSKIP",
159 "ZNAK",
160 "ZABORT",
161 "ZFIN",
162 "ZRPOS",
163 "ZDATA",
164 "ZEOF",
165 "ZFERR",
166 "ZCRC",
167 "ZCHALLENGE",
168 "ZCOMPL",
169 "ZCAN",
170 "ZFREECNT",
171 "ZCOMMAND",
172 "ZSTDERR",
173 };
174
175 if (type >= ZRQINIT && type <= ZSTDERR)
176 return (s[type]);
177 else
178 return NULL;
179 }
180
181 int ZRead1Byte(PFileVar fv, PZVar zv, PComVar cv, LPBYTE b)
182 {
183 char *s;
184
185 if (CommRead1Byte(cv, b) == 0)
186 return 0;
187
188 if (fv->LogFlag) {
189 if (fv->LogState == 0) {
190 // 残りのASCII表示を行う
191 fv->FlushLogLineBuf = 1;
192 FTLog1Byte(fv, 0);
193 fv->FlushLogLineBuf = 0;
194
195 show_sendbuf(fv);
196
197 fv->LogState = 1;
198 fv->LogCount = 0;
199 s = "\015\012<<< Received\015\012";
200 _lwrite(fv->LogFile, s, strlen(s));
201 }
202 FTLog1Byte(fv, *b);
203 }
204 /* ignore 0x11, 0x13, 0x81 and 0x83 */
205 if (((*b & 0x7F) == 0x11) || ((*b & 0x7F) == 0x13))
206 return 0;
207 return 1;
208 }
209
210 int ZWrite(PFileVar fv, PZVar zv, PComVar cv, PCHAR B, int C)
211 {
212 int i, j;
213 char *s;
214
215 i = CommBinaryOut(cv, B, C);
216
217 if (fv->LogFlag && (i > 0)) {
218 if (fv->LogState != 0) {
219 // 残りのASCII表示を行う
220 fv->FlushLogLineBuf = 1;
221 FTLog1Byte(fv, 0);
222 fv->FlushLogLineBuf = 0;
223
224 show_recvbuf(fv);
225
226 fv->LogState = 0;
227 fv->LogCount = 0;
228 s = "\015\012Sending >>>\015\012";
229 _lwrite(fv->LogFile, s, strlen(s));
230 }
231 for (j = 0; j <= i - 1; j++)
232 FTLog1Byte(fv, B[j]);
233 }
234 return i;
235 }
236
237 void ZPutHex(PZVar zv, int *i, BYTE b)
238 {
239 if (b <= 0x9f)
240 zv->PktOut[*i] = (b >> 4) + 0x30;
241 else
242 zv->PktOut[*i] = (b >> 4) + 0x57;
243
244 (*i)++;
245 if ((b & 0x0F) <= 0x09)
246 zv->PktOut[*i] = (b & 0x0F) + 0x30;
247 else
248 zv->PktOut[*i] = (b & 0x0F) + 0x57;
249
250 (*i)++;
251 }
252
253 void ZShHdr(PZVar zv, BYTE HdrType)
254 {
255 int i;
256
257 zv->PktOut[0] = ZPAD;
258 zv->PktOut[1] = ZPAD;
259 zv->PktOut[2] = ZDLE;
260 zv->PktOut[3] = ZHEX;
261 zv->PktOutCount = 4;
262 ZPutHex(zv, &(zv->PktOutCount), HdrType);
263 zv->CRC = UpdateCRC(HdrType, 0);
264 for (i = 0; i <= 3; i++) {
265 ZPutHex(zv, &(zv->PktOutCount), zv->TxHdr[i]);
266 zv->CRC = UpdateCRC(zv->TxHdr[i], zv->CRC);
267 }
268 ZPutHex(zv, &(zv->PktOutCount), HIBYTE(zv->CRC));
269 ZPutHex(zv, &(zv->PktOutCount), LOBYTE(zv->CRC));
270 zv->PktOut[zv->PktOutCount] = 0x8D;
271 zv->PktOutCount++;
272 zv->PktOut[zv->PktOutCount] = 0x8A;
273 zv->PktOutCount++;
274
275 if ((HdrType != ZFIN) && (HdrType != ZACK)) {
276 zv->PktOut[zv->PktOutCount] = XON;
277 zv->PktOutCount++;
278 }
279
280 zv->PktOutPtr = 0;
281 zv->Sending = TRUE;
282
283 add_sendbuf("%s: %s", __FUNCTION__, hdrtype_name(HdrType));
284 #if 0
285 if (HdrType == ZRPOS) {
286 LONG pos;
287 memcpy(&pos, zv->TxHdr[ZP0], 4);
288 add_sendbuf(" offset=%ld", pos);
289 }
290 #endif
291 }
292
293 void ZPutBin(PZVar zv, int *i, BYTE b)
294 {
295 switch (b) {
296 case 0x0D:
297 case 0x8D:
298 /* if (zv->CtlEsc ||
299 ((zv->LastSent & 0x7f) == '@')) */
300 // {
301 zv->PktOut[*i] = ZDLE;
302 (*i)++;
303 b = b ^ 0x40;
304 // }
305 break;
306 case 0x10:
307 case 0x11:
308 case 0x13:
309 case ZDLE:
310 case 0x90:
311 case 0x91:
312 case 0x93:
313 zv->PktOut[*i] = ZDLE;
314 (*i)++;
315 b = b ^ 0x40;
316 break;
317 default:
318 if (zv->CtlEsc && ((b & 0x60) == 0)) {
319 zv->PktOut[*i] = ZDLE;
320 (*i)++;
321 b = b ^ 0x40;
322 }
323 }
324 zv->LastSent = b;
325 zv->PktOut[*i] = b;
326 (*i)++;
327 }
328
329 void ZSbHdr(PZVar zv, BYTE HdrType)
330 {
331 int i;
332
333 zv->PktOut[0] = ZPAD;
334 zv->PktOut[1] = ZDLE;
335 zv->PktOut[2] = ZBIN;
336 zv->PktOutCount = 3;
337 ZPutBin(zv, &(zv->PktOutCount), HdrType);
338 zv->CRC = UpdateCRC(HdrType, 0);
339 for (i = 0; i <= 3; i++) {
340 ZPutBin(zv, &(zv->PktOutCount), zv->TxHdr[i]);
341 zv->CRC = UpdateCRC(zv->TxHdr[i], zv->CRC);
342 }
343 ZPutBin(zv, &(zv->PktOutCount), HIBYTE(zv->CRC));
344 ZPutBin(zv, &(zv->PktOutCount), LOBYTE(zv->CRC));
345
346 zv->PktOutPtr = 0;
347 zv->Sending = TRUE;
348
349 add_sendbuf("%s: %s", __FUNCTION__, hdrtype_name(HdrType));
350 }
351
352 void ZStoHdr(PZVar zv, LONG Pos)
353 {
354 zv->TxHdr[ZP0] = LOBYTE(LOWORD(Pos));
355 zv->TxHdr[ZP1] = HIBYTE(LOWORD(Pos));
356 zv->TxHdr[ZP2] = LOBYTE(HIWORD(Pos));
357 zv->TxHdr[ZP3] = HIBYTE(HIWORD(Pos));
358 }
359
360
361 LONG ZRclHdr(PZVar zv)
362 {
363 LONG L;
364
365 L = (BYTE) (zv->RxHdr[ZP3]);
366 L = (L << 8) + (BYTE) (zv->RxHdr[ZP2]);
367 L = (L << 8) + (BYTE) (zv->RxHdr[ZP1]);
368 return ((L << 8) + (BYTE) (zv->RxHdr[ZP0]));
369 }
370
371 void ZSendRInit(PFileVar fv, PZVar zv)
372 {
373 zv->Pos = 0;
374 ZStoHdr(zv, 0);
375 zv->TxHdr[ZF0] = /* CANFC32 | */ CANFDX | CANOVIO;
376 if (zv->CtlEsc)
377 zv->TxHdr[ZF0] = zv->TxHdr[ZF0] | ESCCTL;
378 ZShHdr(zv, ZRINIT);
379 FTSetTimeOut(fv, IniTimeOut);
380 }
381
382 void ZSendRQInit(PFileVar fv, PZVar zv, PComVar cv)
383 {
384 ZStoHdr(zv, 0);
385 ZShHdr(zv, ZRQINIT);
386 }
387
388 void ZSendRPOS(PFileVar fv, PZVar zv)
389 {
390 ZStoHdr(zv, zv->Pos);
391 ZShHdr(zv, ZRPOS);
392 FTSetTimeOut(fv, zv->TimeOut);
393 }
394
395 void ZSendACK(PFileVar fv, PZVar zv)
396 {
397 ZStoHdr(zv, 0);
398 ZShHdr(zv, ZACK);
399 FTSetTimeOut(fv, zv->TimeOut);
400 }
401
402 void ZSendNAK(PZVar zv)
403 {
404 ZStoHdr(zv, 0);
405 ZShHdr(zv, ZNAK);
406 }
407
408 void ZSendEOF(PZVar zv)
409 {
410 ZStoHdr(zv, zv->Pos);
411 ZShHdr(zv, ZEOF);
412 zv->ZState = Z_SendEOF;
413 }
414
415 void ZSendFIN(PZVar zv)
416 {
417 ZStoHdr(zv, 0);
418 ZShHdr(zv, ZFIN);
419 }
420
421 void ZSendCancel(PZVar zv)
422 {
423 int i;
424
425 for (i = 0; i <= 7; i++)
426 zv->PktOut[i] = ZDLE;
427 for (i = 8; i <= 17; i++)
428 zv->PktOut[i] = 0x08;
429 zv->PktOutCount = 18;
430 zv->PktOutPtr = 0;
431 zv->Sending = TRUE;
432 zv->ZState = Z_Cancel;
433
434 add_sendbuf("%s: ", __FUNCTION__);
435 }
436
437 void ZSendInitHdr(PZVar zv)
438 {
439 ZStoHdr(zv, 0);
440 if (zv->CtlEsc)
441 zv->TxHdr[ZF0] = ESCCTL;
442 ZShHdr(zv, ZSINIT);
443 zv->ZState = Z_SendInitHdr;
444 }
445
446 void ZSendInitDat(PZVar zv)
447 {
448 zv->CRC = 0;
449 zv->PktOutCount = 0;
450 ZPutBin(zv, &(zv->PktOutCount), 0);
451 zv->CRC = UpdateCRC(0, zv->CRC);
452
453 zv->PktOut[zv->PktOutCount] = ZDLE;
454 zv->PktOutCount++;
455 zv->PktOut[zv->PktOutCount] = ZCRCW;
456 zv->PktOutCount++;
457 zv->CRC = UpdateCRC(ZCRCW, zv->CRC);
458
459 ZPutBin(zv, &(zv->PktOutCount), HIBYTE(zv->CRC));
460 ZPutBin(zv, &(zv->PktOutCount), LOBYTE(zv->CRC));
461
462 zv->PktOutPtr = 0;
463 zv->Sending = TRUE;
464 zv->ZState = Z_SendInitDat;
465
466 add_sendbuf("%s: ", __FUNCTION__);
467 }
468
469 void ZSendFileHdr(PZVar zv)
470 {
471 ZStoHdr(zv, 0);
472 if (zv->BinFlag)
473 zv->TxHdr[ZF0] = ZCBIN; /* binary file */
474 else
475 zv->TxHdr[ZF0] = ZCNL; /* text file, convert newline */
476 ZSbHdr(zv, ZFILE);
477 zv->ZState = Z_SendFileHdr;
478 }
479
480 void ZSendFileDat(PFileVar fv, PZVar zv)
481 {
482 int i, j;
483 struct _stat st;
484
485 if (!fv->FileOpen) {
486 ZSendCancel(zv);
487 return;
488 }
489 SetDlgItemText(fv->HWin, IDC_PROTOFNAME, &(fv->FullName[fv->DirLen]));
490
491 /* file name */
492 strncpy_s(zv->PktOut, sizeof(zv->PktOut), &(fv->FullName[fv->DirLen]),
493 _TRUNCATE);
494 FTConvFName(zv->PktOut); // replace ' ' by '_' in FName
495 zv->PktOutCount = strlen(zv->PktOut);
496 zv->CRC = 0;
497 for (i = 0; i <= zv->PktOutCount - 1; i++)
498 zv->CRC = UpdateCRC(zv->PktOut[i], zv->CRC);
499 ZPutBin(zv, &(zv->PktOutCount), 0);
500 zv->CRC = UpdateCRC(0, zv->CRC);
501 /* file size */
502 fv->FileSize = GetFSize(fv->FullName);
503
504 /* timestamp */
505 _stat(fv->FullName, &st);
506
507 // ファイルのタイムスタンプとパーミッションも送るようにした。(2007.12.20 maya, yutaka)
508 _snprintf_s(&(zv->PktOut[zv->PktOutCount]),
509 sizeof(zv->PktOut) - zv->PktOutCount, _TRUNCATE,
510 "%lu %lo %o", fv->FileSize, (long) st.st_mtime,
511 0644 | _S_IFREG);
512 j = strlen(&(zv->PktOut[zv->PktOutCount])) - 1;
513 for (i = 0; i <= j; i++) {
514 zv->CRC = UpdateCRC(zv->PktOut[zv->PktOutCount], zv->CRC);
515 zv->PktOutCount++;
516 }
517
518 ZPutBin(zv, &(zv->PktOutCount), 0);
519 zv->CRC = UpdateCRC(0, zv->CRC);
520 zv->PktOut[zv->PktOutCount] = ZDLE;
521 zv->PktOutCount++;
522 zv->PktOut[zv->PktOutCount] = ZCRCW;
523 zv->PktOutCount++;
524 zv->CRC = UpdateCRC(ZCRCW, zv->CRC);
525
526 ZPutBin(zv, &(zv->PktOutCount), HIBYTE(zv->CRC));
527 ZPutBin(zv, &(zv->PktOutCount), LOBYTE(zv->CRC));
528
529 zv->PktOutPtr = 0;
530 zv->Sending = TRUE;
531 zv->ZState = Z_SendFileDat;
532
533 fv->ByteCount = 0;
534 fv->ProgStat = 0;
535 SetDlgNum(fv->HWin, IDC_PROTOBYTECOUNT, fv->ByteCount);
536 SetDlgPercent(fv->HWin, IDC_PROTOPERCENT, IDC_PROTOPROGRESS,
537 fv->ByteCount, fv->FileSize, &fv->ProgStat);
538
539 add_sendbuf("%s: ZFILE: ZF0=%x ZF1=%x ZF2=%x file=%s size=%lu",
540 __FUNCTION__,
541 zv->TxHdr[ZF0], zv->TxHdr[ZF1],zv->TxHdr[ZF2],
542 &(fv->FullName[fv->DirLen]), fv->FileSize);
543 }
544
545 void ZSendDataHdr(PZVar zv)
546 {
547 ZStoHdr(zv, zv->Pos);
548 ZSbHdr(zv, ZDATA);
549 zv->ZState = Z_SendDataHdr;
550 }
551
552 void ZSendDataDat(PFileVar fv, PZVar zv)
553 {
554 int c;
555 BYTE b;
556
557 if (zv->Pos >= fv->FileSize) {
558 zv->Pos = fv->FileSize;
559 ZSendEOF(zv);
560 return;
561 }
562
563 fv->ByteCount = zv->Pos;
564
565 if (fv->FileOpen && (zv->Pos < fv->FileSize))
566 _llseek(fv->FileHandle, zv->Pos, 0);
567
568 zv->CRC = 0;
569 zv->PktOutCount = 0;
570 do {
571 c = _lread(fv->FileHandle, &b, 1);
572 if (c > 0) {
573 ZPutBin(zv, &(zv->PktOutCount), b);
574 zv->CRC = UpdateCRC(b, zv->CRC);
575 fv->ByteCount++;
576 }
577 } while ((c != 0) && (zv->PktOutCount <= zv->MaxDataLen - 2));
578
579 SetDlgNum(fv->HWin, IDC_PROTOBYTECOUNT, fv->ByteCount);
580 SetDlgPercent(fv->HWin, IDC_PROTOPERCENT, IDC_PROTOPROGRESS,
581 fv->ByteCount, fv->FileSize, &fv->ProgStat);
582 zv->Pos = fv->ByteCount;
583
584 zv->PktOut[zv->PktOutCount] = ZDLE;
585 zv->PktOutCount++;
586 if (zv->Pos >= fv->FileSize)
587 b = ZCRCE;
588 else if ((zv->WinSize >= 0) && (zv->Pos - zv->LastPos > zv->WinSize))
589 b = ZCRCQ;
590 else
591 b = ZCRCG;
592 zv->PktOut[zv->PktOutCount] = b;
593 zv->PktOutCount++;
594 zv->CRC = UpdateCRC(b, zv->CRC);
595
596 ZPutBin(zv, &(zv->PktOutCount), HIBYTE(zv->CRC));
597 ZPutBin(zv, &(zv->PktOutCount), LOBYTE(zv->CRC));
598
599 zv->PktOutPtr = 0;
600 zv->Sending = TRUE;
601 if (b == ZCRCQ)
602 zv->ZState = Z_SendDataDat2; /* wait response from receiver */
603 else
604 zv->ZState = Z_SendDataDat;
605
606 add_sendbuf("%s: ", __FUNCTION__);
607 }
608
609 void ZInit(PFileVar fv, PZVar zv, PComVar cv, PTTSet ts) {
610 int Max;
611 char uimsg[MAX_UIMSG];
612
613 zv->CtlEsc = ((ts->FTFlag & FT_ZESCCTL) != 0);
614 zv->MaxDataLen = ts->ZmodemDataLen;
615 zv->WinSize = ts->ZmodemWinSize;
616 fv->LogFlag = ((ts->LogFlag & LOG_Z) != 0);
617
618 if (zv->ZMode == IdZAuto) {
619 CommInsert1Byte(cv, 'B');
620 CommInsert1Byte(cv, ZDLE);
621 CommInsert1Byte(cv, ZPAD);
622 zv->ZMode = IdZReceive;
623 }
624
625 strncpy_s(fv->DlgCaption, sizeof(fv->DlgCaption), "Tera Term: ",
626 _TRUNCATE);
627 switch (zv->ZMode) {
628 case IdZSend:
629 get_lang_msg("FILEDLG_TRANS_TITLE_ZSEND", uimsg, sizeof(uimsg),
630 TitZSend, UILanguageFile);
631 strncat_s(fv->DlgCaption, sizeof(fv->DlgCaption), uimsg,
632 _TRUNCATE);
633 break;
634 case IdZReceive:
635 get_lang_msg("FILEDLG_TRANS_TITLE_ZRCV", uimsg, sizeof(uimsg),
636 TitZRcv, UILanguageFile);
637 strncat_s(fv->DlgCaption, sizeof(fv->DlgCaption), uimsg,
638 _TRUNCATE);
639 break;
640 }
641
642 SetWindowText(fv->HWin, fv->DlgCaption);
643 SetDlgItemText(fv->HWin, IDC_PROTOPROT, "ZMODEM");
644
645 InitDlgProgress(fv->HWin, IDC_PROTOPROGRESS, &fv->ProgStat);
646
647 fv->FileSize = 0;
648
649 zv->PktOutCount = 0;
650 zv->Pos = 0;
651 zv->LastPos = 0;
652 zv->ZPktState = Z_PktGetPAD;
653 zv->Sending = FALSE;
654 zv->LastSent = 0;
655 zv->CanCount = 5;
656
657 if (zv->MaxDataLen <= 0)
658 zv->MaxDataLen = 1024;
659 if (zv->MaxDataLen < 64)
660 zv->MaxDataLen = 64;
661
662 /* Time out & Max block size */
663 if (cv->PortType == IdTCPIP) {
664 zv->TimeOut = TCPIPTimeOut;
665 Max = 1024;
666 } else {
667 zv->TimeOut = NormalTimeOut;
668 switch (ts->Baud) {
669 case IdBaud110:
670 Max = 64;
671 break;
672 case IdBaud300:
673 Max = 128;
674 break;
675 case IdBaud600:
676 case IdBaud1200:
677 Max = 256;
678 break;
679 case IdBaud2400:
680 Max = 512;
681 break;
682 default:
683 Max = 1024;
684 }
685 }
686 if (zv->MaxDataLen > Max)
687 zv->MaxDataLen = Max;
688
689 if (fv->LogFlag)
690 fv->LogFile = _lcreat("ZMODEM.LOG", 0);
691 fv->LogState = 0;
692 fv->LogCount = 0;
693
694 switch (zv->ZMode) {
695 case IdZReceive:
696 zv->ZState = Z_RecvInit;
697 ZSendRInit(fv, zv);
698 break;
699 case IdZSend:
700 zv->ZState = Z_SendInit;
701
702 // ファイル送信開始前に、"rz"を自動的に呼び出す。(2007.12.21 yutaka)
703 if (ts->ZModemRcvCommand[0] != '\0') {
704 ZWrite(fv, zv, cv, ts->ZModemRcvCommand,
705 strlen(ts->ZModemRcvCommand));
706 ZWrite(fv, zv, cv, "\015", 1);
707 }
708
709 ZSendRQInit(fv, zv, cv);
710 break;
711 }
712 }
713
714 void ZTimeOutProc(PFileVar fv, PZVar zv, PComVar cv)
715 {
716 switch (zv->ZState) {
717 case Z_RecvInit:
718 ZSendRInit(fv, zv);
719 break;
720 case Z_RecvInit2:
721 ZSendACK(fv, zv); /* Ack for ZSINIT */
722 break;
723 case Z_RecvData:
724 ZSendRPOS(fv, zv);
725 break;
726 case Z_RecvFIN:
727 zv->ZState = Z_End;
728 break;
729 }
730 }
731
732 BOOL ZCheckHdr(PFileVar fv, PZVar zv)
733 {
734 int i;
735 BOOL Ok;
736
737 if (zv->CRC32) {
738 zv->CRC3 = 0xFFFFFFFF;
739 for (i = 0; i <= 8; i++)
740 zv->CRC3 = UpdateCRC32(zv->PktIn[i], zv->CRC3);
741 Ok = zv->CRC3 == 0xDEBB20E3;
742 } else {
743 zv->CRC = 0;
744 for (i = 0; i <= 6; i++)
745 zv->CRC = UpdateCRC(zv->PktIn[i], zv->CRC);
746 Ok = zv->CRC == 0;
747 }
748
749 if (!Ok) {
750 switch (zv->ZState) {
751 case Z_RecvInit:
752 ZSendRInit(fv, zv);
753 break;
754 case Z_RecvData:
755 ZSendRPOS(fv, zv);
756 break;
757 }
758 }
759 zv->RxType = zv->PktIn[0];
760 for (i = 1; i <= 4; i++)
761 zv->RxHdr[i - 1] = zv->PktIn[i];
762
763 return Ok;
764 }
765
766 void ZParseRInit(PFileVar fv, PZVar zv)
767 {
768 int Max;
769
770 if ((zv->ZState != Z_SendInit) && (zv->ZState != Z_SendEOF))
771 return;
772
773 if (fv->FileOpen) // close previous file
774 {
775 _lclose(fv->FileHandle);
776 fv->FileOpen = FALSE;
777 }
778
779 if (!GetNextFname(fv)) {
780 zv->ZState = Z_SendFIN;
781 ZSendFIN(zv);
782 return;
783 }
784
785 /* file open */
786 fv->FileHandle = _lopen(fv->FullName, OF_READ);
787 fv->FileOpen = fv->FileHandle > 0;
788
789 if (zv->CtlEsc) {
790 if ((zv->RxHdr[ZF0] & ESCCTL) == 0) {
791 zv->ZState = Z_SendInitHdr;
792 ZSendInitHdr(zv);
793 return;
794 }
795 } else
796 zv->CtlEsc = (zv->RxHdr[ZF0] & ESCCTL) != 0;
797
798 Max = (zv->RxHdr[ZP1] << 8) + zv->RxHdr[ZP0];
799 if (Max <= 0)
800 Max = 1024;
801 if (zv->MaxDataLen > Max)
802 zv->MaxDataLen = Max;
803
804 zv->ZState = Z_SendFileHdr;
805 ZSendFileHdr(zv);
806 }
807
808 BOOL ZParseSInit(PZVar zv)
809 {
810 if (zv->ZState != Z_RecvInit)
811 return FALSE;
812 zv->ZState = Z_RecvInit2;
813 zv->CtlEsc = zv->CtlEsc || ((zv->RxHdr[ZF0] & ESCCTL) != 0);
814 return TRUE;
815 }
816
817 void ZParseHdr(PFileVar fv, PZVar zv, PComVar cv)
818 {
819 add_recvbuf("%s: RxType %s ", __FUNCTION__, hdrtype_name(zv->RxType));
820
821 switch (zv->RxType) {
822 case ZRQINIT:
823 if (zv->ZState == Z_RecvInit)
824 ZSendRInit(fv, zv);
825 break;
826 case ZRINIT:
827 ZParseRInit(fv, zv);
828 break;
829 case ZSINIT:
830 zv->ZPktState = Z_PktGetData;
831 if (zv->ZState == Z_RecvInit)
832 FTSetTimeOut(fv, IniTimeOut);
833 break;
834 case ZACK:
835 switch (zv->ZState) {
836 case Z_SendInitDat:
837 ZSendFileHdr(zv);
838 break;
839 case Z_SendDataDat2:
840 zv->LastPos = ZRclHdr(zv);
841 if (zv->Pos == zv->LastPos)
842 ZSendDataDat(fv, zv);
843 else {
844 zv->Pos = zv->LastPos;
845 ZSendDataHdr(zv);
846 }
847 break;
848 }
849 break;
850 case ZFILE:
851 zv->ZPktState = Z_PktGetData;
852 if ((zv->ZState == Z_RecvInit) || (zv->ZState == Z_RecvInit2)) {
853 zv->BinFlag = zv->RxHdr[ZF0] != ZCNL;
854 FTSetTimeOut(fv, IniTimeOut);
855 }
856 break;
857 case ZSKIP:
858 if (fv->FileOpen) {
859 _lclose(fv->FileHandle);
860 // サーバ側に存在するファイルを送信しようとすると、ZParseRInit()で二重closeになるため、
861 // ここでフラグを落としておく。 (2007.12.20 yutaka)
862 fv->FileOpen = FALSE;
863 }
864 ZStoHdr(zv, 0);
865 if (zv->CtlEsc)
866 zv->RxHdr[ZF0] = ESCCTL;
867 zv->ZState = Z_SendInit;
868 ZParseRInit(fv, zv);
869 break;
870 case ZNAK:
871 switch (zv->ZState) {
872 case Z_SendInitHdr:
873 case Z_SendInitDat:
874 ZSendInitHdr(zv);
875 break;
876 case Z_SendFileHdr:
877 case Z_SendFileDat:
878 ZSendFileHdr(zv);
879 break;
880 }
881 break;
882 case ZABORT:
883 case ZFERR:
884 if (zv->ZMode == IdZSend) {
885 zv->ZState = Z_SendFIN;
886 ZSendFIN(zv);
887 }
888 break;
889 case ZFIN:
890 fv->Success = TRUE;
891 if (zv->ZMode == IdZReceive) {
892 zv->ZState = Z_RecvFIN;
893 ZSendFIN(zv);
894 zv->CanCount = 2;
895 FTSetTimeOut(fv, FinTimeOut);
896 } else {
897 zv->ZState = Z_End;
898 ZWrite(fv, zv, cv, "OO", 2);
899 }
900 break;
901 case ZRPOS:
902 switch (zv->ZState) {
903 case Z_SendFileDat:
904 case Z_SendDataHdr:
905 case Z_SendDataDat:
906 case Z_SendDataDat2:
907 case Z_SendEOF:
908 zv->Pos = ZRclHdr(zv);
909 zv->LastPos = zv->Pos;
910 add_recvbuf(" pos=%ld", zv->Pos);
911 ZSendDataHdr(zv);
912 break;
913 }
914 break;
915 case ZDATA:
916 if (zv->Pos != ZRclHdr(zv)) {
917 ZSendRPOS(fv, zv);
918 return;
919 } else {
920 FTSetTimeOut(fv, zv->TimeOut);
921 zv->ZPktState = Z_PktGetData;
922 }
923 break;
924 case ZEOF:
925 if (zv->Pos != ZRclHdr(zv)) {
926 ZSendRPOS(fv, zv);
927 return;
928 } else {
929 if (fv->FileOpen) {
930 if (zv->CRRecv) {
931 zv->CRRecv = FALSE;
932 _lwrite(fv->FileHandle, "\012", 1);
933 }
934 _lclose(fv->FileHandle);
935 fv->FileOpen = FALSE;
936 }
937 zv->ZState = Z_RecvInit;
938 ZSendRInit(fv, zv);
939 }
940 break;
941 }
942 zv->Quoted = FALSE;
943 zv->CRC = 0;
944 zv->CRC3 = 0xFFFFFFFF;
945 zv->PktInPtr = 0;
946 zv->PktInCount = 0;
947 }
948
949 BOOL ZParseFile(PFileVar fv, PZVar zv)
950 {
951 BYTE b;
952 int i, j;
953
954 if ((zv->ZState != Z_RecvInit) && (zv->ZState != Z_RecvInit2))
955 return FALSE;
956 /* kill timer */
957 FTSetTimeOut(fv, 0);
958 zv->CRRecv = FALSE;
959
960 /* file name */
961 zv->PktIn[zv->PktInPtr] = 0; /* for safety */
962
963 GetFileNamePos(zv->PktIn, &i, &j);
964 strncpy_s(&(fv->FullName[fv->DirLen]),
965 sizeof(fv->FullName) - fv->DirLen, &(zv->PktIn[j]),
966 _TRUNCATE);
967 /* file open */
968 if (!FTCreateFile(fv))
969 return FALSE;
970
971 /* file size */
972 i = strlen(zv->PktIn) + 1;
973 do {
974 b = zv->PktIn[i];
975 if ((b >= 0x30) && (b <= 0x39))
976 fv->FileSize = fv->FileSize * 10 + b - 0x30;
977 i++;
978 } while ((b >= 0x30) && (b <= 0x39));
979
980 zv->Pos = 0;
981 fv->ByteCount = 0;
982 ZStoHdr(zv, 0);
983 zv->ZState = Z_RecvData;
984
985 SetDlgNum(fv->HWin, IDC_PROTOBYTECOUNT, 0);
986 if (fv->FileSize > 0)
987 SetDlgPercent(fv->HWin, IDC_PROTOPERCENT, IDC_PROTOPROGRESS,
988 0, fv->FileSize, &fv->ProgStat);
989 /* set timeout for data */
990 FTSetTimeOut(fv, zv->TimeOut);
991 return TRUE;
992 }
993
994 BOOL ZWriteData(PFileVar fv, PZVar zv)
995 {
996 int i;
997 BYTE b;
998
999 if (zv->ZState != Z_RecvData)
1000 return FALSE;
1001 /* kill timer */
1002 FTSetTimeOut(fv, 0);
1003
1004 if (zv->BinFlag)
1005 _lwrite(fv->FileHandle, zv->PktIn, zv->PktInPtr);
1006 else
1007 for (i = 0; i <= zv->PktInPtr - 1; i++) {
1008 b = zv->PktIn[i];
1009 if ((b == 0x0A) && (!zv->CRRecv))
1010 _lwrite(fv->FileHandle, "\015", 1);
1011 if (zv->CRRecv && (b != 0x0A))
1012 _lwrite(fv->FileHandle, "\012", 1);
1013 zv->CRRecv = b == 0x0D;
1014 _lwrite(fv->FileHandle, &b, 1);
1015 }
1016
1017 fv->ByteCount = fv->ByteCount + zv->PktInPtr;
1018 zv->Pos = zv->Pos + zv->PktInPtr;
1019 ZStoHdr(zv, zv->Pos);
1020 SetDlgNum(fv->HWin, IDC_PROTOBYTECOUNT, fv->ByteCount);
1021 if (fv->FileSize > 0)
1022 SetDlgPercent(fv->HWin, IDC_PROTOPERCENT, IDC_PROTOPROGRESS,
1023 fv->ByteCount, fv->FileSize, &fv->ProgStat);
1024
1025 /* set timeout for data */
1026 FTSetTimeOut(fv, zv->TimeOut);
1027 return TRUE;
1028 }
1029
1030 void ZCheckData(PFileVar fv, PZVar zv)
1031 {
1032 BOOL Ok;
1033
1034 /* check CRC */
1035 if (zv->CRC32 && (zv->CRC3 != 0xDEBB20E3) || (!zv->CRC32 && (zv->CRC != 0))) { /* CRC */
1036 switch (zv->ZState) {
1037 case Z_RecvInit:
1038 case Z_RecvInit2:
1039 ZSendNAK(zv);
1040 break;
1041 case Z_RecvData:
1042 ZSendRPOS(fv, zv);
1043 break;
1044 }
1045 zv->ZPktState = Z_PktGetPAD;
1046 return;
1047 }
1048 /* parse data */
1049 switch (zv->RxType) {
1050 case ZSINIT:
1051 Ok = ZParseSInit(zv);
1052 break;
1053 case ZFILE:
1054 Ok = ZParseFile(fv, zv);
1055 break;
1056 case ZDATA:
1057 Ok = ZWriteData(fv, zv);
1058 break;
1059 default:
1060 Ok = FALSE;
1061 }
1062
1063 if (!Ok) {
1064 zv->ZPktState = Z_PktGetPAD;
1065 return;
1066 }
1067
1068 if (zv->RxType == ZFILE)
1069 ZShHdr(zv, ZRPOS);
1070
1071 /* next state */
1072 switch (zv->TERM) {
1073 case ZCRCE:
1074 zv->ZPktState = Z_PktGetPAD;
1075 break;
1076 case ZCRCG:
1077 zv->ZPktState = Z_PktGetData;
1078 break;
1079 case ZCRCQ:
1080 zv->ZPktState = Z_PktGetData;
1081 if (zv->RxType != ZFILE)
1082 ZShHdr(zv, ZACK);
1083 break;
1084 case ZCRCW:
1085 zv->ZPktState = Z_PktGetPAD;
1086 if (zv->RxType != ZFILE)
1087 ZShHdr(zv, ZACK);
1088 break;
1089 default:
1090 zv->ZPktState = Z_PktGetPAD;
1091 }
1092
1093 if (zv->ZPktState == Z_PktGetData) {
1094 zv->Quoted = FALSE;
1095 zv->CRC = 0;
1096 zv->CRC3 = 0xFFFFFFFF;
1097 zv->PktInPtr = 0;
1098 zv->PktInCount = 0;
1099 }
1100 }
1101
1102 BOOL ZParse(PFileVar fv, PZVar zv, PComVar cv)
1103 {
1104 BYTE b;
1105 int c;
1106
1107 do {
1108 /* Send packet */
1109 if (zv->Sending) {
1110 c = 1;
1111 while ((c > 0) && (zv->PktOutCount > 0)) {
1112 c = ZWrite(fv, zv, cv, &(zv->PktOut[zv->PktOutPtr]),
1113 zv->PktOutCount);
1114 zv->PktOutPtr = zv->PktOutPtr + c;
1115 zv->PktOutCount = zv->PktOutCount - c;
1116 }
1117 if (zv->PktOutCount <= 0)
1118 zv->Sending = FALSE;
1119 if ((zv->ZMode == IdZReceive) && (zv->PktOutCount > 0))
1120 return TRUE;
1121 }
1122
1123 c = ZRead1Byte(fv, zv, cv, &b);
1124 while (c > 0) {
1125 if (zv->ZState == Z_RecvFIN) {
1126 if (b == 'O')
1127 zv->CanCount--;
1128 if (zv->CanCount <= 0) {
1129 zv->ZState = Z_End;
1130 return FALSE;
1131 }
1132 } else
1133 switch (b) {
1134 case ZDLE:
1135 zv->CanCount--;
1136 if (zv->CanCount <= 0) {
1137 zv->ZState = Z_End;
1138 return FALSE;
1139 }
1140 break;
1141 default:
1142 zv->CanCount = 5;
1143 }
1144
1145 switch (zv->ZPktState) {
1146 case Z_PktGetPAD:
1147 switch (b) {
1148 case ZPAD:
1149 zv->ZPktState = Z_PktGetDLE;
1150 break;
1151 }
1152 break;
1153 case Z_PktGetDLE:
1154 switch (b) {
1155 case ZPAD:
1156 break;
1157 case ZDLE:
1158 zv->ZPktState = Z_PktHdrFrm;
1159 break;
1160 default:
1161 zv->ZPktState = Z_PktGetPAD;
1162 }
1163 break;
1164 case Z_PktHdrFrm: /* Get header format type */
1165 switch (b) {
1166 case ZBIN:
1167 zv->CRC32 = FALSE;
1168 zv->PktInCount = 7;
1169 zv->ZPktState = Z_PktGetBin;
1170 break;
1171 case ZHEX:
1172 zv->HexLo = FALSE;
1173 zv->CRC32 = FALSE;
1174 zv->PktInCount = 7;
1175 zv->ZPktState = Z_PktGetHex;
1176 break;
1177 case ZBIN32:
1178 zv->CRC32 = TRUE;
1179 zv->PktInCount = 9;
1180 zv->ZPktState = Z_PktGetBin;
1181 break;
1182 default:
1183 zv->ZPktState = Z_PktGetPAD;
1184 }
1185 zv->Quoted = FALSE;
1186 zv->PktInPtr = 0;
1187 break;
1188 case Z_PktGetBin:
1189 switch (b) {
1190 case ZDLE:
1191 zv->Quoted = TRUE;
1192 break;
1193 default:
1194 if (zv->Quoted) {
1195 b = b ^ 0x40;
1196 zv->Quoted = FALSE;
1197 }
1198 zv->PktIn[zv->PktInPtr] = b;
1199 zv->PktInPtr++;
1200 zv->PktInCount--;
1201 if (zv->PktInCount == 0) {
1202 zv->ZPktState = Z_PktGetPAD;
1203 if (ZCheckHdr(fv, zv))
1204 ZParseHdr(fv, zv, cv);
1205 }
1206 }
1207 break;
1208 case Z_PktGetHex:
1209 if (b <= '9')
1210 b = b - 0x30;
1211 else if ((b >= 'a') && (b <= 'f'))
1212 b = b - 0x57;
1213 else {
1214 zv->ZPktState = Z_PktGetPAD;
1215 return TRUE;
1216 }
1217
1218 if (zv->HexLo) {
1219 zv->PktIn[zv->PktInPtr] = zv->PktIn[zv->PktInPtr] + b;
1220 zv->HexLo = FALSE;
1221 zv->PktInPtr++;
1222 zv->PktInCount--;
1223 if (zv->PktInCount <= 0) {
1224 zv->ZPktState = Z_PktGetHexEOL;
1225 zv->PktInCount = 2;
1226 }
1227 } else {
1228 zv->PktIn[zv->PktInPtr] = b << 4;
1229 zv->HexLo = TRUE;
1230 }
1231 break;
1232 case Z_PktGetHexEOL:
1233 zv->PktInCount--;
1234 if (zv->PktInCount <= 0) {
1235 zv->ZPktState = Z_PktGetPAD;
1236 if (ZCheckHdr(fv, zv))
1237 ZParseHdr(fv, zv, cv);
1238 }
1239 break;
1240 case Z_PktGetData:
1241 switch (b) {
1242 case ZDLE:
1243 zv->Quoted = TRUE;
1244 break;
1245 default:
1246 if (zv->Quoted) {
1247 switch (b) {
1248 case ZCRCE:
1249 case ZCRCG:
1250 case ZCRCQ:
1251 case ZCRCW:
1252 zv->TERM = b;
1253 if (zv->CRC32)
1254 zv->PktInCount = 4;
1255 else
1256 zv->PktInCount = 2;
1257 zv->ZPktState = Z_PktGetCRC;
1258 break;
1259 case ZRUB0:
1260 b = 0x7F;
1261 break;
1262 case ZRUB1:
1263 b = 0xFF;
1264 break;
1265 default:
1266 b = b ^ 0x40;
1267 }
1268 zv->Quoted = FALSE;
1269 }
1270 if (zv->CRC32)
1271 zv->CRC3 = UpdateCRC32(b, zv->CRC3);
1272 else
1273 zv->CRC = UpdateCRC(b, zv->CRC);
1274 if (zv->ZPktState == Z_PktGetData) {
1275 if (zv->PktInPtr < 1024) {
1276 zv->PktIn[zv->PktInPtr] = b;
1277 zv->PktInPtr++;
1278 } else
1279 zv->ZPktState = Z_PktGetPAD;
1280 }
1281 }
1282 break;
1283 case Z_PktGetCRC:
1284 switch (b) {
1285 case ZDLE:
1286 zv->Quoted = TRUE;
1287 break;
1288 default:
1289 if (zv->Quoted) {
1290 switch (b) {
1291 case ZRUB0:
1292 b = 0x7F;
1293 break;
1294 case ZRUB1:
1295 b = 0xFF;
1296 break;
1297 default:
1298 b = b ^ 0x40;
1299 }
1300 zv->Quoted = FALSE;
1301 }
1302 if (zv->CRC32)
1303 zv->CRC3 = UpdateCRC32(b, zv->CRC3);
1304 else
1305 zv->CRC = UpdateCRC(b, zv->CRC);
1306 zv->PktInCount--;
1307 if (zv->PktInCount <= 0)
1308 ZCheckData(fv, zv);
1309 }
1310 break;
1311 }
1312 c = ZRead1Byte(fv, zv, cv, &b);
1313 }
1314
1315 if (!zv->Sending)
1316 switch (zv->ZState) {
1317 case Z_SendInitHdr:
1318 ZSendInitDat(zv);
1319 break;
1320 case Z_SendFileHdr:
1321 ZSendFileDat(fv, zv);
1322 break;
1323 case Z_SendDataHdr:
1324 case Z_SendDataDat:
1325 ZSendDataDat(fv, zv);
1326 break;
1327 case Z_Cancel:
1328 zv->ZState = Z_End;
1329 break;
1330 }
1331
1332 if (zv->Sending && (zv->PktOutCount > 0))
1333 return TRUE;
1334 } while (zv->Sending);
1335
1336 if (zv->ZState == Z_End)
1337 return FALSE;
1338 return TRUE;
1339 }
1340
1341 void ZCancel(PZVar zv)
1342 {
1343 ZSendCancel(zv);
1344 }

SourceForge.JP is a Japanese version of SourceForge.net. For developments that are not related to Japan, we recommend you to use SourceForge.net.