/* * Copyright (c) Likewise Software. All rights Reserved. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the license, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy * of the GNU Lesser General Public License along with this program. If * not, see . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ /* * Module Name: * * connection-buffer.c * * Abstract: * * Connection API * Packet buffer logic * * Authors: Brian Koropoff (bkoropoff@likewisesoftware.com) * */ #include "connection-private.h" #include "util-private.h" LWMsgStatus lwmsg_connection_buffer_construct(ConnectionBuffer* buffer) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; memset(buffer, 0, sizeof(*buffer)); lwmsg_ring_init(&buffer->fragments); buffer->fd_capacity = MAX_FD_PAYLOAD; buffer->fd_length = 0; buffer->fd = malloc(sizeof(int) * buffer->fd_capacity); if (!buffer->fd) { BAIL_ON_ERROR(status = LWMSG_STATUS_MEMORY); } done: return status; error: if (buffer->fd) { free(buffer->fd); } goto done; } void lwmsg_connection_buffer_empty(ConnectionBuffer* buffer) { LWMsgRing* ring, *next; if (buffer->fd) { memset(buffer->fd, 0xFF, sizeof(int) * buffer->fd_capacity); } for (ring = buffer->fragments.next; ring != &buffer->fragments; ring = next) { next = ring->next; lwmsg_ring_remove(ring); free(LWMSG_OBJECT_FROM_MEMBER(ring, ConnectionFragment, ring)); } if (buffer->current) { free(buffer->current); buffer->current = NULL; } } void lwmsg_connection_buffer_destruct(ConnectionBuffer* buffer) { lwmsg_connection_buffer_empty(buffer); if (buffer->fd) { free(buffer->fd); } memset(buffer, 0, sizeof(*buffer)); } LWMsgStatus lwmsg_connection_buffer_create_fragment( ConnectionBuffer* buffer, size_t length, ConnectionFragment** fragment ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; ConnectionFragment* frag = NULL; frag = calloc(1, offsetof(ConnectionFragment, data) + length); if (!frag) { BAIL_ON_ERROR(status = LWMSG_STATUS_MEMORY); } lwmsg_ring_init(&frag->ring); frag->cursor = frag->data; *fragment = frag; error: return status; } void lwmsg_connection_buffer_queue_fragment( ConnectionBuffer* buffer, ConnectionFragment* fragment ) { lwmsg_ring_insert_before(&buffer->fragments, &fragment->ring); } ConnectionFragment* lwmsg_connection_buffer_dequeue_fragment( ConnectionBuffer* buffer ) { LWMsgRing* ring = NULL; if (buffer->fragments.next == &buffer->fragments) { return NULL; } else { ring = buffer->fragments.next; lwmsg_ring_remove(ring); return LWMSG_OBJECT_FROM_MEMBER(ring, ConnectionFragment, ring); } } ConnectionFragment* lwmsg_connection_buffer_get_first_fragment( ConnectionBuffer* buffer ) { if (buffer->fragments.next != &buffer->fragments) { return LWMSG_OBJECT_FROM_MEMBER(buffer->fragments.next, ConnectionFragment, ring); } else { return NULL; } } ConnectionFragment* lwmsg_connection_buffer_get_last_fragment( ConnectionBuffer* buffer ) { if (buffer->fragments.prev != &buffer->fragments) { return LWMSG_OBJECT_FROM_MEMBER(buffer->fragments.prev, ConnectionFragment, ring); } else { return NULL; } } void lwmsg_connection_buffer_free_fragment( ConnectionBuffer* buffer, ConnectionFragment* fragment ) { free(fragment); } LWMsgStatus lwmsg_connection_buffer_ensure_fd_capacity(ConnectionBuffer* buffer, size_t needed) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; if (buffer->fd_capacity - buffer->fd_length < needed) { BAIL_ON_ERROR(status = LWMSG_STATUS_MALFORMED); } error: return status; }