Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
sockbuf.c
00001 /* 00002 * Copyright (c) 2016-2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "nsconfig.h" 00019 #include "ns_trace.h" 00020 #include <string.h> 00021 #include "Core/include/sockbuf.h" 00022 00023 #define TRACE_GROUP "sbuf" 00024 00025 void sockbuf_init(sockbuf_t *sb) 00026 { 00027 memset(sb, 0, sizeof *sb); 00028 ns_list_init(&sb->bufs); 00029 } 00030 00031 /* Add buf to counters */ 00032 void sockbuf_alloc(sockbuf_t *sb, const buffer_t *buf) 00033 { 00034 sb->buf_overhead_bytes += sizeof *buf + buf->size ; 00035 sb->data_bytes += buffer_data_length(buf); 00036 } 00037 00038 /* Remove buf from counters */ 00039 void sockbuf_free(sockbuf_t *sb, const buffer_t *buf) 00040 { 00041 sb->buf_overhead_bytes -= sizeof *buf + buf->size ; 00042 sb->data_bytes -= buffer_data_length(buf); 00043 } 00044 00045 void sockbuf_append(sockbuf_t *sb, buffer_t *buf) 00046 { 00047 // Nasty little one - if the buffer references the socket (as is likely on 00048 // entry), it might stop a socket with queued data ever being freed. Avoid 00049 // this trap. Should be no need for socket pointer if on a queue. 00050 buffer_socket_set(buf, NULL); 00051 sockbuf_alloc(sb, buf); 00052 ns_list_add_to_end(&sb->bufs, buf); 00053 } 00054 00055 /* Try to avoid totally wasting space for streams. Overhead of buffer_t 00056 * still rather large - we don't actually want any metadata at all... 00057 */ 00058 void sockbuf_append_and_compress(sockbuf_t *sb, buffer_t *buf) 00059 { 00060 if (buffer_data_length(buf) == 0) { 00061 buffer_free(buf); 00062 return; 00063 } 00064 00065 buffer_t *last = ns_list_get_last(&sb->bufs); 00066 if (last) { 00067 uint16_t new_len = buffer_data_length(buf); 00068 uint32_t total = buffer_data_length(last) + new_len; 00069 if (total <= last->size) { 00070 // Pack down destination buffer if necessary 00071 if (buffer_data_free_length(last) < new_len) { 00072 uint16_t last_len = buffer_data_length(last); 00073 memmove(last->buf , buffer_data_pointer(last), last_len); 00074 last->buf_ptr = 0; 00075 last->buf_end = last_len; 00076 } 00077 // Add in the data, and add to data count 00078 buffer_data_add(last, buffer_data_pointer(buf), new_len); 00079 sb->data_bytes += new_len; 00080 // Free source buffer 00081 buffer_free(buf); 00082 return; 00083 } 00084 } 00085 sockbuf_append(sb, buf); 00086 } 00087 00088 /* Drop len bytes of data from the front of the queue */ 00089 void sockbuf_drop(sockbuf_t *sb, uint32_t len) 00090 { 00091 while (len) { 00092 buffer_t *buf = ns_list_get_first(&sb->bufs); 00093 if (!buf) { 00094 tr_err("sockbuf_drop"); 00095 return; 00096 } 00097 if ((uint32_t) buffer_data_length(buf) > len) { 00098 buffer_data_strip_header(buf, len); 00099 sb->data_bytes -= len; 00100 break; 00101 } 00102 len -= buffer_data_length(buf); 00103 sockbuf_free(sb, buf); 00104 ns_list_remove(&sb->bufs, buf); 00105 buffer_free(buf); 00106 } 00107 } 00108 00109 /* Drop first buffer from the front of the queue */ 00110 void sockbuf_drop_first(sockbuf_t *sb) 00111 { 00112 buffer_t *buf = ns_list_get_first(&sb->bufs); 00113 if (buf) { 00114 sockbuf_free(sb, buf); 00115 ns_list_remove(&sb->bufs, buf); 00116 buffer_free(buf); 00117 } 00118 } 00119 00120 void sockbuf_flush(sockbuf_t *sb) 00121 { 00122 buffer_free_list(&sb->bufs); 00123 sb->buf_overhead_bytes = sb->data_bytes = 0; 00124 } 00125 00126 bool sockbuf_reserve(sockbuf_t *sb, uint32_t space) 00127 { 00128 /* Arbitrary limit for now, just avoids overflow nonsense */ 00129 if (space >= 0x10000) { 00130 return false; 00131 } 00132 sb->data_byte_limit = space; 00133 sb->buf_overhead_byte_limit = space * 2; // BSD 4.4-style. Does it work for our buffers though? 00134 if (sb->low_water_mark < 1) { 00135 sb->low_water_mark = 1; 00136 } 00137 if (sb->low_water_mark > sb->data_byte_limit) { 00138 sb->low_water_mark = sb->data_byte_limit; 00139 } 00140 00141 return true; 00142 } 00143 00144 /* Note that space could be negative if we've overfilled - everything handled signed to catch this */ 00145 int32_t sockbuf_space(const sockbuf_t *sb) 00146 { 00147 int32_t data_space = (int32_t) sb->data_byte_limit - (int32_t) sb->data_bytes; 00148 int32_t buf_space = (int32_t) sb->buf_overhead_byte_limit - (int32_t) sb->buf_overhead_bytes; 00149 return data_space < buf_space ? data_space : buf_space; 00150 } 00151 00152 void sockbuf_check(sockbuf_t *sb) 00153 { 00154 uint32_t data = 0; 00155 uint32_t overhead = 0; 00156 ns_list_foreach(buffer_t, buf, &sb->bufs) { 00157 data += buffer_data_length(buf); 00158 overhead += sizeof *buf + buf->size ; 00159 } 00160 00161 if (sb->data_bytes != data || sb->buf_overhead_bytes != overhead) { 00162 tr_err("data=%"PRIu32" actual=%"PRIu32", overhead=%"PRIu32" actual=%"PRIu32, 00163 sb->data_bytes, data, sb->buf_overhead_bytes, overhead); 00164 sb->data_bytes = data; 00165 sb->buf_overhead_bytes = overhead; 00166 } 00167 }
Generated on Tue Jul 12 2022 12:45:46 by
