00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 #include "lwip/opt.h"
00065
00066 #include "lwip/stats.h"
00067 #include "lwip/def.h"
00068 #include "lwip/mem.h"
00069 #include "lwip/memp.h"
00070 #include "lwip/pbuf.h"
00071 #include "lwip/sys.h"
00072 #include "arch/perf.h"
00073 #if LWIP_TCP && TCP_QUEUE_OOSEQ
00074 #include "lwip/tcp_impl.h"
00075 #endif
00076 #if LWIP_CHECKSUM_ON_COPY
00077 #include "lwip/inet_chksum.h"
00078 #endif
00079
00080 #include <string.h>
00081
00082 #define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf))
00083
00084
00085 #define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE)
00086
00087 #if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ
00088 #define PBUF_POOL_IS_EMPTY()
00089 #else
00090
00091 #if !NO_SYS
00092 #ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL
00093 #include "lwip/tcpip.h"
00094 #define PBUF_POOL_FREE_OOSEQ_QUEUE_CALL() do { \
00095 if(tcpip_callback_with_block(pbuf_free_ooseq_callback, NULL, 0) != ERR_OK) { \
00096 SYS_ARCH_PROTECT(old_level); \
00097 pbuf_free_ooseq_pending = 0; \
00098 SYS_ARCH_UNPROTECT(old_level); \
00099 } } while(0)
00100 #endif
00101 #endif
00102
00103 volatile u8_t pbuf_free_ooseq_pending;
00104 #define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty()
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 #if !NO_SYS
00115 static
00116 #endif
00117 void
00118 pbuf_free_ooseq(void)
00119 {
00120 struct tcp_pcb* pcb;
00121 SYS_ARCH_DECL_PROTECT(old_level);
00122
00123 SYS_ARCH_PROTECT(old_level);
00124 pbuf_free_ooseq_pending = 0;
00125 SYS_ARCH_UNPROTECT(old_level);
00126
00127 for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
00128 if (NULL != pcb->ooseq) {
00129
00130 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n"));
00131 tcp_segs_free(pcb->ooseq);
00132 pcb->ooseq = NULL;
00133 return;
00134 }
00135 }
00136 }
00137
00138 #if !NO_SYS
00139
00140
00141
00142 static void
00143 pbuf_free_ooseq_callback(void *arg)
00144 {
00145 LWIP_UNUSED_ARG(arg);
00146 pbuf_free_ooseq();
00147 }
00148 #endif
00149
00150
00151 static void
00152 pbuf_pool_is_empty(void)
00153 {
00154 #ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL
00155 SYS_ARCH_DECL_PROTECT(old_level);
00156 SYS_ARCH_PROTECT(old_level);
00157 pbuf_free_ooseq_pending = 1;
00158 SYS_ARCH_UNPROTECT(old_level);
00159 #else
00160 u8_t queued;
00161 SYS_ARCH_DECL_PROTECT(old_level);
00162 SYS_ARCH_PROTECT(old_level);
00163 queued = pbuf_free_ooseq_pending;
00164 pbuf_free_ooseq_pending = 1;
00165 SYS_ARCH_UNPROTECT(old_level);
00166
00167 if(!queued) {
00168
00169 PBUF_POOL_FREE_OOSEQ_QUEUE_CALL();
00170 }
00171 #endif
00172 }
00173 #endif
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 struct pbuf *
00207 pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
00208 {
00209 struct pbuf *p, *q, *r;
00210 u16_t offset;
00211 s32_t rem_len;
00212 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length));
00213
00214
00215 switch (layer) {
00216 case PBUF_TRANSPORT:
00217
00218 offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN;
00219 break;
00220 case PBUF_IP:
00221
00222 offset = PBUF_LINK_HLEN + PBUF_IP_HLEN;
00223 break;
00224 case PBUF_LINK:
00225
00226 offset = PBUF_LINK_HLEN;
00227 break;
00228 case PBUF_RAW:
00229 offset = 0;
00230 break;
00231 default:
00232 LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0);
00233 return NULL;
00234 }
00235
00236 switch (type) {
00237 case PBUF_POOL:
00238
00239 p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
00240 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
00241 if (p == NULL) {
00242 PBUF_POOL_IS_EMPTY();
00243 return NULL;
00244 }
00245 p->type = type;
00246 p->next = NULL;
00247
00248
00249 p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset)));
00250 LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned",
00251 ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
00252
00253 p->tot_len = length;
00254
00255 p->len = LWIP_MIN(length, PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset));
00256 LWIP_ASSERT("check p->payload + p->len does not overflow pbuf",
00257 ((u8_t*)p->payload + p->len <=
00258 (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED));
00259 LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT",
00260 (PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 );
00261
00262 p->ref = 1;
00263
00264
00265
00266
00267 r = p;
00268
00269 rem_len = length - p->len;
00270
00271 while (rem_len > 0) {
00272 q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
00273 if (q == NULL) {
00274 PBUF_POOL_IS_EMPTY();
00275
00276 pbuf_free(p);
00277
00278 return NULL;
00279 }
00280 q->type = type;
00281 q->flags = 0;
00282 q->next = NULL;
00283
00284 r->next = q;
00285
00286 LWIP_ASSERT("rem_len < max_u16_t", rem_len < 0xffff);
00287 q->tot_len = (u16_t)rem_len;
00288
00289 q->len = LWIP_MIN((u16_t)rem_len, PBUF_POOL_BUFSIZE_ALIGNED);
00290 q->payload = (void *)((u8_t *)q + SIZEOF_STRUCT_PBUF);
00291 LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
00292 ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0);
00293 LWIP_ASSERT("check p->payload + p->len does not overflow pbuf",
00294 ((u8_t*)p->payload + p->len <=
00295 (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED));
00296 q->ref = 1;
00297
00298 rem_len -= q->len;
00299
00300 r = q;
00301 }
00302
00303
00304
00305 break;
00306 case PBUF_RAM:
00307
00308 p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length));
00309 if (p == NULL) {
00310 return NULL;
00311 }
00312
00313 p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset));
00314 p->len = p->tot_len = length;
00315 p->next = NULL;
00316 p->type = type;
00317
00318 LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
00319 ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
00320 break;
00321
00322 case PBUF_ROM:
00323
00324 case PBUF_REF:
00325
00326 p = (struct pbuf *)memp_malloc(MEMP_PBUF);
00327 if (p == NULL) {
00328 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00329 ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n",
00330 (type == PBUF_ROM) ? "ROM" : "REF"));
00331 return NULL;
00332 }
00333
00334 p->payload = NULL;
00335 p->len = p->tot_len = length;
00336 p->next = NULL;
00337 p->type = type;
00338 break;
00339 default:
00340 LWIP_ASSERT("pbuf_alloc: erroneous type", 0);
00341 return NULL;
00342 }
00343
00344 p->ref = 1;
00345
00346 p->flags = 0;
00347 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
00348 return p;
00349 }
00350
00351 #if LWIP_SUPPORT_CUSTOM_PBUF
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 struct pbuf*
00367 pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p,
00368 void *payload_mem, u16_t payload_mem_len)
00369 {
00370 u16_t offset;
00371 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length));
00372
00373
00374 switch (l) {
00375 case PBUF_TRANSPORT:
00376
00377 offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN;
00378 break;
00379 case PBUF_IP:
00380
00381 offset = PBUF_LINK_HLEN + PBUF_IP_HLEN;
00382 break;
00383 case PBUF_LINK:
00384
00385 offset = PBUF_LINK_HLEN;
00386 break;
00387 case PBUF_RAW:
00388 offset = 0;
00389 break;
00390 default:
00391 LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0);
00392 return NULL;
00393 }
00394
00395 if (LWIP_MEM_ALIGN_SIZE(offset) + length > payload_mem_len) {
00396 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloced_custom(length=%"U16_F") buffer too short\n", length));
00397 return NULL;
00398 }
00399
00400 p->pbuf.next = NULL;
00401 if (payload_mem != NULL) {
00402 p->pbuf.payload = (u8_t *)payload_mem + LWIP_MEM_ALIGN_SIZE(offset);
00403 } else {
00404 p->pbuf.payload = NULL;
00405 }
00406 p->pbuf.flags = PBUF_FLAG_IS_CUSTOM;
00407 p->pbuf.len = p->pbuf.tot_len = length;
00408 p->pbuf.type = type;
00409 p->pbuf.ref = 1;
00410 return &p->pbuf;
00411 }
00412 #endif
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 void
00430 pbuf_realloc(struct pbuf *p, u16_t new_len)
00431 {
00432 struct pbuf *q;
00433 u16_t rem_len;
00434 s32_t grow;
00435
00436 LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL);
00437 LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL ||
00438 p->type == PBUF_ROM ||
00439 p->type == PBUF_RAM ||
00440 p->type == PBUF_REF);
00441
00442
00443 if (new_len >= p->tot_len) {
00444
00445 return;
00446 }
00447
00448
00449
00450 grow = new_len - p->tot_len;
00451
00452
00453 rem_len = new_len;
00454 q = p;
00455
00456 while (rem_len > q->len) {
00457
00458 rem_len -= q->len;
00459
00460 LWIP_ASSERT("grow < max_u16_t", grow < 0xffff);
00461 q->tot_len += (u16_t)grow;
00462
00463 q = q->next;
00464 LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL);
00465 }
00466
00467
00468
00469
00470
00471 if ((q->type == PBUF_RAM) && (rem_len != q->len)) {
00472
00473 q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len);
00474 LWIP_ASSERT("mem_trim returned q == NULL", q != NULL);
00475 }
00476
00477 q->len = rem_len;
00478 q->tot_len = q->len;
00479
00480
00481 if (q->next != NULL) {
00482
00483 pbuf_free(q->next);
00484 }
00485
00486 q->next = NULL;
00487
00488 }
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510 u8_t
00511 pbuf_header(struct pbuf *p, s16_t header_size_increment)
00512 {
00513 u16_t type;
00514 void *payload;
00515 u16_t increment_magnitude;
00516
00517 LWIP_ASSERT("p != NULL", p != NULL);
00518 if ((header_size_increment == 0) || (p == NULL)) {
00519 return 0;
00520 }
00521
00522 if (header_size_increment < 0){
00523 increment_magnitude = -header_size_increment;
00524
00525 LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;);
00526 } else {
00527 increment_magnitude = header_size_increment;
00528 #if 0
00529
00530
00531
00532 LWIP_ASSERT("p->type == PBUF_RAM || p->type == PBUF_POOL",
00533 p->type == PBUF_RAM || p->type == PBUF_POOL);
00534
00535 LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF",
00536 (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF);
00537 #endif
00538 }
00539
00540 type = p->type;
00541
00542 payload = p->payload;
00543
00544
00545 if (type == PBUF_RAM || type == PBUF_POOL) {
00546
00547 p->payload = (u8_t *)p->payload - header_size_increment;
00548
00549 if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) {
00550 LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00551 ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
00552 (void *)p->payload, (void *)(p + 1)));
00553
00554 p->payload = payload;
00555
00556 return 1;
00557 }
00558
00559 } else if (type == PBUF_REF || type == PBUF_ROM) {
00560
00561 if ((header_size_increment < 0) && (increment_magnitude <= p->len)) {
00562
00563 p->payload = (u8_t *)p->payload - header_size_increment;
00564 } else {
00565
00566
00567 return 1;
00568 }
00569 } else {
00570
00571 LWIP_ASSERT("bad pbuf type", 0);
00572 return 1;
00573 }
00574
00575 p->len += header_size_increment;
00576 p->tot_len += header_size_increment;
00577
00578 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n",
00579 (void *)payload, (void *)p->payload, header_size_increment));
00580
00581 return 0;
00582 }
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 u8_t
00618 pbuf_free(struct pbuf *p)
00619 {
00620 u16_t type;
00621 struct pbuf *q;
00622 u8_t count;
00623
00624 if (p == NULL) {
00625 LWIP_ASSERT("p != NULL", p != NULL);
00626
00627 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00628 ("pbuf_free(p == NULL) was called.\n"));
00629 return 0;
00630 }
00631 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p));
00632
00633 PERF_START;
00634
00635 LWIP_ASSERT("pbuf_free: sane type",
00636 p->type == PBUF_RAM || p->type == PBUF_ROM ||
00637 p->type == PBUF_REF || p->type == PBUF_POOL);
00638
00639 count = 0;
00640
00641
00642 while (p != NULL) {
00643 u16_t ref;
00644 SYS_ARCH_DECL_PROTECT(old_level);
00645
00646
00647
00648 SYS_ARCH_PROTECT(old_level);
00649
00650 LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
00651
00652 ref = --(p->ref);
00653 SYS_ARCH_UNPROTECT(old_level);
00654
00655 if (ref == 0) {
00656
00657 q = p->next;
00658 LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p));
00659 type = p->type;
00660 #if LWIP_SUPPORT_CUSTOM_PBUF
00661
00662 if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) {
00663 struct pbuf_custom *pc = (struct pbuf_custom*)p;
00664 LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL);
00665 pc->custom_free_function(p);
00666 } else
00667 #endif
00668 {
00669
00670 if (type == PBUF_POOL) {
00671 memp_free(MEMP_PBUF_POOL, p);
00672
00673 } else if (type == PBUF_ROM || type == PBUF_REF) {
00674 memp_free(MEMP_PBUF, p);
00675
00676 } else {
00677 mem_free(p);
00678 }
00679 }
00680 count++;
00681
00682 p = q;
00683
00684
00685 } else {
00686 LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref));
00687
00688 p = NULL;
00689 }
00690 }
00691 PERF_STOP("pbuf_free");
00692
00693 return count;
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703 u8_t
00704 pbuf_clen(struct pbuf *p)
00705 {
00706 u8_t len;
00707
00708 len = 0;
00709 while (p != NULL) {
00710 ++len;
00711 p = p->next;
00712 }
00713 return len;
00714 }
00715
00716
00717
00718
00719
00720
00721
00722 void
00723 pbuf_ref(struct pbuf *p)
00724 {
00725 SYS_ARCH_DECL_PROTECT(old_level);
00726
00727 if (p != NULL) {
00728 SYS_ARCH_PROTECT(old_level);
00729 ++(p->ref);
00730 SYS_ARCH_UNPROTECT(old_level);
00731 }
00732 }
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744 void
00745 pbuf_cat(struct pbuf *h, struct pbuf *t)
00746 {
00747 struct pbuf *p;
00748
00749 LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)",
00750 ((h != NULL) && (t != NULL)), return;);
00751
00752
00753 for (p = h; p->next != NULL; p = p->next) {
00754
00755 p->tot_len += t->tot_len;
00756 }
00757
00758 LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
00759 LWIP_ASSERT("p->next == NULL", p->next == NULL);
00760
00761 p->tot_len += t->tot_len;
00762
00763 p->next = t;
00764
00765
00766
00767 }
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785 void
00786 pbuf_chain(struct pbuf *h, struct pbuf *t)
00787 {
00788 pbuf_cat(h, t);
00789
00790 pbuf_ref(t);
00791 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
00792 }
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802 struct pbuf *
00803 pbuf_dechain(struct pbuf *p)
00804 {
00805 struct pbuf *q;
00806 u8_t tail_gone = 1;
00807
00808 q = p->next;
00809
00810 if (q != NULL) {
00811
00812 LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len);
00813
00814 q->tot_len = p->tot_len - p->len;
00815
00816 p->next = NULL;
00817
00818 p->tot_len = p->len;
00819
00820 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
00821 tail_gone = pbuf_free(q);
00822 if (tail_gone > 0) {
00823 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE,
00824 ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
00825 }
00826
00827 }
00828
00829 LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
00830 return ((tail_gone > 0) ? NULL : q);
00831 }
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851 err_t
00852 pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
00853 {
00854 u16_t offset_to=0, offset_from=0, len;
00855
00856 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n",
00857 (void*)p_to, (void*)p_from));
00858
00859
00860 LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) &&
00861 (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;);
00862
00863
00864 do
00865 {
00866
00867 if ((p_to->len - offset_to) >= (p_from->len - offset_from)) {
00868
00869 len = p_from->len - offset_from;
00870 } else {
00871
00872 len = p_to->len - offset_to;
00873 }
00874 MEMCPY((u8_t*)p_to->payload + offset_to, (u8_t*)p_from->payload + offset_from, len);
00875 offset_to += len;
00876 offset_from += len;
00877 LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len);
00878 LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len);
00879 if (offset_from >= p_from->len) {
00880
00881 offset_from = 0;
00882 p_from = p_from->next;
00883 }
00884 if (offset_to == p_to->len) {
00885
00886 offset_to = 0;
00887 p_to = p_to->next;
00888 LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL) , return ERR_ARG;);
00889 }
00890
00891 if((p_from != NULL) && (p_from->len == p_from->tot_len)) {
00892
00893 LWIP_ERROR("pbuf_copy() does not allow packet queues!\n",
00894 (p_from->next == NULL), return ERR_VAL;);
00895 }
00896 if((p_to != NULL) && (p_to->len == p_to->tot_len)) {
00897
00898 LWIP_ERROR("pbuf_copy() does not allow packet queues!\n",
00899 (p_to->next == NULL), return ERR_VAL;);
00900 }
00901 } while (p_from);
00902 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n"));
00903 return ERR_OK;
00904 }
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917 u16_t
00918 pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
00919 {
00920 struct pbuf *p;
00921 u16_t left;
00922 u16_t buf_copy_len;
00923 u16_t copied_total = 0;
00924
00925 LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;);
00926 LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;);
00927
00928 left = 0;
00929
00930 if((buf == NULL) || (dataptr == NULL)) {
00931 return 0;
00932 }
00933
00934
00935 for(p = buf; len != 0 && p != NULL; p = p->next) {
00936 if ((offset != 0) && (offset >= p->len)) {
00937
00938 offset -= p->len;
00939 } else {
00940
00941 buf_copy_len = p->len - offset;
00942 if (buf_copy_len > len)
00943 buf_copy_len = len;
00944
00945 MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len);
00946 copied_total += buf_copy_len;
00947 left += buf_copy_len;
00948 len -= buf_copy_len;
00949 offset = 0;
00950 }
00951 }
00952 return copied_total;
00953 }
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965 err_t
00966 pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)
00967 {
00968 struct pbuf *p;
00969 u16_t buf_copy_len;
00970 u16_t total_copy_len = len;
00971 u16_t copied_total = 0;
00972
00973 LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return 0;);
00974 LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return 0;);
00975
00976 if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) {
00977 return ERR_ARG;
00978 }
00979
00980
00981 for(p = buf; total_copy_len != 0; p = p->next) {
00982 LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL);
00983 buf_copy_len = total_copy_len;
00984 if (buf_copy_len > p->len) {
00985
00986 buf_copy_len = p->len;
00987 }
00988
00989 MEMCPY(p->payload, &((char*)dataptr)[copied_total], buf_copy_len);
00990 total_copy_len -= buf_copy_len;
00991 copied_total += buf_copy_len;
00992 }
00993 LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len);
00994 return ERR_OK;
00995 }
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009 struct pbuf*
01010 pbuf_coalesce(struct pbuf *p, pbuf_layer layer)
01011 {
01012 struct pbuf *q;
01013 err_t err;
01014 if (p->next == NULL) {
01015 return p;
01016 }
01017 q = pbuf_alloc(layer, p->tot_len, PBUF_RAM);
01018 if (q == NULL) {
01019
01020 return p;
01021 }
01022 err = pbuf_copy(q, p);
01023 LWIP_ASSERT("pbuf_copy failed", err == ERR_OK);
01024 pbuf_free(p);
01025 return q;
01026 }
01027
01028 #if LWIP_CHECKSUM_ON_COPY
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041 err_t
01042 pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr,
01043 u16_t len, u16_t *chksum)
01044 {
01045 u32_t acc;
01046 u16_t copy_chksum;
01047 char *dst_ptr;
01048 LWIP_ASSERT("p != NULL", p != NULL);
01049 LWIP_ASSERT("dataptr != NULL", dataptr != NULL);
01050 LWIP_ASSERT("chksum != NULL", chksum != NULL);
01051 LWIP_ASSERT("len != 0", len != 0);
01052
01053 if ((start_offset >= p->len) || (start_offset + len > p->len)) {
01054 return ERR_ARG;
01055 }
01056
01057 dst_ptr = ((char*)p->payload) + start_offset;
01058 copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len);
01059 if ((start_offset & 1) != 0) {
01060 copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum);
01061 }
01062 acc = *chksum;
01063 acc += copy_chksum;
01064 *chksum = FOLD_U32T(acc);
01065 return ERR_OK;
01066 }
01067 #endif
01068
01069
01070
01071
01072
01073
01074
01075
01076 u8_t
01077 pbuf_get_at(struct pbuf* p, u16_t offset)
01078 {
01079 u16_t copy_from = offset;
01080 struct pbuf* q = p;
01081
01082
01083 while ((q != NULL) && (q->len <= copy_from)) {
01084 copy_from -= q->len;
01085 q = q->next;
01086 }
01087
01088 if ((q != NULL) && (q->len > copy_from)) {
01089 return ((u8_t*)q->payload)[copy_from];
01090 }
01091 return 0;
01092 }
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103 u16_t
01104 pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n)
01105 {
01106 u16_t start = offset;
01107 struct pbuf* q = p;
01108
01109
01110 while ((q != NULL) && (q->len <= start)) {
01111 start -= q->len;
01112 q = q->next;
01113 }
01114
01115 if ((q != NULL) && (q->len > start)) {
01116 u16_t i;
01117 for(i = 0; i < n; i++) {
01118 u8_t a = pbuf_get_at(q, start + i);
01119 u8_t b = ((u8_t*)s2)[i];
01120 if (a != b) {
01121 return i+1;
01122 }
01123 }
01124 return 0;
01125 }
01126 return 0xffff;
01127 }
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139 u16_t
01140 pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset)
01141 {
01142 u16_t i;
01143 u16_t max = p->tot_len - mem_len;
01144 if (p->tot_len >= mem_len + start_offset) {
01145 for(i = start_offset; i <= max; ) {
01146 u16_t plus = pbuf_memcmp(p, i, mem, mem_len);
01147 if (plus == 0) {
01148 return i;
01149 } else {
01150 i += plus;
01151 }
01152 }
01153 }
01154 return 0xFFFF;
01155 }
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167 u16_t
01168 pbuf_strstr(struct pbuf* p, const char* substr)
01169 {
01170 size_t substr_len;
01171 if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) {
01172 return 0xFFFF;
01173 }
01174 substr_len = strlen(substr);
01175 if (substr_len >= 0xFFFF) {
01176 return 0xFFFF;
01177 }
01178 return pbuf_memfind(p, substr, (u16_t)substr_len, 0);
01179 }