<commit_before>/* Copyright (c) 2010 Stanford University
 *
 * 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 THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS 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.
 */

#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>

#include "Common.h"
#include "UDPDriver.h"

namespace RAMCloud {

/**
 * Construct a UDPDriver that is unbound to any particular UDP address.
 *
 * For use by clients.
 */
UDPDriver::UDPDriver()
    : socketFd(-1), packetBufsUtilized(0)
{
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd == -1)
        throw UnrecoverableDriverException(errno);
    socketFd = fd;
}

/**
 * Construct a UDPDriver that is bound to a particular UDP address.
 *
 * For use by servers.
 *
 * \param addr
 *      The address to bind to.
 * \param addrlen
 *      The length of addr.
 */
UDPDriver::UDPDriver(const sockaddr *addr, socklen_t addrlen)
    : socketFd(-1), packetBufsUtilized(0)
{
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd == -1) {
        LOG(ERROR, "Couldn't create socket");
        throw UnrecoverableDriverException(errno);
    }

    int r = bind(fd, addr, addrlen);
    if (r == -1) {
        int e = errno;
        close(fd);
        LOG(ERROR, "Couldn't bind socket");
        throw UnrecoverableDriverException(e);
    }

    socketFd = fd;
}

/// Close the UDP socket.
UDPDriver::~UDPDriver()
{
    if (packetBufsUtilized != 0)
        LOG(WARNING, "packetBufsUtilized: %d",
            packetBufsUtilized);
    close(socketFd);
}

/// The maximum number bytes we can stuff in a UDP packet payload.
uint32_t
UDPDriver::getMaxPayloadSize()
{
    return MAX_PAYLOAD_SIZE;
}

// See Driver::release().
void
UDPDriver::release(char *payload, uint32_t len)
{
    packetBufsUtilized--;
    assert(packetBufsUtilized >= 0);
    delete[] payload;
}

// See Driver::sendPacket().
void
UDPDriver::sendPacket(const sockaddr *addr,
                      socklen_t addrlen,
                      void *header,
                      uint32_t headerLen,
                      Buffer::Iterator *payload)
{
    uint32_t totalLength = headerLen +
                           (payload ? payload->getTotalLength() : 0);
    assert(totalLength <= getMaxPayloadSize());<commit_msg>Added remark regarding guarantees on return from UDPDriver::sendPacket.<commit_after>/* Copyright (c) 2010 Stanford University
 *
 * 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 THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS 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.
 */

#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>

#include "Common.h"
#include "UDPDriver.h"

namespace RAMCloud {

/**
 * Construct a UDPDriver that is unbound to any particular UDP address.
 *
 * For use by clients.
 */
UDPDriver::UDPDriver()
    : socketFd(-1), packetBufsUtilized(0)
{
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd == -1)
        throw UnrecoverableDriverException(errno);
    socketFd = fd;
}

/**
 * Construct a UDPDriver that is bound to a particular UDP address.
 *
 * For use by servers.
 *
 * \param addr
 *      The address to bind to.
 * \param addrlen
 *      The length of addr.
 */
UDPDriver::UDPDriver(const sockaddr *addr, socklen_t addrlen)
    : socketFd(-1), packetBufsUtilized(0)
{
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd == -1) {
        LOG(ERROR, "Couldn't create socket");
        throw UnrecoverableDriverException(errno);
    }

    int r = bind(fd, addr, addrlen);
    if (r == -1) {
        int e = errno;
        close(fd);
        LOG(ERROR, "Couldn't bind socket");
        throw UnrecoverableDriverException(e);
    }

    socketFd = fd;
}

/// Close the UDP socket.
UDPDriver::~UDPDriver()
{
    if (packetBufsUtilized != 0)
        LOG(WARNING, "packetBufsUtilized: %d",
            packetBufsUtilized);
    close(socketFd);
}

/// The maximum number bytes we can stuff in a UDP packet payload.
uint32_t
UDPDriver::getMaxPayloadSize()
{
    return MAX_PAYLOAD_SIZE;
}

// See Driver::release().
void
UDPDriver::release(char *payload, uint32_t len)
{
    packetBufsUtilized--;
    assert(packetBufsUtilized >= 0);
    delete[] payload;
}

// See Driver::sendPacket().
// UDPDriver::sendPacket currently guarantees that the caller is free to
// discard or reuse the memory associated with payload and header once
// on return from this method.
void
UDPDriver::sendPacket(const sockaddr *addr,
                      socklen_t addrlen,
                      void *header,
                      uint32_t headerLen,
                      Buffer::Iterator *payload)
{
    uint32_t totalLength = headerLen +
                           (payload ? payload->getTotalLength() : 0);
    assert(totalLength <= getMaxPayloadSize());
{'fraction_non_alphanumeric': 0.10052462345574548, 'fraction_numerical': 0.008123201895413776, 'mean_word_length': 2.9878542510121457, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6092302', 'n_tokens_mistral': 1852, 'n_tokens_neox': 1751, 'n_words': 611}