STM32F769IDiscovery  1.00
uDANTE Audio Networking with STM32F7 DISCO board
vj.c
Go to the documentation of this file.
1 /*
2  * Routines to compress and uncompess tcp packets (for transmission
3  * over low speed serial lines.
4  *
5  * Copyright (c) 1989 Regents of the University of California.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by the University of California, Berkeley. The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
21  * Initial distribution.
22  *
23  * Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au,
24  * so that the entire packet being decompressed doesn't have
25  * to be in contiguous memory (just the compressed header).
26  *
27  * Modified March 1998 by Guy Lancaster, glanca@gesn.com,
28  * for a 16 bit processor.
29  */
30 
31 #include "lwip/opt.h"
32 #if PPP_SUPPORT && VJ_SUPPORT && LWIP_TCP /* don't build if not configured for use in lwipopts.h */
33 
34 #include "netif/ppp/ppp_impl.h"
35 #include "netif/ppp/pppdebug.h"
36 
37 #include "netif/ppp/vj.h"
38 
39 #include <string.h>
40 
41 #if LINK_STATS
42 #define INCR(counter) ++comp->stats.counter
43 #else
44 #define INCR(counter)
45 #endif
46 
47 void
48 vj_compress_init(struct vjcompress *comp)
49 {
50  u8_t i;
51  struct cstate *tstate = comp->tstate;
52 
53 #if MAX_SLOTS == 0
54  memset((char *)comp, 0, sizeof(*comp));
55 #endif
56  comp->maxSlotIndex = MAX_SLOTS - 1;
57  comp->compressSlot = 0; /* Disable slot ID compression by default. */
58  for (i = MAX_SLOTS - 1; i > 0; --i) {
59  tstate[i].cs_id = i;
60  tstate[i].cs_next = &tstate[i - 1];
61  }
62  tstate[0].cs_next = &tstate[MAX_SLOTS - 1];
63  tstate[0].cs_id = 0;
64  comp->last_cs = &tstate[0];
65  comp->last_recv = 255;
66  comp->last_xmit = 255;
67  comp->flags = VJF_TOSS;
68 }
69 
70 
71 /* ENCODE encodes a number that is known to be non-zero. ENCODEZ
72  * checks for zero (since zero has to be encoded in the long, 3 byte
73  * form).
74  */
75 #define ENCODE(n) { \
76  if ((u16_t)(n) >= 256) { \
77  *cp++ = 0; \
78  cp[1] = (u8_t)(n); \
79  cp[0] = (u8_t)((n) >> 8); \
80  cp += 2; \
81  } else { \
82  *cp++ = (u8_t)(n); \
83  } \
84 }
85 #define ENCODEZ(n) { \
86  if ((u16_t)(n) >= 256 || (u16_t)(n) == 0) { \
87  *cp++ = 0; \
88  cp[1] = (u8_t)(n); \
89  cp[0] = (u8_t)((n) >> 8); \
90  cp += 2; \
91  } else { \
92  *cp++ = (u8_t)(n); \
93  } \
94 }
95 
96 #define DECODEL(f) { \
97  if (*cp == 0) {\
98  u32_t tmp_ = ntohl(f) + ((cp[1] << 8) | cp[2]); \
99  (f) = htonl(tmp_); \
100  cp += 3; \
101  } else { \
102  u32_t tmp_ = ntohl(f) + (u32_t)*cp++; \
103  (f) = htonl(tmp_); \
104  } \
105 }
106 
107 #define DECODES(f) { \
108  if (*cp == 0) {\
109  u16_t tmp_ = ntohs(f) + (((u16_t)cp[1] << 8) | cp[2]); \
110  (f) = htons(tmp_); \
111  cp += 3; \
112  } else { \
113  u16_t tmp_ = ntohs(f) + (u16_t)*cp++; \
114  (f) = htons(tmp_); \
115  } \
116 }
117 
118 #define DECODEU(f) { \
119  if (*cp == 0) {\
120  (f) = htons(((u16_t)cp[1] << 8) | cp[2]); \
121  cp += 3; \
122  } else { \
123  (f) = htons((u16_t)*cp++); \
124  } \
125 }
126 
127 /*
128  * vj_compress_tcp - Attempt to do Van Jacobson header compression on a
129  * packet. This assumes that nb and comp are not null and that the first
130  * buffer of the chain contains a valid IP header.
131  * Return the VJ type code indicating whether or not the packet was
132  * compressed.
133  */
134 u8_t
135 vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb)
136 {
137  struct pbuf *np = *pb;
138  struct ip_hdr *ip = (struct ip_hdr *)np->payload;
139  struct cstate *cs = comp->last_cs->cs_next;
140  u16_t ilen = IPH_HL(ip);
141  u16_t hlen;
142  struct tcp_hdr *oth;
143  struct tcp_hdr *th;
144  u16_t deltaS, deltaA = 0;
145  u32_t deltaL;
146  u32_t changes = 0;
147  u8_t new_seq[16];
148  u8_t *cp = new_seq;
149 
150  /*
151  * Check that the packet is IP proto TCP.
152  */
153  if (IPH_PROTO(ip) != IP_PROTO_TCP) {
154  return (TYPE_IP);
155  }
156 
157  /*
158  * Bail if this is an IP fragment or if the TCP packet isn't
159  * `compressible' (i.e., ACK isn't set or some other control bit is
160  * set).
161  */
162  if ((IPH_OFFSET(ip) & PP_HTONS(0x3fff)) || np->tot_len < 40) {
163  return (TYPE_IP);
164  }
165  th = (struct tcp_hdr *)&((u32_t*)ip)[ilen];
166  if ((TCPH_FLAGS(th) & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) {
167  return (TYPE_IP);
168  }
169 
170  /* Check that the TCP/IP headers are contained in the first buffer. */
171  hlen = ilen + TCPH_HDRLEN(th);
172  hlen <<= 2;
173  if (np->len < hlen) {
174  PPPDEBUG(LOG_INFO, ("vj_compress_tcp: header len %d spans buffers\n", hlen));
175  return (TYPE_IP);
176  }
177 
178  /* TCP stack requires that we don't change the packet payload, therefore we copy
179  * the whole packet before compression. */
180  np = pbuf_alloc(PBUF_RAW, np->tot_len, PBUF_POOL);
181  if (!np) {
182  return (TYPE_IP);
183  }
184 
185  if (pbuf_copy(np, *pb) != ERR_OK) {
186  pbuf_free(np);
187  return (TYPE_IP);
188  }
189 
190  *pb = np;
191  ip = (struct ip_hdr *)np->payload;
192 
193  /*
194  * Packet is compressible -- we're going to send either a
195  * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need
196  * to locate (or create) the connection state. Special case the
197  * most recently used connection since it's most likely to be used
198  * again & we don't have to do any reordering if it's used.
199  */
200  INCR(vjs_packets);
201  if (!ip4_addr_cmp(&ip->src, &cs->cs_ip.src)
202  || !ip4_addr_cmp(&ip->dest, &cs->cs_ip.dest)
203  || *(u32_t*)th != ((u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) {
204  /*
205  * Wasn't the first -- search for it.
206  *
207  * States are kept in a circularly linked list with
208  * last_cs pointing to the end of the list. The
209  * list is kept in lru order by moving a state to the
210  * head of the list whenever it is referenced. Since
211  * the list is short and, empirically, the connection
212  * we want is almost always near the front, we locate
213  * states via linear search. If we don't find a state
214  * for the datagram, the oldest state is (re-)used.
215  */
216  struct cstate *lcs;
217  struct cstate *lastcs = comp->last_cs;
218 
219  do {
220  lcs = cs; cs = cs->cs_next;
221  INCR(vjs_searches);
222  if (ip4_addr_cmp(&ip->src, &cs->cs_ip.src)
223  && ip4_addr_cmp(&ip->dest, &cs->cs_ip.dest)
224  && *(u32_t*)th == ((u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) {
225  goto found;
226  }
227  } while (cs != lastcs);
228 
229  /*
230  * Didn't find it -- re-use oldest cstate. Send an
231  * uncompressed packet that tells the other side what
232  * connection number we're using for this conversation.
233  * Note that since the state list is circular, the oldest
234  * state points to the newest and we only need to set
235  * last_cs to update the lru linkage.
236  */
237  INCR(vjs_misses);
238  comp->last_cs = lcs;
239  goto uncompressed;
240 
241  found:
242  /*
243  * Found it -- move to the front on the connection list.
244  */
245  if (cs == lastcs) {
246  comp->last_cs = lcs;
247  } else {
248  lcs->cs_next = cs->cs_next;
249  cs->cs_next = lastcs->cs_next;
250  lastcs->cs_next = cs;
251  }
252  }
253 
254  oth = (struct tcp_hdr *)&((u32_t*)&cs->cs_ip)[ilen];
255  deltaS = ilen;
256 
257  /*
258  * Make sure that only what we expect to change changed. The first
259  * line of the `if' checks the IP protocol version, header length &
260  * type of service. The 2nd line checks the "Don't fragment" bit.
261  * The 3rd line checks the time-to-live and protocol (the protocol
262  * check is unnecessary but costless). The 4th line checks the TCP
263  * header length. The 5th line checks IP options, if any. The 6th
264  * line checks TCP options, if any. If any of these things are
265  * different between the previous & current datagram, we send the
266  * current datagram `uncompressed'.
267  */
268  if (((u16_t*)ip)[0] != ((u16_t*)&cs->cs_ip)[0]
269  || ((u16_t*)ip)[3] != ((u16_t*)&cs->cs_ip)[3]
270  || ((u16_t*)ip)[4] != ((u16_t*)&cs->cs_ip)[4]
271  || TCPH_HDRLEN(th) != TCPH_HDRLEN(oth)
272  || (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2))
273  || (TCPH_HDRLEN(th) > 5 && BCMP(th + 1, oth + 1, (TCPH_HDRLEN(th) - 5) << 2))) {
274  goto uncompressed;
275  }
276 
277  /*
278  * Figure out which of the changing fields changed. The
279  * receiver expects changes in the order: urgent, window,
280  * ack, seq (the order minimizes the number of temporaries
281  * needed in this section of code).
282  */
283  if (TCPH_FLAGS(th) & TCP_URG) {
284  deltaS = ntohs(th->urgp);
285  ENCODEZ(deltaS);
286  changes |= NEW_U;
287  } else if (th->urgp != oth->urgp) {
288  /* argh! URG not set but urp changed -- a sensible
289  * implementation should never do this but RFC793
290  * doesn't prohibit the change so we have to deal
291  * with it. */
292  goto uncompressed;
293  }
294 
295  if ((deltaS = (u16_t)(ntohs(th->wnd) - ntohs(oth->wnd))) != 0) {
296  ENCODE(deltaS);
297  changes |= NEW_W;
298  }
299 
300  if ((deltaL = ntohl(th->ackno) - ntohl(oth->ackno)) != 0) {
301  if (deltaL > 0xffff) {
302  goto uncompressed;
303  }
304  deltaA = (u16_t)deltaL;
305  ENCODE(deltaA);
306  changes |= NEW_A;
307  }
308 
309  if ((deltaL = ntohl(th->seqno) - ntohl(oth->seqno)) != 0) {
310  if (deltaL > 0xffff) {
311  goto uncompressed;
312  }
313  deltaS = (u16_t)deltaL;
314  ENCODE(deltaS);
315  changes |= NEW_S;
316  }
317 
318  switch(changes) {
319  case 0:
320  /*
321  * Nothing changed. If this packet contains data and the
322  * last one didn't, this is probably a data packet following
323  * an ack (normal on an interactive connection) and we send
324  * it compressed. Otherwise it's probably a retransmit,
325  * retransmitted ack or window probe. Send it uncompressed
326  * in case the other side missed the compressed version.
327  */
328  if (IPH_LEN(ip) != IPH_LEN(&cs->cs_ip) &&
329  ntohs(IPH_LEN(&cs->cs_ip)) == hlen) {
330  break;
331  }
332  /* no break */
333  /* fall through */
334 
335  case SPECIAL_I:
336  case SPECIAL_D:
337  /*
338  * actual changes match one of our special case encodings --
339  * send packet uncompressed.
340  */
341  goto uncompressed;
342 
343  case NEW_S|NEW_A:
344  if (deltaS == deltaA && deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) {
345  /* special case for echoed terminal traffic */
346  changes = SPECIAL_I;
347  cp = new_seq;
348  }
349  break;
350 
351  case NEW_S:
352  if (deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) {
353  /* special case for data xfer */
354  changes = SPECIAL_D;
355  cp = new_seq;
356  }
357  break;
358  default:
359  break;
360  }
361 
362  deltaS = (u16_t)(ntohs(IPH_ID(ip)) - ntohs(IPH_ID(&cs->cs_ip)));
363  if (deltaS != 1) {
364  ENCODEZ(deltaS);
365  changes |= NEW_I;
366  }
367  if (TCPH_FLAGS(th) & TCP_PSH) {
368  changes |= TCP_PUSH_BIT;
369  }
370  /*
371  * Grab the cksum before we overwrite it below. Then update our
372  * state with this packet's header.
373  */
374  deltaA = ntohs(th->chksum);
375  MEMCPY(&cs->cs_ip, ip, hlen);
376 
377  /*
378  * We want to use the original packet as our compressed packet.
379  * (cp - new_seq) is the number of bytes we need for compressed
380  * sequence numbers. In addition we need one byte for the change
381  * mask, one for the connection id and two for the tcp checksum.
382  * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how
383  * many bytes of the original packet to toss so subtract the two to
384  * get the new packet size.
385  */
386  deltaS = (u16_t)(cp - new_seq);
387  if (!comp->compressSlot || comp->last_xmit != cs->cs_id) {
388  comp->last_xmit = cs->cs_id;
389  hlen -= deltaS + 4;
390  if (pbuf_header(np, -(s16_t)hlen)){
391  /* Can we cope with this failing? Just assert for now */
392  LWIP_ASSERT("pbuf_header failed\n", 0);
393  }
394  cp = (u8_t*)np->payload;
395  *cp++ = (u8_t)(changes | NEW_C);
396  *cp++ = cs->cs_id;
397  } else {
398  hlen -= deltaS + 3;
399  if (pbuf_header(np, -(s16_t)hlen)) {
400  /* Can we cope with this failing? Just assert for now */
401  LWIP_ASSERT("pbuf_header failed\n", 0);
402  }
403  cp = (u8_t*)np->payload;
404  *cp++ = (u8_t)changes;
405  }
406  *cp++ = (u8_t)(deltaA >> 8);
407  *cp++ = (u8_t)deltaA;
408  MEMCPY(cp, new_seq, deltaS);
409  INCR(vjs_compressed);
410  return (TYPE_COMPRESSED_TCP);
411 
412  /*
413  * Update connection state cs & send uncompressed packet (that is,
414  * a regular ip/tcp packet but with the 'conversation id' we hope
415  * to use on future compressed packets in the protocol field).
416  */
417 uncompressed:
418  MEMCPY(&cs->cs_ip, ip, hlen);
419  IPH_PROTO_SET(ip, cs->cs_id);
420  comp->last_xmit = cs->cs_id;
421  return (TYPE_UNCOMPRESSED_TCP);
422 }
423 
424 /*
425  * Called when we may have missed a packet.
426  */
427 void
428 vj_uncompress_err(struct vjcompress *comp)
429 {
430  comp->flags |= VJF_TOSS;
431  INCR(vjs_errorin);
432 }
433 
434 /*
435  * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP.
436  * Return 0 on success, -1 on failure.
437  */
438 int
439 vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp)
440 {
441  u32_t hlen;
442  struct cstate *cs;
443  struct ip_hdr *ip;
444 
445  ip = (struct ip_hdr *)nb->payload;
446  hlen = IPH_HL(ip) << 2;
447  if (IPH_PROTO(ip) >= MAX_SLOTS
448  || hlen + sizeof(struct tcp_hdr) > nb->len
449  || (hlen += TCPH_HDRLEN(((struct tcp_hdr *)&((char *)ip)[hlen])) << 2)
450  > nb->len
451  || hlen > MAX_HDR) {
452  PPPDEBUG(LOG_INFO, ("vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n",
453  IPH_PROTO(ip), hlen, nb->len));
454  comp->flags |= VJF_TOSS;
455  INCR(vjs_errorin);
456  return -1;
457  }
458  cs = &comp->rstate[comp->last_recv = IPH_PROTO(ip)];
459  comp->flags &=~ VJF_TOSS;
460  IPH_PROTO_SET(ip, IP_PROTO_TCP);
461  MEMCPY(&cs->cs_ip, ip, hlen);
462  cs->cs_hlen = (u16_t)hlen;
463  INCR(vjs_uncompressedin);
464  return 0;
465 }
466 
467 /*
468  * Uncompress a packet of type TYPE_COMPRESSED_TCP.
469  * The packet is composed of a buffer chain and the first buffer
470  * must contain an accurate chain length.
471  * The first buffer must include the entire compressed TCP/IP header.
472  * This procedure replaces the compressed header with the uncompressed
473  * header and returns the length of the VJ header.
474  */
475 int
476 vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp)
477 {
478  u8_t *cp;
479  struct tcp_hdr *th;
480  struct cstate *cs;
481  u16_t *bp;
482  struct pbuf *n0 = *nb;
483  u32_t tmp;
484  u32_t vjlen, hlen, changes;
485 
486  INCR(vjs_compressedin);
487  cp = (u8_t*)n0->payload;
488  changes = *cp++;
489  if (changes & NEW_C) {
490  /*
491  * Make sure the state index is in range, then grab the state.
492  * If we have a good state index, clear the 'discard' flag.
493  */
494  if (*cp >= MAX_SLOTS) {
495  PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: bad cid=%d\n", *cp));
496  goto bad;
497  }
498 
499  comp->flags &=~ VJF_TOSS;
500  comp->last_recv = *cp++;
501  } else {
502  /*
503  * this packet has an implicit state index. If we've
504  * had a line error since the last time we got an
505  * explicit state index, we have to toss the packet.
506  */
507  if (comp->flags & VJF_TOSS) {
508  PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: tossing\n"));
509  INCR(vjs_tossed);
510  return (-1);
511  }
512  }
513  cs = &comp->rstate[comp->last_recv];
514  hlen = IPH_HL(&cs->cs_ip) << 2;
515  th = (struct tcp_hdr *)&((u8_t*)&cs->cs_ip)[hlen];
516  th->chksum = htons((*cp << 8) | cp[1]);
517  cp += 2;
518  if (changes & TCP_PUSH_BIT) {
519  TCPH_SET_FLAG(th, TCP_PSH);
520  } else {
521  TCPH_UNSET_FLAG(th, TCP_PSH);
522  }
523 
524  switch (changes & SPECIALS_MASK) {
525  case SPECIAL_I:
526  {
527  u32_t i = ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen;
528  /* some compilers can't nest inline assembler.. */
529  tmp = ntohl(th->ackno) + i;
530  th->ackno = htonl(tmp);
531  tmp = ntohl(th->seqno) + i;
532  th->seqno = htonl(tmp);
533  }
534  break;
535 
536  case SPECIAL_D:
537  /* some compilers can't nest inline assembler.. */
538  tmp = ntohl(th->seqno) + ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen;
539  th->seqno = htonl(tmp);
540  break;
541 
542  default:
543  if (changes & NEW_U) {
544  TCPH_SET_FLAG(th, TCP_URG);
545  DECODEU(th->urgp);
546  } else {
547  TCPH_UNSET_FLAG(th, TCP_URG);
548  }
549  if (changes & NEW_W) {
550  DECODES(th->wnd);
551  }
552  if (changes & NEW_A) {
553  DECODEL(th->ackno);
554  }
555  if (changes & NEW_S) {
556  DECODEL(th->seqno);
557  }
558  break;
559  }
560  if (changes & NEW_I) {
561  DECODES(cs->cs_ip._id);
562  } else {
563  IPH_ID_SET(&cs->cs_ip, ntohs(IPH_ID(&cs->cs_ip)) + 1);
564  IPH_ID_SET(&cs->cs_ip, htons(IPH_ID(&cs->cs_ip)));
565  }
566 
567  /*
568  * At this point, cp points to the first byte of data in the
569  * packet. Fill in the IP total length and update the IP
570  * header checksum.
571  */
572  vjlen = (u16_t)(cp - (u8_t*)n0->payload);
573  if (n0->len < vjlen) {
574  /*
575  * We must have dropped some characters (crc should detect
576  * this but the old slip framing won't)
577  */
578  PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: head buffer %d too short %d\n",
579  n0->len, vjlen));
580  goto bad;
581  }
582 
583 #if BYTE_ORDER == LITTLE_ENDIAN
584  tmp = n0->tot_len - vjlen + cs->cs_hlen;
585  IPH_LEN_SET(&cs->cs_ip, htons((u16_t)tmp));
586 #else
587  IPH_LEN_SET(&cs->cs_ip, htons(n0->tot_len - vjlen + cs->cs_hlen));
588 #endif
589 
590  /* recompute the ip header checksum */
591  bp = (u16_t*) &cs->cs_ip;
592  IPH_CHKSUM_SET(&cs->cs_ip, 0);
593  for (tmp = 0; hlen > 0; hlen -= 2) {
594  tmp += *bp++;
595  }
596  tmp = (tmp & 0xffff) + (tmp >> 16);
597  tmp = (tmp & 0xffff) + (tmp >> 16);
598  IPH_CHKSUM_SET(&cs->cs_ip, (u16_t)(~tmp));
599 
600  /* Remove the compressed header and prepend the uncompressed header. */
601  if (pbuf_header(n0, -(s16_t)vjlen)) {
602  /* Can we cope with this failing? Just assert for now */
603  LWIP_ASSERT("pbuf_header failed\n", 0);
604  goto bad;
605  }
606 
607  if(LWIP_MEM_ALIGN(n0->payload) != n0->payload) {
608  struct pbuf *np, *q;
609  u8_t *bufptr;
610 
611 #if IP_FORWARD
612  /* If IP forwarding is enabled we are using a PBUF_LINK packet type so
613  * the packet is being allocated with enough header space to be
614  * forwarded (to Ethernet for example).
615  */
616  np = pbuf_alloc(PBUF_LINK, n0->len + cs->cs_hlen, PBUF_POOL);
617 #else /* IP_FORWARD */
618  np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL);
619 #endif /* IP_FORWARD */
620  if(!np) {
621  PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: realign failed\n"));
622  goto bad;
623  }
624 
625  if (pbuf_header(np, -(s16_t)cs->cs_hlen)) {
626  /* Can we cope with this failing? Just assert for now */
627  LWIP_ASSERT("pbuf_header failed\n", 0);
628  goto bad;
629  }
630 
631  bufptr = (u8_t*)n0->payload;
632  for(q = np; q != NULL; q = q->next) {
633  MEMCPY(q->payload, bufptr, q->len);
634  bufptr += q->len;
635  }
636 
637  if(n0->next) {
638  pbuf_chain(np, n0->next);
639  pbuf_dechain(n0);
640  }
641  pbuf_free(n0);
642  n0 = np;
643  }
644 
645  if (pbuf_header(n0, (s16_t)cs->cs_hlen)) {
646  struct pbuf *np;
647 
648  LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE);
649  np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL);
650  if(!np) {
651  PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: prepend failed\n"));
652  goto bad;
653  }
654  pbuf_cat(np, n0);
655  n0 = np;
656  }
657  LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen);
658  MEMCPY(n0->payload, &cs->cs_ip, cs->cs_hlen);
659 
660  *nb = n0;
661 
662  return vjlen;
663 
664 bad:
665  comp->flags |= VJF_TOSS;
666  INCR(vjs_errorin);
667  return (-1);
668 }
669 
670 #endif /* PPP_SUPPORT && VJ_SUPPORT && LWIP_TCP */
671 
signed short s16_t
Definition: cc.h:41
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
Definition: pbuf.c:603
#define htons(x)
Definition: def.h:86
#define IP_PROTO_TCP
Definition: ip.h:53
#define MEMCPY(dst, src, len)
Definition: opt.h:84
if(LCD_Lock==DISABLE)
Definition: lcd_log.c:249
u16_t len
Definition: pbuf.h:125
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:199
#define PBUF_POOL_BUFSIZE
Definition: lwipopts.h:105
Definition: pbuf.h:66
u8_t flags
Definition: pbuf.h:131
#define NULL
Definition: usbd_def.h:53
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:652
Definition: pbuf.h:68
#define ntohl(x)
Definition: def.h:89
err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
Definition: pbuf.c:886
#define PP_HTONS(x)
Definition: def.h:97
unsigned long u32_t
Definition: cc.h:42
void pbuf_chain(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:820
#define ERR_OK
Definition: err.h:52
u16_t tot_len
Definition: pbuf.h:122
Definition: pbuf.h:108
Definition: pbuf.h:90
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:70
struct pbuf * next
Definition: pbuf.h:110
struct pbuf * pbuf_dechain(struct pbuf *p)
Definition: pbuf.c:837
void pbuf_cat(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:779
unsigned char u8_t
Definition: cc.h:38
#define LWIP_MEM_ALIGN(addr)
Definition: mem.h:116
#define ntohs(x)
Definition: def.h:87
#define htonl(x)
Definition: def.h:88
unsigned short u16_t
Definition: cc.h:40
void * payload
Definition: pbuf.h:113