unthwack.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <ip.h>
  4. #include <auth.h>
  5. #include "ppp.h"
  6. #include "thwack.h"
  7. enum
  8. {
  9. DMaxFastLen = 7,
  10. DBigLenCode = 0x3c, /* minimum code for large lenth encoding */
  11. DBigLenBits = 6,
  12. DBigLenBase = 1 /* starting items to encode for big lens */
  13. };
  14. static uchar lenval[1 << (DBigLenBits - 1)] =
  15. {
  16. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  17. 3, 3, 3, 3, 3, 3, 3, 3,
  18. 4, 4, 4, 4,
  19. 5,
  20. 6,
  21. 255,
  22. 255
  23. };
  24. static uchar lenbits[] =
  25. {
  26. 0, 0, 0,
  27. 2, 3, 5, 5,
  28. };
  29. static uchar offbits[16] =
  30. {
  31. 5, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 12, 13
  32. };
  33. static ushort offbase[16] =
  34. {
  35. 0, 0x20,
  36. 0x40, 0x60,
  37. 0x80, 0xc0,
  38. 0x100, 0x180,
  39. 0x200, 0x300,
  40. 0x400, 0x600,
  41. 0x800, 0xc00,
  42. 0x1000,
  43. 0x2000
  44. };
  45. void
  46. unthwackinit(Unthwack *ut)
  47. {
  48. int i;
  49. memset(ut, 0, sizeof *ut);
  50. for(i = 0; i < DWinBlocks; i++)
  51. ut->blocks[i].data = ut->data[i];
  52. }
  53. ulong
  54. unthwackstate(Unthwack *ut, uchar *mask)
  55. {
  56. ulong bseq, seq;
  57. int slot, m;
  58. seq = ~0UL;
  59. m = 0;
  60. slot = ut->slot;
  61. for(;;){
  62. slot--;
  63. if(slot < 0)
  64. slot += DWinBlocks;
  65. if(slot == ut->slot)
  66. break;
  67. if(ut->blocks[slot].maxoff == 0)
  68. continue;
  69. bseq = ut->blocks[slot].seq;
  70. if(seq == ~0UL)
  71. seq = bseq;
  72. else if(seq - bseq > MaxSeqMask)
  73. break;
  74. else
  75. m |= 1 << (seq - bseq - 1);
  76. }
  77. *mask = m;
  78. return seq;
  79. }
  80. /*
  81. * insert this block in it's correct sequence number order.
  82. * replace the oldest block, which is always pointed to by ut->slot.
  83. * the encoder doesn't use a history at wraparound,
  84. * so don't worry about that case.
  85. */
  86. static int
  87. unthwackinsert(Unthwack *ut, int len, ulong seq)
  88. {
  89. uchar *d;
  90. int slot, tslot;
  91. tslot = ut->slot;
  92. for(;;){
  93. slot = tslot - 1;
  94. if(slot < 0)
  95. slot += DWinBlocks;
  96. if(ut->blocks[slot].seq <= seq || ut->blocks[slot].maxoff == 0)
  97. break;
  98. d = ut->blocks[tslot].data;
  99. ut->blocks[tslot] = ut->blocks[slot];
  100. ut->blocks[slot].data = d;
  101. tslot = slot;
  102. }
  103. ut->blocks[tslot].seq = seq;
  104. ut->blocks[tslot].maxoff = len;
  105. ut->slot++;
  106. if(ut->slot >= DWinBlocks)
  107. ut->slot = 0;
  108. ut->blocks[ut->slot].seq = ~0UL;
  109. ut->blocks[ut->slot].maxoff = 0;
  110. return tslot;
  111. }
  112. int
  113. unthwackadd(Unthwack *ut, uchar *src, int nsrc, ulong seq)
  114. {
  115. int tslot;
  116. if(nsrc > ThwMaxBlock)
  117. return -1;
  118. tslot = unthwackinsert(ut, nsrc, seq);
  119. if(tslot < 0)
  120. return -1;
  121. memmove(ut->blocks[tslot].data, src, nsrc);
  122. return nsrc;
  123. }
  124. int
  125. unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
  126. {
  127. UnthwBlock blocks[CompBlocks], *b, *eblocks;
  128. uchar *s, *d, *dmax, *smax, lit;
  129. ulong cmask, cseq, bseq, utbits;
  130. int i, off, len, bits, slot, use, code, utnbits, overbits, lithist;
  131. if(nsrc < 4 || nsrc > ThwMaxBlock){
  132. snprint(ut->err, ThwErrLen, "block too small or large");
  133. return -1;
  134. }
  135. slot = ut->slot;
  136. b = blocks;
  137. *b = ut->blocks[slot];
  138. d = b->data;
  139. dmax = d + ndst;
  140. /*
  141. * set up the history blocks
  142. */
  143. cseq = seq - src[0];
  144. cmask = src[1];
  145. b++;
  146. while(cseq != seq && b < blocks + CompBlocks){
  147. slot--;
  148. if(slot < 0)
  149. slot += DWinBlocks;
  150. if(slot == ut->slot)
  151. break;
  152. bseq = ut->blocks[slot].seq;
  153. if(bseq == cseq){
  154. *b = ut->blocks[slot];
  155. b++;
  156. if(cmask == 0){
  157. cseq = seq;
  158. break;
  159. }
  160. do{
  161. bits = cmask & 1;
  162. cseq--;
  163. cmask >>= 1;
  164. }while(!bits);
  165. }
  166. }
  167. eblocks = b;
  168. if(cseq != seq){
  169. snprint(ut->err, ThwErrLen, "blocks dropped: seq=%ld cseq=%ld %d cmask=%#lx %#x\n", seq, cseq, src[0], cmask, src[1]);
  170. return -2;
  171. }
  172. smax = src + nsrc;
  173. src += 2;
  174. utnbits = 0;
  175. utbits = 0;
  176. overbits = 0;
  177. lithist = ~0;
  178. while(src < smax || utnbits - overbits >= MinDecode){
  179. while(utnbits <= 24){
  180. utbits <<= 8;
  181. if(src < smax)
  182. utbits |= *src++;
  183. else
  184. overbits += 8;
  185. utnbits += 8;
  186. }
  187. /*
  188. * literal
  189. */
  190. len = lenval[(utbits >> (utnbits - 5)) & 0x1f];
  191. if(len == 0){
  192. if(lithist & 0xf){
  193. utnbits -= 9;
  194. lit = (utbits >> utnbits) & 0xff;
  195. lit &= 255;
  196. }else{
  197. utnbits -= 8;
  198. lit = (utbits >> utnbits) & 0x7f;
  199. if(lit < 32){
  200. if(lit < 24){
  201. utnbits -= 2;
  202. lit = (lit << 2) | ((utbits >> utnbits) & 3);
  203. }else{
  204. utnbits -= 3;
  205. lit = (lit << 3) | ((utbits >> utnbits) & 7);
  206. }
  207. lit = (lit - 64) & 0xff;
  208. }
  209. }
  210. if(d >= dmax){
  211. snprint(ut->err, ThwErrLen, "too much output");
  212. return -1;
  213. }
  214. *d++ = lit;
  215. lithist = (lithist << 1) | (lit < 32) | (lit > 127);
  216. blocks->maxoff++;
  217. continue;
  218. }
  219. /*
  220. * length
  221. */
  222. if(len < 255)
  223. utnbits -= lenbits[len];
  224. else{
  225. utnbits -= DBigLenBits;
  226. code = ((utbits >> utnbits) & ((1 << DBigLenBits) - 1)) - DBigLenCode;
  227. len = DMaxFastLen;
  228. use = DBigLenBase;
  229. bits = (DBigLenBits & 1) ^ 1;
  230. while(code >= use){
  231. len += use;
  232. code -= use;
  233. code <<= 1;
  234. utnbits--;
  235. if(utnbits < 0){
  236. snprint(ut->err, ThwErrLen, "len out of range");
  237. return -1;
  238. }
  239. code |= (utbits >> utnbits) & 1;
  240. use <<= bits;
  241. bits ^= 1;
  242. }
  243. len += code;
  244. while(utnbits <= 24){
  245. utbits <<= 8;
  246. if(src < smax)
  247. utbits |= *src++;
  248. else
  249. overbits += 8;
  250. utnbits += 8;
  251. }
  252. }
  253. /*
  254. * offset
  255. */
  256. utnbits -= 4;
  257. bits = (utbits >> utnbits) & 0xf;
  258. off = offbase[bits];
  259. bits = offbits[bits];
  260. utnbits -= bits;
  261. off |= (utbits >> utnbits) & ((1 << bits) - 1);
  262. off++;
  263. b = blocks;
  264. while(off > b->maxoff){
  265. off -= b->maxoff;
  266. b++;
  267. if(b >= eblocks){
  268. snprint(ut->err, ThwErrLen, "offset out of range");
  269. return -1;
  270. }
  271. }
  272. if(d + len > dmax
  273. || b != blocks && len > off){
  274. snprint(ut->err, ThwErrLen, "len out of range");
  275. return -1;
  276. }
  277. s = b->data + b->maxoff - off;
  278. blocks->maxoff += len;
  279. for(i = 0; i < len; i++)
  280. d[i] = s[i];
  281. d += len;
  282. }
  283. if(utnbits < overbits){
  284. snprint(ut->err, ThwErrLen, "compressed data overrun");
  285. return -1;
  286. }
  287. len = d - blocks->data;
  288. memmove(dst, blocks->data, len);
  289. unthwackinsert(ut, len, seq);
  290. return len;
  291. }