📄 buffer.c
字号:
/* buffer.c Buffer access functions for the object management protocol... *//* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 1999-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Internet Systems Consortium, Inc. * 950 Charter Street * Redwood City, CA 94063 * <info@isc.org> * http://www.isc.org/ * * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. * To learn more about Internet Systems Consortium, see * ``http://www.isc.org/''. To learn more about Vixie Enterprises, * see ``http://www.vix.com''. To learn more about Nominum, Inc., see * ``http://www.nominum.com''. */#include <omapip/omapip_p.h>#if defined (TRACING)static void trace_connection_input_input (trace_type_t *, unsigned, char *);static void trace_connection_input_stop (trace_type_t *);static void trace_connection_output_input (trace_type_t *, unsigned, char *);static void trace_connection_output_stop (trace_type_t *);static trace_type_t *trace_connection_input;static trace_type_t *trace_connection_output;static isc_result_t omapi_connection_reader_trace (omapi_object_t *, unsigned, char *, unsigned *);extern omapi_array_t *omapi_connections;void omapi_buffer_trace_setup (){ trace_connection_input = trace_type_register ("connection-input", (void *)0, trace_connection_input_input, trace_connection_input_stop, MDL); trace_connection_output = trace_type_register ("connection-output", (void *)0, trace_connection_output_input, trace_connection_output_stop, MDL);}static void trace_connection_input_input (trace_type_t *ttype, unsigned length, char *buf){ unsigned left, taken, cc = 0; char *s; int32_t connect_index; isc_result_t status; omapi_connection_object_t *c = (omapi_connection_object_t *)0; memcpy (&connect_index, buf, sizeof connect_index); connect_index = ntohl (connect_index); omapi_array_foreach_begin (omapi_connections, omapi_connection_object_t, lp) { if (lp -> index == ntohl (connect_index)) { omapi_connection_reference (&c, lp, MDL); omapi_connection_dereference (&lp, MDL); break; } } omapi_array_foreach_end (omapi_connections, omapi_connection_object_t, lp); if (!c) { log_error ("trace connection input: no connection index %ld", (long int)connect_index); return; } s = buf + sizeof connect_index; left = length - sizeof connect_index; while (left) { taken = 0; status = omapi_connection_reader_trace ((omapi_object_t *)c, left, s, &taken); if (status != ISC_R_SUCCESS) { log_error ("trace connection input: %s", isc_result_totext (status)); break; } if (!taken) { if (cc > 0) { log_error ("trace connection_input: %s", "input is not being consumed."); break; } cc++; } else { cc = 0; left -= taken; } } omapi_connection_dereference (&c, MDL);}static void trace_connection_input_stop (trace_type_t *ttype) { }static void trace_connection_output_input (trace_type_t *ttype, unsigned length, char *buf){ /* We *could* check to see if the output is correct, but for now we aren't going to do that. */}static void trace_connection_output_stop (trace_type_t *ttype) { }#endif/* Make sure that at least len bytes are in the input buffer, and if not, read enough bytes to make up the difference. */isc_result_t omapi_connection_reader (omapi_object_t *h){#if defined (TRACING) return omapi_connection_reader_trace (h, 0, (char *)0, (unsigned *)0);}static isc_result_t omapi_connection_reader_trace (omapi_object_t *h, unsigned stuff_len, char *stuff_buf, unsigned *stuff_taken){#endif omapi_buffer_t *buffer; isc_result_t status; unsigned read_len; int read_status; omapi_connection_object_t *c; unsigned bytes_to_read; if (!h || h -> type != omapi_type_connection) return ISC_R_INVALIDARG; c = (omapi_connection_object_t *)h; /* Make sure c -> bytes_needed is valid. */ if (c -> bytes_needed < 0) return ISC_R_INVALIDARG; /* See if there are enough bytes. */ if (c -> in_bytes >= OMAPI_BUF_SIZE - 1 && c -> in_bytes > c -> bytes_needed) return ISC_R_SUCCESS; if (c -> inbufs) { for (buffer = c -> inbufs; buffer -> next; buffer = buffer -> next) ; if (!BUFFER_BYTES_FREE (buffer)) { status = omapi_buffer_new (&buffer -> next, MDL); if (status != ISC_R_SUCCESS) return status; buffer = buffer -> next; } } else { status = omapi_buffer_new (&c -> inbufs, MDL); if (status != ISC_R_SUCCESS) return status; buffer = c -> inbufs; } bytes_to_read = BUFFER_BYTES_FREE (buffer); while (bytes_to_read) { if (buffer -> tail > buffer -> head) read_len = sizeof (buffer -> buf) - buffer -> tail; else read_len = buffer -> head - buffer -> tail;#if defined (TRACING) if (trace_playback()) { if (stuff_len) { if (read_len > stuff_len) read_len = stuff_len; if (stuff_taken) *stuff_taken += read_len; memcpy (&buffer -> buf [buffer -> tail], stuff_buf, read_len); stuff_len -= read_len; stuff_buf += read_len; read_status = read_len; } else { break; } } else#endif { read_status = read (c -> socket, &buffer -> buf [buffer -> tail], read_len); } if (read_status < 0) { if (errno == EWOULDBLOCK) break; else if (errno == EIO) return ISC_R_IOERROR; else if (errno == EINVAL) return ISC_R_INVALIDARG; else if (errno == ECONNRESET) { omapi_disconnect (h, 1); return ISC_R_SHUTTINGDOWN; } else return ISC_R_UNEXPECTED; } /* If we got a zero-length read, as opposed to EWOULDBLOCK, the remote end closed the connection. */ if (read_status == 0) { omapi_disconnect (h, 0); return ISC_R_SHUTTINGDOWN; }#if defined (TRACING) if (trace_record ()) { trace_iov_t iov [2]; int32_t connect_index; connect_index = htonl (c -> index); iov [0].buf = (char *)&connect_index; iov [0].len = sizeof connect_index; iov [1].buf = &buffer -> buf [buffer -> tail]; iov [1].len = read_status; status = (trace_write_packet_iov (trace_connection_input, 2, iov, MDL)); if (status != ISC_R_SUCCESS) { trace_stop (); log_error ("trace connection input: %s", isc_result_totext (status)); } }#endif buffer -> tail += read_status; c -> in_bytes += read_status; if (buffer -> tail == sizeof buffer -> buf) buffer -> tail = 0; if (read_status < read_len) break; bytes_to_read -= read_status; } if (c -> bytes_needed <= c -> in_bytes) { omapi_signal (h, "ready", c); } return ISC_R_SUCCESS;}/* Put some bytes into the output buffer for a connection. */isc_result_t omapi_connection_copyin (omapi_object_t *h, const unsigned char *bufp, unsigned len){ omapi_buffer_t *buffer; isc_result_t status; int bytes_copied = 0; unsigned copy_len; int sig_flags = SIG_MODE_UPDATE; omapi_connection_object_t *c; /* Make sure len is valid. */ if (len < 0) return ISC_R_INVALIDARG; if (!h || h -> type != omapi_type_connection) return ISC_R_INVALIDARG; c = (omapi_connection_object_t *)h; /* If the connection is closed, return an error if the caller tries to copy in. */ if (c -> state == omapi_connection_disconnecting || c -> state == omapi_connection_closed) return ISC_R_NOTCONNECTED; if (c -> outbufs) { for (buffer = c -> outbufs; buffer -> next; buffer = buffer -> next) ; } else { status = omapi_buffer_new (&c -> outbufs, MDL); if (status != ISC_R_SUCCESS) return status; buffer = c -> outbufs; } while (bytes_copied < len) { /* If there is no space available in this buffer, allocate a new one. */ if (!BUFFER_BYTES_FREE (buffer)) { status = (omapi_buffer_new (&buffer -> next, MDL)); if (status != ISC_R_SUCCESS) return status; buffer = buffer -> next; } if (buffer -> tail > buffer -> head) copy_len = sizeof (buffer -> buf) - buffer -> tail; else copy_len = buffer -> head - buffer -> tail; if (copy_len > (len - bytes_copied)) copy_len = len - bytes_copied; if (c -> out_key) { if (!c -> out_context) sig_flags |= SIG_MODE_INIT; status = omapi_connection_sign_data (sig_flags, c -> out_key, &c -> out_context, &bufp [bytes_copied], copy_len, (omapi_typed_data_t **)0); if (status != ISC_R_SUCCESS) return status; } memcpy (&buffer -> buf [buffer -> tail], &bufp [bytes_copied], copy_len); buffer -> tail += copy_len; c -> out_bytes += copy_len; bytes_copied += copy_len; if (buffer -> tail == sizeof buffer -> buf) buffer -> tail = 0; } return ISC_R_SUCCESS;}/* Copy some bytes from the input buffer, and advance the input buffer pointer beyond the bytes copied out. */isc_result_t omapi_connection_copyout (unsigned char *buf, omapi_object_t *h, unsigned size){ unsigned bytes_remaining; unsigned bytes_this_copy;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -