Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2012 lines
46 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. arap.c
  5. Abstract:
  6. This module implements the v42bis compression/decompression routines
  7. used by ARAP (adapted from fcr's code)
  8. Author:
  9. Shirish Koti
  10. Revision History:
  11. 15 Nov 1996 Initial Version
  12. --*/
  13. #include "atalk.h"
  14. #ifdef ALLOC_PRAGMA
  15. #pragma alloc_text(PAGE_ARAP, v42bis_init_dictionary)
  16. #pragma alloc_text(PAGE_ARAP, v42bis_init)
  17. #pragma alloc_text(PAGE_ARAP, v42bis_decode_codeword)
  18. #pragma alloc_text(PAGE_ARAP, v42bis_decode_codeword_flush)
  19. #pragma alloc_text(PAGE_ARAP, v42bis_encode_codeword)
  20. #pragma alloc_text(PAGE_ARAP, v42bis_encode_codeword_flush)
  21. #pragma alloc_text(PAGE_ARAP, v42bis_encode_value)
  22. #pragma alloc_text(PAGE_ARAP, v42bis_apply_compression_test)
  23. #pragma alloc_text(PAGE_ARAP, v42bis_encode_buffer)
  24. #pragma alloc_text(PAGE_ARAP, v42bis_encode_flush)
  25. #pragma alloc_text(PAGE_ARAP, v42bis_transition_to_compressed)
  26. #pragma alloc_text(PAGE_ARAP, v42bis_transition_to_transparent)
  27. #pragma alloc_text(PAGE_ARAP, v42bis_signal_reset)
  28. #pragma alloc_text(PAGE_ARAP, v42bis_decode_match)
  29. #pragma alloc_text(PAGE_ARAP, v42bis_decode_buffer)
  30. #pragma alloc_text(PAGE_ARAP, v42bis_decode_flush)
  31. #pragma alloc_text(PAGE_ARAP, v42bis_init_buffer)
  32. #pragma alloc_text(PAGE_ARAP, v42bis_connection_init)
  33. #pragma alloc_text(PAGE_ARAP, v42bis_connection_init_buffers)
  34. #pragma alloc_text(PAGE_ARAP, v42bis_connection_init_push)
  35. #pragma alloc_text(PAGE_ARAP, v42bisInit)
  36. #pragma alloc_text(PAGE_ARAP, v42bisCompress)
  37. #pragma alloc_text(PAGE_ARAP, v42bisDecompress)
  38. #endif
  39. //
  40. // bitmaps[# of bits]
  41. //
  42. USHORT bit_masks[16] =
  43. {
  44. 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f,
  45. 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff
  46. };
  47. static PCHAR
  48. show_char(
  49. IN UCHAR ch
  50. )
  51. {
  52. static char dec[20];
  53. if (' ' <= ch && ch <= '~')
  54. {
  55. dec[0] = ch;
  56. dec[1] = 0;
  57. return dec;
  58. }
  59. // BUGV42BUG: do we need this?
  60. //sprintf(dec, "0x%02x", ch);
  61. return dec;
  62. }
  63. /*
  64. decode_xid_params()
  65. decode compression negotiation packet as per V42bis spec.
  66. note: this is not used (there is code in the mnp LR routines to do
  67. this), but is included for completeness.
  68. */
  69. /*
  70. v42bis_push()
  71. perform PUSH on output stream. accumlated bytes are pushed
  72. out.
  73. */
  74. /*
  75. v42bis_init_dictionary()
  76. init dictionary in accordance with section 6.2 and 7.2
  77. this is used at init time and in response to a CCW_RESET
  78. */
  79. DWORD
  80. v42bis_init_dictionary(state)
  81. v42bis_t *state;
  82. {
  83. int i;
  84. node_t *n;
  85. /* initialize dictionary tree */
  86. for (i = 0, n = state->dictionary; i < state->n2; i++, n++)
  87. {
  88. n->byte = 0;
  89. n->parent = 0;
  90. n->node = 0;
  91. n->leaf = 0;
  92. }
  93. /* section 6.2 */
  94. state->c1 = N5; /* next codeword */
  95. state->c2 = N3 + 1; /* codeword size (bits) */
  96. state->c3 = N4 * 2; /* threshold */
  97. state->transparent = TRUE;
  98. state->escape = 0;
  99. state->escaped = FALSE;
  100. state->exception_next = FALSE;
  101. /* initialize searching */
  102. state->last_match = 0;
  103. state->last_new = 0;
  104. state->string_size = 0;
  105. return ARAPERR_NO_ERROR;
  106. }
  107. /*
  108. v42bis_init()
  109. implements C-INIT semantics
  110. */
  111. DWORD
  112. v42bis_init(state)
  113. v42bis_t *state;
  114. {
  115. DWORD dwRetCode;
  116. V_FLOW(("v42bis_init()"));
  117. /* our defaults */
  118. state->n1 = LOG2_CODES; /* max codeword size (bits) */
  119. state->n2 = CONN(state)->neg_p1; /* total # of codewords */
  120. state->n7 = CONN(state)->neg_p2; /* max string length */
  121. /* init dictionary */
  122. v42bis_init_dictionary(state);
  123. /* initialize encode/decode */
  124. state->bits_acc = 0;
  125. state->bits_used = 0;
  126. state->word_size = 8*sizeof(unsigned short);
  127. state->bits_waiting = 0;
  128. state->bits_remaining = 0;
  129. return ARAPERR_NO_ERROR;
  130. }
  131. #ifdef DEBUG_ENABLED
  132. /*
  133. itobits()
  134. turn an integer bitfield into an ascii representation (i.e. "01010101")
  135. */
  136. char *
  137. itobits(word, bits)
  138. USHORT word;
  139. int bits;
  140. {
  141. static char buf[33];
  142. int i;
  143. if (bits > 32) bits = 32;
  144. for (i = bits-1; i >= 0; i--)
  145. buf[(bits-1)-i] = word & (1 << i) ? '1' : '0';
  146. buf[bits] = 0;
  147. return buf;
  148. }
  149. #endif
  150. /*
  151. v42bis_decode_codeword()
  152. decode n-bit codewords from a bytesteam.
  153. */
  154. USHORT
  155. v42bis_decode_codeword(state, value)
  156. v42bis_t *state;
  157. UCHAR value;
  158. {
  159. register UCHAR bits_free, bits_new, bits_residual;
  160. register USHORT codeword;
  161. V_FLOW(("v42bis_decode_codeword(%x) c2=%d", value, state->c2));
  162. /* simple case */
  163. if (state->c2 == 8 || state->transparent)
  164. return value;
  165. /* not-so-simple case */
  166. D_DEBUG(("before: waiting %06x, bits_remaining %d",
  167. state->bits_waiting, state->bits_remaining));
  168. /* add in these 8 bits */
  169. state->bits_waiting |= ((DWORD)value) << state->bits_remaining;
  170. state->bits_remaining += 8;
  171. /* do we have a codeword ? */
  172. if (state->bits_remaining >= state->c2) {
  173. D_DEBUG(("input %04x %s",
  174. state->bits_waiting & bit_masks[state->c2],
  175. itobits(state->bits_waiting & bit_masks[state->c2],
  176. state->c2)));
  177. codeword = (USHORT)(state->bits_waiting & bit_masks[state->c2]);
  178. state->bits_waiting >>= state->c2;
  179. state->bits_remaining -= state->c2;
  180. D_DEBUG(("after: waiting %04x, bits_remaining %d (data)",
  181. state->bits_waiting, state->bits_remaining));
  182. return codeword;
  183. }
  184. D_DEBUG(("after: waiting %04x, bits_remaining %d (no data)",
  185. state->bits_waiting, state->bits_remaining));
  186. return ((USHORT)-1);
  187. }
  188. /*
  189. v42bis_decode_codeword_flush()
  190. "flush" decoding of codewords, returning the last codeword
  191. */
  192. USHORT
  193. v42bis_decode_codeword_flush(state)
  194. v42bis_t *state;
  195. {
  196. USHORT codeword = (USHORT)-1;
  197. if (state->bits_remaining)
  198. codeword = (USHORT)(state->bits_waiting & bit_masks[state->c2]);
  199. state->bits_waiting = 0;
  200. state->bits_remaining = 0;
  201. return codeword;
  202. }
  203. /*
  204. v42bis_encode_codeword()
  205. encode n-bit codewords into a bytesteam.
  206. This routine makes use of the fact that the code words will be always
  207. be smaller than 16 bits. An "accumulator" is used with several state
  208. variables to keep track of how much of the accumulator is in use at
  209. any given time.
  210. The code works for wordsizes of 8 and 16 bits. It is assumed that the
  211. output is a byte stream. No assumptions are made about alignment of
  212. data.
  213. note: this routine needs to be "flushed" to get out the value left
  214. in the accumulator.
  215. jbp@fcr.com 09/13/92, 19:52
  216. */
  217. DWORD
  218. v42bis_encode_codeword(state, value)
  219. v42bis_t *state;
  220. USHORT value;
  221. {
  222. register UCHAR bits_free, bits_new, bits_residual;
  223. EN_DEBUG(("v42bis_encode_codeword(%d 0x%x) c2=%d",
  224. value, value, state->c2));
  225. /* simple case */
  226. if (state->c2 == 8 || state->transparent)
  227. {
  228. E_DEBUG(("put acc %02x %s", value & 0xff, itobits(value & 0xff, 8)));
  229. PUT((UCHAR)value);
  230. if (state->transparent)
  231. {
  232. state->bits_out_while_transparent += N3;
  233. }
  234. else
  235. {
  236. state->bits_out_while_compressed += N3;
  237. }
  238. return ARAPERR_NO_ERROR;
  239. }
  240. state->bits_out_while_compressed += state->c2;
  241. /* not-so-simple case */
  242. E_DEBUG(("before: acc %04x, bits_used %d",
  243. state->bits_acc, state->bits_used));
  244. /* place new value in appropriate bit positions */
  245. state->bits_acc |= ((DWORD)value) << state->bits_used;
  246. /* housekeeping */
  247. bits_free = state->word_size - state->bits_used;
  248. bits_new = bits_free < state->c2 ? bits_free : state->c2;
  249. bits_residual = state->c2 - bits_new;
  250. E_DEBUG(("bits_free %d, bits_new %d, bits_residual %d",
  251. bits_free, bits_new, bits_residual));
  252. #ifdef DEBUG
  253. if (state->bits_used + bits_new >= 31)
  254. logf("acc oflo, size %d", state->bits_used + bits_new);
  255. #endif
  256. /* do we have a full codeword in the accumulator? */
  257. if (state->bits_used + bits_new == state->word_size)
  258. {
  259. if (state->word_size == 16)
  260. {
  261. E_DEBUG(("put acc %06x %s",
  262. state->bits_acc, itobits(state->bits_acc, 24)));
  263. PUT((UCHAR)(state->bits_acc));
  264. PUT((UCHAR)(state->bits_acc >> 8));
  265. }
  266. else
  267. {
  268. E_DEBUG(("put acc %02x %s",
  269. state->bits_acc & 0xff,
  270. itobits(state->bits_acc & 0xff, 8)));
  271. PUT((UCHAR)(state->bits_acc));
  272. }
  273. E_DEBUG(("value 0x%x, bits_used %d, acc 0x%x",
  274. value, state->bits_used, value >> state->bits_used));
  275. /* account for left over bits */
  276. state->bits_acc = value >> (state->c2 - bits_residual);
  277. state->bits_used = bits_residual;
  278. }
  279. else
  280. {
  281. state->bits_used += bits_new;
  282. }
  283. E_DEBUG(("after: acc %06x, bits_used %d",
  284. state->bits_acc, state->bits_used));
  285. return ARAPERR_NO_ERROR;
  286. }
  287. /*
  288. v42bis_encode_codeword_flush()
  289. flush partial assembly of codeword into 16 bit accumulator
  290. */
  291. DWORD
  292. v42bis_encode_codeword_flush(state)
  293. v42bis_t *state;
  294. {
  295. V_FLOW(("v42bis_encode_codeword_flush() bits_used %d", state->bits_used));
  296. if (state->bits_used) {
  297. E_DEBUG(("put acc (flush) %02x %s",
  298. state->bits_acc & 0xff,
  299. itobits(state->bits_acc & 0xff, 8)));
  300. PUT((UCHAR)(state->bits_acc));
  301. }
  302. if (state->bits_used > 8) {
  303. E_DEBUG(("put acc (flush2) %02x %s",
  304. (state->bits_acc>>8) & 0xff,
  305. itobits((state->bits_acc>>8) & 0xff, 8)));
  306. PUT((UCHAR)(state->bits_acc >> 8));
  307. }
  308. #ifdef DEBUG
  309. if (state->bits_used > 16)
  310. logf("flush: bits_used %d", state->bits_used);
  311. #endif
  312. state->bits_used = 0;
  313. state->bits_acc = 0;
  314. return ARAPERR_NO_ERROR;
  315. }
  316. /*
  317. v42bis_encode_value()
  318. encode a codeword value, noting if it's size exceeds C3, and
  319. doing any required STEPUPs
  320. */
  321. DWORD
  322. v42bis_encode_value(state, value)
  323. v42bis_t *state;
  324. USHORT value;
  325. {
  326. DWORD dwRetCode;
  327. V_FLOW(("v42bis_encode_value(%lx, 0x%x)", state, value));
  328. #ifdef DEBUG
  329. /* sanity check */
  330. if (value >= 8192) {
  331. logf("encode_value() value too big, %d", value);
  332. exit(1);
  333. }
  334. #endif
  335. /* section 7.4 */
  336. /* check codeword size */
  337. while (value >= state->c3)
  338. {
  339. EN_DEBUG(("stepup: value %d, max %d", value, state->c3));
  340. dwRetCode = v42bis_encode_codeword(state, CCW_STEPUP);
  341. if (dwRetCode != ARAPERR_NO_ERROR)
  342. {
  343. return(dwRetCode);
  344. }
  345. state->c2++;
  346. state->c3 *= 2;
  347. }
  348. dwRetCode = v42bis_encode_codeword(state, value);
  349. return(dwRetCode);
  350. }
  351. /*
  352. decide if we should transition from tranparent to compressed or
  353. visa versa.
  354. */
  355. DWORD
  356. v42bis_apply_compression_test(state)
  357. v42bis_t *state;
  358. {
  359. DWORD dwRetCode;
  360. if (state->just_flushed || state->exception_next)
  361. {
  362. return ARAPERR_NO_ERROR;
  363. }
  364. #ifdef UNIT_TEST_PROGRESS
  365. {
  366. static int times = 0;
  367. if (++times == 1000)
  368. {
  369. times = 0;
  370. dwRetCode = v42bis_comp_test_report(state);
  371. if (dwRetCode != ARAPERR_NO_ERROR)
  372. {
  373. return(dwRetCode);
  374. }
  375. }
  376. }
  377. #endif
  378. #ifdef UNIT_TEST_FORCE
  379. /* force consistant behavior across all input */
  380. if (!state->transparent)
  381. {
  382. state->bits_out_while_transparent = 0;
  383. return ARAPERR_NO_ERROR;
  384. }
  385. else
  386. {
  387. state->bits_out_if_transparent = 0;
  388. #undef WINDOW_CHECK_BYTES
  389. #define WINDOW_CHECK_BYTES 0
  390. if (state->bits_out_while_transparent > 64*N3)
  391. {
  392. dwRetCode = v42bis_transition_to_compressed(state);
  393. if (dwRetCode != ARAPERR_NO_ERROR)
  394. {
  395. return(dwRetCode);
  396. }
  397. }
  398. return ARAPERR_NO_ERROR;
  399. }
  400. #endif
  401. /* bound check to recent history */
  402. if (WINDOW_FULL(state->bits_out_this_mode))
  403. {
  404. state->bits_out_this_mode = 0;
  405. state->bits_out_other_mode = 0;
  406. }
  407. if (!state->transparent)
  408. {
  409. /* compressing */
  410. if ((state->bits_out_while_compressed -
  411. state->bits_out_if_transparent) > WINDOW_MIN_BITS)
  412. {
  413. dwRetCode = v42bis_transition_to_transparent(state);
  414. if (dwRetCode != ARAPERR_NO_ERROR)
  415. {
  416. return(dwRetCode);
  417. }
  418. }
  419. }
  420. else
  421. {
  422. /* transparent */
  423. #ifdef NEVER_SEND_COMPRESSED
  424. return ARAPERR_NO_ERROR;
  425. #endif
  426. /* transparent */
  427. if ((state->bits_out_while_transparent -
  428. state->bits_out_if_compressed) > WINDOW_MIN_BITS)
  429. {
  430. dwRetCode = v42bis_transition_to_compressed(state);
  431. if (dwRetCode != ARAPERR_NO_ERROR)
  432. {
  433. return(dwRetCode);
  434. }
  435. }
  436. }
  437. return ARAPERR_NO_ERROR;
  438. }
  439. /*
  440. v42bis_encode_buffer()
  441. implements C-DATA semantics on encode side
  442. encode a buffer full of data...
  443. */
  444. DWORD
  445. v42bis_encode_buffer(state, string, insize)
  446. v42bis_t *state;
  447. PUCHAR string;
  448. int insize;
  449. {
  450. UCHAR ch;
  451. BOOLEAN hit, duplicate;
  452. USHORT root_value, hit_node;
  453. node_t *n, *dead, *p;
  454. DWORD dwRetCode;
  455. V_FLOW(("v42bis_encode_buffer(%lx, %lx, %d)", state, string, insize));
  456. if (insize == 0)
  457. {
  458. return ARAPERR_NO_ERROR;
  459. }
  460. V_FLOW(("v42bis_encode: input %*s", insize, string));
  461. state->bytes_in += insize;
  462. /* section 6.3 */
  463. while (insize > 0)
  464. {
  465. /* "search" dictionary for string + character */
  466. ch = string[0];
  467. hit = FALSE;
  468. duplicate = FALSE;
  469. hit_node = state->last_match;
  470. p = DICT(state->last_match);
  471. EN_S_DEBUG(("last_match %d, string_size %d, insize %d, ch %d '%s'",
  472. state->last_match, state->string_size, insize,
  473. ch, show_char(ch)));
  474. if (state->last_match == 0)
  475. {
  476. /*
  477. * "the code word associated with each root node shall be N6 (the
  478. * number of control codewords) plus the ordinal value of the
  479. * character represented by the node"
  480. */
  481. state->last_match = ch + N6;
  482. state->string_size = 1;
  483. EN_S_DEBUG(("codeword for root %d, '%s' = %d",
  484. ch + N6, show_char(ch), CODE(DICT(ch + N6))));
  485. p = DICT(ch + N6);
  486. p->byte = ch;
  487. hit = TRUE;
  488. hit_node = state->last_match;
  489. /* consume input */
  490. goto consume_input;
  491. }
  492. /* we're at a node; search it's leaves */
  493. for (n = DICT(DICT(state->last_match)->leaf);
  494. CODE(n) && insize > 0;)
  495. {
  496. EN_S_DEBUG((" checking leaf node %d", CODE(n)));
  497. if (n->byte == *string)
  498. {
  499. /* hit - check leafs */
  500. EN_S_DEBUG((" hit: "));
  501. hit_node = (USHORT)CODE(n);
  502. p = n;
  503. state->last_match = (USHORT)CODE(n);
  504. if (state->just_flushed || hit_node == state->last_new)
  505. {
  506. EN_S_DEBUG(("leaving search, node == last created"));
  507. hit = FALSE;
  508. duplicate = TRUE;
  509. /* backup to previous node */
  510. hit_node = n->parent;
  511. state->last_match = n->parent;
  512. break;
  513. }
  514. hit = TRUE;
  515. state->string_size++;
  516. #ifdef never
  517. string++;
  518. insize--;
  519. /* if no leafs, exit now - we're at the end */
  520. if (n->leaf == 0)
  521. {
  522. EN_S_DEBUG(("leaving search, no leaf"));
  523. break;
  524. }
  525. n = DICT(n->leaf);
  526. EN_S_DEBUG(("continuing search, leaf %d", CODE(n)));
  527. continue;
  528. #else
  529. EN_S_DEBUG(("exiting search, leaf %d", CODE(n)));
  530. goto consume_input;
  531. #endif
  532. }
  533. else
  534. {
  535. EN_S_DEBUG((" miss: "));
  536. hit = FALSE;
  537. }
  538. if (n->node == 0)
  539. {
  540. EN_S_DEBUG(("leaving search, no node"));
  541. break;
  542. }
  543. n = DICT(n->node);
  544. EN_S_DEBUG(("continuing search, node %d", CODE(n)));
  545. }
  546. EN_S_DEBUG(("search done, n %d, insize %d, next %d '%s' %s %s",
  547. CODE(n), insize, string[0], show_char(string[0]),
  548. hit ? "hit" : "miss", duplicate ? "duplicate" : ""));
  549. #ifdef never
  550. /* we're matching but we ran out of characters */
  551. if (hit && insize == 0)
  552. {
  553. return ARAPERR_NO_ERROR;
  554. }
  555. #endif
  556. if (!hit && duplicate)
  557. {
  558. BOOLEAN ok_to_output;
  559. EN_S_DEBUG(("duplicate"));
  560. ok_to_output =
  561. !state->just_flushed &&
  562. !state->exception_next &&
  563. !state->decode_only;
  564. state->exception_next = FALSE;
  565. if (ok_to_output)
  566. {
  567. if (!state->transparent)
  568. {
  569. dwRetCode = v42bis_encode_value(state, hit_node);
  570. if (dwRetCode != ARAPERR_NO_ERROR)
  571. {
  572. return(dwRetCode);
  573. }
  574. }
  575. else
  576. {
  577. state->bits_out_if_compressed += state->c2;
  578. /* check if we should go compressed */
  579. if (state->bytes_since_last_check > WINDOW_CHECK_BYTES)
  580. {
  581. state->bytes_since_last_check = 0;
  582. dwRetCode = v42bis_apply_compression_test(state);
  583. if (dwRetCode != ARAPERR_NO_ERROR)
  584. {
  585. return(dwRetCode);
  586. }
  587. }
  588. }
  589. }
  590. /* string = string + character */
  591. state->string_size++;
  592. /* reset match to unmatched character */
  593. state->last_match = 0;
  594. state->string_size = 0;
  595. state->last_new = 0;
  596. state->just_flushed = 0;
  597. /* don't advance, "string = unmatched character" */
  598. continue;
  599. }
  600. /* last char did not match or already in dictionary */
  601. if (!hit && !duplicate)
  602. {
  603. BOOLEAN ok_to_output;
  604. EN_S_DEBUG(("update dictionary"));
  605. ok_to_output =
  606. !state->just_flushed &&
  607. !state->exception_next &&
  608. !state->decode_only;
  609. state->exception_next = FALSE;
  610. if (ok_to_output)
  611. {
  612. if (!state->transparent)
  613. {
  614. dwRetCode = v42bis_encode_value(state, hit_node);
  615. if (dwRetCode != ARAPERR_NO_ERROR)
  616. {
  617. return(dwRetCode);
  618. }
  619. }
  620. else
  621. {
  622. state->bits_out_if_compressed += state->c2;
  623. /* check if we should go compressed */
  624. if (state->bytes_since_last_check > WINDOW_CHECK_BYTES)
  625. {
  626. state->bytes_since_last_check = 0;
  627. dwRetCode = v42bis_apply_compression_test(state);
  628. if (dwRetCode != ARAPERR_NO_ERROR)
  629. {
  630. return(dwRetCode);
  631. }
  632. }
  633. }
  634. }
  635. state->just_flushed = 0;
  636. /* "add string + character to dictionary" */
  637. /* section 6.4a */
  638. /* string too big? */
  639. if (state->string_size >= state->n7)
  640. {
  641. EN_DEBUG(("string size (%d) > n7 (%d)",
  642. state->string_size, state->n7));
  643. /* reset match */
  644. state->last_match = 0;
  645. state->string_size = 0;
  646. /* we were in the match routine, reset last new */
  647. state->last_new = 0;
  648. continue;
  649. }
  650. /* pick a new code word */
  651. n = DICT(state->c1);
  652. state->last_new = (USHORT)CODE(n);
  653. EN_DEBUG(("adding new node %d = %d '%s', parent %d",
  654. CODE(n), string[0], show_char(string[0]), CODE(p)));
  655. /* attach "string + character" */
  656. n->byte = string[0];
  657. n->parent = hit_node;
  658. #ifdef DEBUG
  659. if (CODE(n) == hit_node)
  660. {
  661. logf("creating loop! node %d", CODE(n));
  662. }
  663. #endif
  664. n->node = 0;
  665. /* XXX should be in ord(ch) order to allow faster search */
  666. n->node = p->leaf;
  667. p->leaf = (USHORT)CODE(n);
  668. /* section 6.5 */
  669. /* recover dictionary entries */
  670. do
  671. {
  672. state->c1++;
  673. if (state->c1 > (state->n2 - 1))
  674. {
  675. state->c1 = N5;
  676. state->dict_full = TRUE;
  677. }
  678. dead = DICT(state->c1);
  679. /* find terminal nodes (i.e. leaf == 0) */
  680. } while (/*dead->parent != 0 &&*/ dead->leaf != 0);
  681. /* terminal nodes with parents are eligible */
  682. if (CODE(dead) && /* <- I think this is not needed */
  683. /*dead->parent && */dead->leaf == 0 &&
  684. state->dict_full)
  685. {
  686. /* go to parent, disconnect from chain */
  687. node_t *parent = DICT(dead->parent);
  688. EN_DEBUG(("recovering dead node %d", CODE(dead)));
  689. /* if first on parents list, fix parent */
  690. if (DICT(parent->leaf) == dead)
  691. {
  692. parent->leaf = dead->node;
  693. }
  694. else
  695. {
  696. /* else search parents list, fix sibling */
  697. for (parent = DICT(DICT(dead->parent)->leaf);
  698. CODE(parent); parent = DICT(parent->node))
  699. {
  700. if (DICT(parent->node) == dead)
  701. {
  702. parent->node = dead->node;
  703. break;
  704. }
  705. }
  706. }
  707. /* mark node free */
  708. dead->parent = 0;
  709. dead->leaf = 0;
  710. } /* dead node */
  711. /* if we added a node, reset "string" */
  712. //reset_match:
  713. state->last_match = 0;
  714. state->string_size = 0;
  715. state->just_flushed = 0;
  716. /*
  717. * this is a "safe time" to do compression test, as we've just
  718. * done an update...
  719. */
  720. if (!state->decode_only)
  721. {
  722. if (state->bytes_since_last_check > WINDOW_CHECK_BYTES)
  723. {
  724. state->bytes_since_last_check = 0;
  725. dwRetCode = v42bis_apply_compression_test(state);
  726. if (dwRetCode != ARAPERR_NO_ERROR)
  727. {
  728. return(dwRetCode);
  729. }
  730. }
  731. }
  732. /* don't advance, "string = unmatched character" */
  733. continue;
  734. } /* (!hit && !duplicate) */
  735. consume_input:
  736. string++;
  737. insize--;
  738. state->bytes_since_last_check++;
  739. /* section 9.2 */
  740. //check_escape:
  741. /* escape processing */
  742. if (state->transparent)
  743. {
  744. if (!state->decode_only)
  745. {
  746. dwRetCode = v42bis_encode_value(state, ch);
  747. if (dwRetCode != ARAPERR_NO_ERROR)
  748. {
  749. return(dwRetCode);
  750. }
  751. }
  752. if (ch == state->escape)
  753. {
  754. if (!state->decode_only)
  755. {
  756. dwRetCode = v42bis_encode_value(state, CCW_EID);
  757. if (dwRetCode != ARAPERR_NO_ERROR)
  758. {
  759. return(dwRetCode);
  760. }
  761. state->escape += ESCAPE_CYCLE;
  762. }
  763. }
  764. }
  765. else
  766. {
  767. /* compressed, cycle escape character */
  768. if (ch == state->escape && !state->decode_only)
  769. {
  770. state->escape += ESCAPE_CYCLE;
  771. }
  772. state->bits_out_if_transparent += N3;
  773. }
  774. state->just_flushed = 0;
  775. }
  776. return ARAPERR_NO_ERROR;
  777. }
  778. /*
  779. implements C-FLUSH semantics
  780. */
  781. DWORD
  782. v42bis_encode_flush(state)
  783. v42bis_t *state;
  784. {
  785. DWORD dwRetCode=ARAPERR_NO_ERROR;
  786. V_FLOW(("v42bis_encode_flush() string_size %d, last_match %d",
  787. state->string_size, state->last_match));
  788. if (state->just_flushed)
  789. {
  790. return ARAPERR_NO_ERROR;
  791. }
  792. if (state->transparent)
  793. {
  794. /* transparent, send any buffered characters */
  795. }
  796. else
  797. {
  798. /* compressed */
  799. /* section 7.9a */
  800. /* output partial match, if any */
  801. if (state->string_size)
  802. {
  803. /* section 7.8.2 */
  804. dwRetCode = v42bis_encode_value(state, state->last_match);
  805. if (dwRetCode != ARAPERR_NO_ERROR)
  806. {
  807. return(dwRetCode);
  808. }
  809. }
  810. state->just_flushed = 1;
  811. dwRetCode = v42bis_encode_value(state, CCW_FLUSH);
  812. if (dwRetCode != ARAPERR_NO_ERROR)
  813. {
  814. return(dwRetCode);
  815. }
  816. dwRetCode = v42bis_encode_codeword_flush(state);
  817. }
  818. return dwRetCode;
  819. }
  820. DWORD
  821. v42bis_transition_to_compressed(state)
  822. v42bis_t *state;
  823. {
  824. DWORD dwRetCode=ARAPERR_NO_ERROR;
  825. V_FLOW(("v42bis_transition_to_compressed()"));
  826. #ifdef UNIT_TEST_VERBOSE
  827. logf("v42bis_transition_to_compressed()");
  828. v42bis_comp_test_report(state);
  829. #endif
  830. if (state->transparent)
  831. {
  832. /* section 7.8.1a */
  833. dwRetCode = v42bis_encode_value(state, state->escape);
  834. if (dwRetCode != ARAPERR_NO_ERROR)
  835. {
  836. return(dwRetCode);
  837. }
  838. /* section 7.8.1b */
  839. if ((dwRetCode = v42bis_encode_value(state, CCW_ECM)) != ARAPERR_NO_ERROR)
  840. {
  841. return(dwRetCode);
  842. }
  843. if ((dwRetCode = v42bis_encode_codeword_flush(state)) != ARAPERR_NO_ERROR)
  844. {
  845. return(dwRetCode);
  846. }
  847. /* enter compressed mode */
  848. state->transparent = FALSE;
  849. state->bits_out_if_transparent = 0;
  850. state->bits_out_while_compressed = 0;
  851. }
  852. return ARAPERR_NO_ERROR;
  853. }
  854. DWORD
  855. v42bis_transition_to_transparent(state)
  856. v42bis_t *state;
  857. {
  858. DWORD dwRetCode;
  859. V_FLOW(("v42bis_transition_to_transparent()"));
  860. #ifdef UNIT_TEST_VERBOSE
  861. logf("v42bis_transition_to_transparent()");
  862. v42bis_comp_test_report(state);
  863. #endif
  864. /* check counters for overflow */
  865. if (!state->transparent)
  866. {
  867. /* output partial match, if any */
  868. if (state->string_size)
  869. {
  870. /* section 7.8.2 */
  871. dwRetCode = v42bis_encode_value(state, state->last_match);
  872. if (dwRetCode != ARAPERR_NO_ERROR)
  873. {
  874. return(dwRetCode);
  875. }
  876. }
  877. /* section 7.8.2c */
  878. if ((dwRetCode = v42bis_encode_value(state, CCW_ETM)) != ARAPERR_NO_ERROR)
  879. {
  880. return(dwRetCode);
  881. }
  882. /* section 7.8.2d */
  883. if ((dwRetCode = v42bis_encode_codeword_flush(state)) != ARAPERR_NO_ERROR)
  884. {
  885. return(dwRetCode);
  886. }
  887. /* section 7.8.2e */
  888. /* enter transparent mode */
  889. state->transparent = TRUE;
  890. /* reset compressibility test */
  891. state->bits_out_if_compressed = 0;
  892. state->bits_out_while_transparent = 0;
  893. }
  894. return ARAPERR_NO_ERROR;
  895. }
  896. DWORD
  897. v42bis_signal_reset(state)
  898. v42bis_t *state;
  899. {
  900. DWORD dwRetCode;
  901. if (!state->transparent)
  902. {
  903. /* change to transparent */
  904. dwRetCode = v42bis_transition_to_transparent(state);
  905. if (dwRetCode != ARAPERR_NO_ERROR)
  906. {
  907. return(dwRetCode);
  908. }
  909. /* counteract side effect */
  910. state->exception_next = FALSE;
  911. }
  912. dwRetCode = v42bis_encode_value(state, state->escape);
  913. if (dwRetCode != ARAPERR_NO_ERROR)
  914. {
  915. return(dwRetCode);
  916. }
  917. dwRetCode = v42bis_encode_value(state, CCW_RESET);
  918. return(dwRetCode);
  919. }
  920. /*
  921. expand a codeword into it's string
  922. follow chain of "parent" to root and then expand the node characters
  923. one by one.
  924. */
  925. DWORD
  926. v42bis_decode_match(state, codeword, psize, pRetChar)
  927. v42bis_t *state;
  928. USHORT codeword;
  929. UCHAR *pRetChar;
  930. int *psize;
  931. {
  932. node_t *path[256];
  933. int path_size = 0;
  934. node_t *base;
  935. int i;
  936. V_FLOW(("v42bis_decode_match(%d)", codeword));
  937. for (base = DICT(codeword); CODE(base); base = DICT(base->parent))
  938. {
  939. path[path_size++] = base;
  940. if (path_size >= 256)
  941. {
  942. v42bis_c_error(state, "path_size exceeds 256!");
  943. break;
  944. }
  945. #ifdef DEBUG
  946. if (base == DICT(base->parent))
  947. {
  948. logf("loop! node %d", CODE(base));
  949. break;
  950. }
  951. #endif
  952. }
  953. /* XXX this should not be done here! */
  954. if (codeword < N5 && DICT(codeword)->byte == 0)
  955. {
  956. DICT(codeword)->byte = codeword - N6;
  957. }
  958. D_DEBUG(("path_size %d", path_size));
  959. for (i = path_size - 1; i >= 0; i--)
  960. {
  961. D_DEBUG(("put byte %02x '%s'",
  962. path[i]->byte, show_char(path[i]->byte)));
  963. if (path[i]->byte == state->escape)
  964. {
  965. state->escape += ESCAPE_CYCLE;
  966. }
  967. PUT(path[i]->byte);
  968. }
  969. *psize = path_size;
  970. /* return first (prefix) char of string */
  971. *pRetChar = path[path_size-1]->byte;
  972. return ARAPERR_NO_ERROR;
  973. }
  974. /*
  975. decode L-DATA semantics on the decode side
  976. decode a buffer full of data...
  977. */
  978. DWORD
  979. v42bis_decode_buffer(state, data, pDataSize)
  980. v42bis_t *state;
  981. PUCHAR data;
  982. int *pDataSize;
  983. {
  984. USHORT codeword;
  985. UCHAR ch;
  986. DWORD dwRetCode;
  987. V_FLOW(("v42bis_decode_buffer() %d bytes", *pDataSize));
  988. while (*pDataSize)
  989. {
  990. //
  991. // did we have an overflow? if so, stop right here
  992. //
  993. if (state->OverFlowBytes && data)
  994. {
  995. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  996. ("Arap v42bis: %d bytes overflowed, suspending decomp\n",
  997. state->OverFlowBytes));
  998. return(ARAPERR_BUF_TOO_SMALL);
  999. }
  1000. #if DBG
  1001. if (state->OverFlowBytes && !data)
  1002. {
  1003. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1004. ("Arap v42bis: ALERT! ALERT: (%d)\n",state->OverFlowBytes));
  1005. ASSERT(0);
  1006. }
  1007. #endif
  1008. (*pDataSize)--;
  1009. if (data)
  1010. {
  1011. /* we have a buffer */
  1012. D_DEBUG(("pull 0x%x", *data & 0xff));
  1013. codeword = v42bis_decode_codeword(state, *data++);
  1014. }
  1015. else
  1016. {
  1017. /* no input buffer, flush */
  1018. codeword = v42bis_decode_codeword_flush(state);
  1019. *pDataSize = 0;
  1020. }
  1021. DE_DEBUG(("codeword %d (0x%x)", codeword, codeword));
  1022. /* if decode did not return a value, return */
  1023. if (codeword == 0xffff)
  1024. {
  1025. /* no data */
  1026. D_DEBUG(("no data"));
  1027. continue;
  1028. }
  1029. if (state->transparent)
  1030. {
  1031. /* transparent mode */
  1032. /* escaped - look at next codeword */
  1033. if (state->escaped)
  1034. {
  1035. state->escaped = FALSE;
  1036. DE_DEBUG(("escape codeword"));
  1037. /* section 5.8d */
  1038. if (codeword >= 3 && codeword <= 255)
  1039. {
  1040. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1041. ("v42: received reserved code word (%d)", codeword));
  1042. v42bis_c_error(state, "received reserved code word");
  1043. break;
  1044. }
  1045. switch (codeword)
  1046. {
  1047. case CCW_ECM:
  1048. DE_DEBUG(("enter compression mode"));
  1049. state->transparent = FALSE;
  1050. /* set up for decode */
  1051. state->last_decode = state->last_match;
  1052. state->last_decode_size = state->string_size;
  1053. state->exception_next = TRUE;
  1054. break;
  1055. case CCW_EID:
  1056. DE_DEBUG(("escape id"));
  1057. codeword = state->escape;
  1058. state->escape += ESCAPE_CYCLE;
  1059. goto decode_encode;
  1060. break;
  1061. case CCW_RESET:
  1062. DE_DEBUG(("reset"));
  1063. v42bis_init_dictionary(state);
  1064. break;
  1065. }
  1066. }
  1067. else
  1068. {
  1069. /* escape? */
  1070. if (codeword == state->escape)
  1071. {
  1072. DE_DEBUG(("escape prefix"));
  1073. state->escaped = TRUE;
  1074. continue;
  1075. }
  1076. decode_encode:
  1077. /* save data in output buffer */
  1078. PUT((UCHAR)codeword);
  1079. /* encode to build dictionary */
  1080. ch = (UCHAR)codeword;
  1081. dwRetCode = v42bis_encode_buffer(state, &ch, 1);
  1082. if (dwRetCode != ARAPERR_NO_ERROR)
  1083. {
  1084. return(dwRetCode);
  1085. }
  1086. }
  1087. }
  1088. else
  1089. {
  1090. int size;
  1091. /* compression mode */
  1092. switch (codeword)
  1093. {
  1094. case CCW_ETM:
  1095. DE_DEBUG(("enter transparent mode"));
  1096. v42bis_decode_codeword_flush(state);
  1097. state->transparent = TRUE;
  1098. state->last_match = state->last_decode;
  1099. state->string_size = state->last_decode_size;
  1100. state->last_new = 0;
  1101. state->just_flushed = 1;
  1102. break;
  1103. case CCW_FLUSH:
  1104. DE_DEBUG(("flush"));
  1105. /* terminate search */
  1106. state->last_match = 0;
  1107. state->string_size = 0;
  1108. state->last_match = state->last_decode;
  1109. state->string_size = state->last_decode_size;
  1110. state->last_new = 0;
  1111. /* reset codeword decode machine */
  1112. state->bits_waiting = 0;
  1113. state->bits_remaining = 0;
  1114. break;
  1115. case CCW_STEPUP:
  1116. DE_DEBUG(("stepup"));
  1117. /* section 5.8a */;
  1118. if (state->c2 + 1 > state->n1)
  1119. {
  1120. v42bis_c_error(state, "received STEPUP; c2 exceeds max");
  1121. }
  1122. else
  1123. {
  1124. state->c2++;
  1125. }
  1126. break;
  1127. default:
  1128. /* regular codeword */
  1129. /* section 5.8b */
  1130. if (codeword == state->c1)
  1131. {
  1132. #ifdef DEBUG
  1133. logf(state, "received codeword equal to c1");
  1134. #endif
  1135. continue;
  1136. }
  1137. /* section 5.8c */
  1138. if (codeword >= N5 && state->dictionary[codeword].parent == 0)
  1139. {
  1140. #ifdef DEBUG
  1141. logf("received unused codeword %d, full %d, c1 %d",
  1142. codeword, state->dict_full, state->c1);
  1143. #endif
  1144. v42bis_c_error(state, "received unused codeword");
  1145. }
  1146. dwRetCode = v42bis_decode_match(state, codeword, &size, &ch);
  1147. if (dwRetCode != ARAPERR_NO_ERROR)
  1148. {
  1149. return(dwRetCode);
  1150. }
  1151. /*
  1152. * umm... "New dictionary entries shall be created using
  1153. * the proceedure defined in section 6.4, with the first
  1154. * (prefix) character of the most recently decoded string
  1155. * being appended to the previously decoded string."
  1156. *
  1157. * what a pain this was to get right!
  1158. */
  1159. /* section 8 */
  1160. state->last_match = state->last_decode;
  1161. state->string_size = state->last_decode_size;
  1162. dwRetCode = v42bis_encode_buffer(state, &ch, 1);
  1163. if (dwRetCode != ARAPERR_NO_ERROR)
  1164. {
  1165. return(dwRetCode);
  1166. }
  1167. state->last_decode = codeword;
  1168. state->last_decode_size = (UCHAR)size;
  1169. }
  1170. }
  1171. }
  1172. dwRetCode = (state->OverFlowBytes) ?
  1173. ARAPERR_BUF_TOO_SMALL : ARAPERR_NO_ERROR;
  1174. return(dwRetCode);
  1175. }
  1176. /*
  1177. v42bis_decode_flush()
  1178. flush codeword decoder and push out data
  1179. */
  1180. DWORD
  1181. v42bis_decode_flush(state)
  1182. v42bis_t *state;
  1183. {
  1184. DWORD dwRetCode;
  1185. int one;
  1186. V_FLOW(("v42bis_decode_flush()"));
  1187. one = 1;
  1188. dwRetCode = v42bis_decode_buffer(state, (PUCHAR )0, &one);
  1189. return(dwRetCode);
  1190. }
  1191. /*
  1192. v42bis_c_error()
  1193. implements C-ERROR semantics
  1194. */
  1195. DWORD
  1196. v42bis_c_error(state, reason_string)
  1197. v42bis_t *state;
  1198. char *reason_string;
  1199. {
  1200. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1201. ("v42bis: C-ERROR with '%s' on %s",reason_string,
  1202. state == &((v42bis_connection_t *)state->connection)->encode ?
  1203. "encode" : "decode"));
  1204. ASSERT(0);
  1205. return ARAPERR_NO_ERROR;
  1206. }
  1207. DWORD
  1208. v42bis_init_buffer(state, buf, size)
  1209. v42bis_t *state;
  1210. PUCHAR buf;
  1211. int size;
  1212. {
  1213. state->output_buffer = buf;
  1214. state->output_ptr = buf;
  1215. state->output_size = 0;
  1216. state->output_max = (USHORT)size;
  1217. return ARAPERR_NO_ERROR;
  1218. }
  1219. /*
  1220. */
  1221. DWORD
  1222. v42bis_connection_init(conn)
  1223. v42bis_connection_t *conn;
  1224. {
  1225. conn->default_p0 = 3;
  1226. conn->default_p1 = DEF_P1; /* total # of codewords */
  1227. conn->default_p2 = DEF_P2; /* max string length */
  1228. conn->neg_p0 = conn->default_p0; /* direction of compression */
  1229. conn->neg_p1 = conn->default_p1; /* total # of codewords */
  1230. conn->neg_p2 = (UCHAR)conn->default_p2; /* max string length */
  1231. /* encode side */
  1232. conn->encode.connection = (void *)conn;
  1233. conn->encode.decode_only = FALSE;
  1234. v42bis_init(&conn->encode);
  1235. /* decode side */
  1236. conn->decode.connection = (void *)conn;
  1237. conn->decode.decode_only = TRUE;
  1238. v42bis_init(&conn->decode);
  1239. return ARAPERR_NO_ERROR;
  1240. }
  1241. DWORD
  1242. v42bis_connection_init_buffers(conn, e_buf, e_size, d_buf, d_size)
  1243. v42bis_connection_t *conn;
  1244. PUCHAR e_buf;
  1245. int e_size;
  1246. PUCHAR d_buf;
  1247. int d_size;
  1248. {
  1249. v42bis_init_buffer(&conn->encode, e_buf, e_size);
  1250. v42bis_init_buffer(&conn->decode, d_buf, d_size);
  1251. return ARAPERR_NO_ERROR;
  1252. }
  1253. DWORD
  1254. v42bis_connection_init_push(conn, context, e_push, d_push)
  1255. v42bis_connection_t *conn;
  1256. void *context;
  1257. void (*e_push)();
  1258. void (*d_push)();
  1259. {
  1260. conn->encode.push_func = e_push;
  1261. conn->encode.push_context = context;
  1262. conn->decode.push_func = d_push;
  1263. conn->decode.push_context = context;
  1264. return ARAPERR_NO_ERROR;
  1265. }
  1266. /* ------------- debug -------------- */
  1267. #ifdef DEBUG
  1268. DWORD
  1269. v42bis_dumptree_follownode(state, node)
  1270. v42bis_t *state;
  1271. USHORT node;
  1272. {
  1273. int i;
  1274. node_t *n = DICT(node);
  1275. for (i = 0; i < state->dump_indent; i++)
  1276. fprintf(stderr, " ");
  1277. fprintf(stderr, "code %d; char %d '%s' parent %d, node %d, leaf %d\n",
  1278. node, n->byte, show_char(n->byte), n->parent, n->node, n->leaf);
  1279. if (n->node)
  1280. v42bis_dumptree_follownode(state, n->node);
  1281. state->dump_indent++;
  1282. if (n->leaf)
  1283. v42bis_dumptree_follownode(state, n->leaf);
  1284. state->dump_indent--;
  1285. return ARAPERR_NO_ERROR;
  1286. }
  1287. DWORD
  1288. v42bis_dumptree(state, name)
  1289. v42bis_t *state;
  1290. char *name;
  1291. {
  1292. int i;
  1293. fprintf(stderr, "%s codewords:\n", name);
  1294. for (i = 0; i < CODES; i++)
  1295. if (state->dictionary[i].byte) {
  1296. node_t *n = &state->dictionary[i];
  1297. fprintf(stderr, "code %d; char %d '%s' parent %d, node %d, leaf %d\n",
  1298. i, n->byte, show_char(n->byte),
  1299. n->parent, n->node, n->leaf);
  1300. }
  1301. state->dump_indent = 0;
  1302. fprintf(stderr, "%s tree:\n", name);
  1303. for (i = 0; i < N5; i++)
  1304. if (state->dictionary[i].byte) {
  1305. node_t *n = &state->dictionary[i];
  1306. fprintf(stderr, "code %d; root node, %d '%s', leaf %d:\n",
  1307. i, n->byte, show_char(n->byte), n->leaf);
  1308. if (state->dictionary[i].leaf) {
  1309. state->dump_indent = 1;
  1310. v42bis_dumptree_follownode(state, n->leaf);
  1311. }
  1312. }
  1313. return ARAPERR_NO_ERROR;
  1314. }
  1315. DWORD
  1316. v42bis_connection_dumptree(conn)
  1317. v42bis_connection_t *conn;
  1318. {
  1319. int i;
  1320. fprintf(stderr, "\nv42bis_connection_dumptree()\n");
  1321. v42bis_dumptree(&conn->encode, "encode");
  1322. v42bis_dumptree(&conn->decode, "decode");
  1323. return ARAPERR_NO_ERROR;
  1324. }
  1325. #endif /* DEBUG */
  1326. /* ------------- external interface -------------- */
  1327. DWORD
  1328. v42bis_mnp_set_debug(pArapConn)
  1329. PARAPCONN pArapConn;
  1330. {
  1331. #if DEBUG
  1332. pArapConn->v42bis.decode.debug_decode = 0;
  1333. pArapConn->v42bis.decode.debug_encode = 0;
  1334. switch (pArapConn->debug_v42) {
  1335. case 3:
  1336. pArapConn->v42bis.decode.debug_flow = TRUE;
  1337. pArapConn->v42bis.encode.debug_flow = TRUE;
  1338. /* fall through */
  1339. case 2:
  1340. pArapConn->v42bis.decode.debug_decode_bytes = TRUE;
  1341. pArapConn->v42bis.decode.debug_encode_bytes = TRUE;
  1342. pArapConn->v42bis.encode.debug_encode_bytes = TRUE;
  1343. pArapConn->v42bis.decode.debug_decode++;
  1344. pArapConn->v42bis.decode.debug_encode++;
  1345. /* fall through */
  1346. case 1:
  1347. pArapConn->v42bis.decode.debug_decode++;
  1348. pArapConn->v42bis.decode.debug_encode++;
  1349. pArapConn->v42bis.encode.debug_encode = TRUE;
  1350. break;
  1351. case 0:
  1352. break;
  1353. }
  1354. #endif
  1355. return ARAPERR_NO_ERROR;
  1356. }
  1357. /*
  1358. v42bis_send()
  1359. send data to V.42bis connection
  1360. input: unsigned char *buffer; pointer to user data buffer
  1361. int buflen; length of user data buffer
  1362. output: int retcode - if positive, the number of data bytes
  1363. copied from the user data buffer;
  1364. if negative, link error code
  1365. */
  1366. /*
  1367. v42bis_receive()
  1368. receive data from V.42bis connection
  1369. input: unsigned char *buffer; pointer to user buffer
  1370. int buflen; length of user buffer
  1371. output: int retcode; if positive, the number of data bytes
  1372. copied into the user data buffer;
  1373. if negative, link error code
  1374. */
  1375. //-----------------------------------------------------------------------------
  1376. //
  1377. // Interface functions
  1378. //
  1379. //-----------------------------------------------------------------------------
  1380. BOOLEAN
  1381. v42bisInit(
  1382. IN PARAPCONN pArapConn,
  1383. IN PBYTE pReq,
  1384. OUT DWORD *dwReqToSkip,
  1385. OUT PBYTE pFrame,
  1386. OUT DWORD *dwFrameToSkip
  1387. )
  1388. {
  1389. BYTE VarLen;
  1390. BOOLEAN fV42Bis=TRUE;
  1391. DBG_ARAP_CHECK_PAGED_CODE();
  1392. if (ArapGlobs.V42bisEnabled)
  1393. {
  1394. *pFrame++ = MNP_LR_V42BIS;
  1395. VarLen = *pReq;
  1396. *pFrame++ = *pReq++;
  1397. RtlCopyMemory(pFrame, pReq, VarLen);
  1398. fV42Bis = TRUE;
  1399. *dwReqToSkip = (VarLen+1);
  1400. *dwFrameToSkip = (VarLen+2);
  1401. /* init the connection (both encode and decode */
  1402. v42bis_connection_init(pArapConn->pV42bis);
  1403. }
  1404. else
  1405. {
  1406. // send the v42bis type, but 0 for all parms
  1407. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1408. ("v42bisInit: no v42bis (type 1: i.e. 0 for all parms) on %lx\n",pArapConn));
  1409. *pFrame++ = MNP_LR_V42BIS;
  1410. VarLen = *pReq;
  1411. *pFrame++ = *pReq++;
  1412. *pFrame++ = 0;
  1413. *pFrame++ = 0;
  1414. *pFrame++ = 0;
  1415. *pFrame++ = 0;
  1416. fV42Bis = FALSE;
  1417. *dwReqToSkip = (VarLen+1);
  1418. *dwFrameToSkip = (VarLen+2);
  1419. //
  1420. // the other two possibilities to indicate no compression: the one above works,
  1421. // the following two retained just in case we need later
  1422. //
  1423. #if 0
  1424. // send the v42bis type, but 0 for the direction flags: other parms valid
  1425. {
  1426. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1427. ("v42bisInit: no v42bis (type 2: i.e. 0 only for direction) on %lx\n",pArapConn));
  1428. *pFrame++ = MNP_LR_V42BIS;
  1429. VarLen = *pReq;
  1430. *pFrame++ = *pReq++;
  1431. *pFrame++ = 0;
  1432. *pFrame++ = 0;
  1433. *pFrame++ = 0x8;
  1434. *pFrame++ = 0xfa;
  1435. fV42Bis = FALSE;
  1436. *dwReqToSkip = (VarLen+1);
  1437. *dwFrameToSkip = (VarLen+2);
  1438. }
  1439. // skip the v42bis type altogether
  1440. {
  1441. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1442. ("v42bisInit: no v42bis (type 3: i.e. not sending v42bis type) on %lx\n",pArapConn));
  1443. VarLen = *pReq;
  1444. fV42Bis = FALSE;
  1445. *dwReqToSkip = (VarLen+1);
  1446. *dwFrameToSkip = 0;
  1447. }
  1448. #endif
  1449. }
  1450. return(fV42Bis);
  1451. }
  1452. DWORD
  1453. v42bisCompress(
  1454. IN PARAPCONN pArapConn,
  1455. IN PUCHAR pUncompressedData,
  1456. IN DWORD UnCompressedDataLen,
  1457. OUT PUCHAR pCompressedData,
  1458. OUT DWORD CompressedDataBufSize,
  1459. OUT DWORD *pCompressedDataLen
  1460. )
  1461. {
  1462. DWORD dwRetCode;
  1463. DBG_ARAP_CHECK_PAGED_CODE();
  1464. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,("v42bisCompress (%lx, %lx, %ld)\n",
  1465. pArapConn, pUncompressedData, UnCompressedDataLen));
  1466. #ifdef V42_DUMP_ENABLED
  1467. if (pArapConn->v42_dump) {
  1468. pArapConn->v42_size = buflen;
  1469. pArapConn->v42_type = 2;
  1470. write(pArapConn->v42_dump, &pArapConn->v42_esize, 4);
  1471. write(pArapConn->v42_dump, bufptr, buflen);
  1472. }
  1473. #endif
  1474. v42bis_init_buffer(&pArapConn->pV42bis->encode,
  1475. pCompressedData,
  1476. CompressedDataBufSize);
  1477. dwRetCode = v42bis_encode_buffer(&pArapConn->pV42bis->encode,
  1478. pUncompressedData,
  1479. UnCompressedDataLen);
  1480. if (dwRetCode != ARAPERR_NO_ERROR)
  1481. {
  1482. return(dwRetCode);
  1483. }
  1484. dwRetCode = v42bis_encode_flush(&pArapConn->pV42bis->encode);
  1485. // set the length of compressed data
  1486. *pCompressedDataLen = pArapConn->pV42bis->encode.output_size;
  1487. return(dwRetCode);
  1488. }
  1489. DWORD
  1490. v42bisDecompress(
  1491. IN PARAPCONN pArapConn,
  1492. IN PUCHAR pCompressedData,
  1493. IN DWORD CompressedDataLen,
  1494. OUT PUCHAR pDecompressedData,
  1495. OUT DWORD DecompressedDataBufSize,
  1496. OUT DWORD *pByteStillToDecompress,
  1497. OUT DWORD *pDecompressedDataLen
  1498. )
  1499. {
  1500. DWORD dwRetCode;
  1501. DWORD dwRemaingDataSize;
  1502. DWORD dwOverFlow;
  1503. DBG_ARAP_CHECK_PAGED_CODE();
  1504. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,("v42bisDecompress (%lx, %lx, %ld)\n",
  1505. pArapConn, pCompressedData, CompressedDataLen));
  1506. *pDecompressedDataLen = 0;
  1507. dwRemaingDataSize = CompressedDataLen;
  1508. *pByteStillToDecompress = CompressedDataLen;
  1509. #ifdef V42_DUMP_ENABLED
  1510. if (pArapConn->v42_dump) {
  1511. pArapConn->v42_size = mnp_size;
  1512. pArapConn->v42_type = 2;
  1513. write(pArapConn->v42_dump, &pArapConn->v42_size, 4 + mnp_size);
  1514. }
  1515. #endif
  1516. //
  1517. // if we had an overflow in the previous decomp effort, we have bytes in
  1518. // the overflow buffer: copy those in first.
  1519. //
  1520. if ( (dwOverFlow = pArapConn->pV42bis->decode.OverFlowBytes) > 0)
  1521. {
  1522. if (DecompressedDataBufSize <= dwOverFlow)
  1523. {
  1524. return(ARAPERR_BUF_TOO_SMALL);
  1525. }
  1526. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  1527. ("Arap v42bis: (%lx) copying %d overflow bytes first\n",
  1528. pArapConn, dwOverFlow));
  1529. RtlCopyMemory(pDecompressedData,
  1530. pArapConn->pV42bis->decode.OverFlowBuf,
  1531. dwOverFlow);
  1532. pDecompressedData += dwOverFlow;
  1533. DecompressedDataBufSize -= dwOverFlow;
  1534. pArapConn->pV42bis->decode.OverFlowBytes = 0;
  1535. *pDecompressedDataLen += dwOverFlow;
  1536. }
  1537. //
  1538. // this can happen if we got called because we told in a previous call that
  1539. // there was buffer overflow and there was nothing more left to decompress
  1540. //
  1541. if (CompressedDataLen == 0)
  1542. {
  1543. return(ARAPERR_NO_ERROR);
  1544. }
  1545. //
  1546. // set decomp buffer to the buffer supplied
  1547. //
  1548. v42bis_init_buffer(&pArapConn->pV42bis->decode,
  1549. pDecompressedData,
  1550. DecompressedDataBufSize);
  1551. /* decode everything we got */
  1552. dwRetCode = v42bis_decode_buffer(&pArapConn->pV42bis->decode,
  1553. pCompressedData,
  1554. &dwRemaingDataSize);
  1555. *pByteStillToDecompress = dwRemaingDataSize;
  1556. //
  1557. // how big is the decompressed data?
  1558. //
  1559. *pDecompressedDataLen += pArapConn->pV42bis->decode.output_size;
  1560. return(dwRetCode);
  1561. }