sockcreator.h 5.44 KB
Newer Older
1
// Copyright (C) 2011-2012  Internet Systems Consortium, Inc. ("ISC")
2 3 4 5 6 7 8 9 10 11 12 13 14
//
// Permission to use, copy, modify, and/or 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.

15 16 17 18 19
/// \file sockcreator.h
/// \short Socket creator functionality.
///
/// This module holds the functionality of the socket creator. It is a separate
/// module from main to make testing easier.
20 21 22 23

#ifndef __SOCKCREATOR_H
#define __SOCKCREATOR_H 1

24
#include <util/io/fd_share.h>
Stephen Morris's avatar
Stephen Morris committed
25
#include <exceptions/exceptions.h>
26

27 28
#include <sys/types.h>
#include <sys/socket.h>
29
#include <unistd.h>
30 31 32 33

namespace isc {
namespace socket_creator {

Stephen Morris's avatar
Stephen Morris committed
34
// Exception classes - the base class exception SocketCreatorError is caught
35 36 37
// by main() and holds an exit code returned to the environment.  The code
// depends on the exact exception raised.
class SocketCreatorError : public isc::Exception {
Stephen Morris's avatar
Stephen Morris committed
38 39 40 41 42 43 44 45 46 47
public:
    SocketCreatorError(const char* file, size_t line, const char* what,
                       int exit_code) :
        isc::Exception(file, line, what), exit_code_(exit_code) {}

    int getExitCode() const {
        return (exit_code_);
    }

private:
48
    const int exit_code_;   // Code returned to exit()
Stephen Morris's avatar
Stephen Morris committed
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
};

class ReadError : public SocketCreatorError {
public:
    ReadError(const char* file, size_t line, const char* what) :
        SocketCreatorError(file, line, what, 1) {}
};

class WriteError : public SocketCreatorError {
public:
    WriteError(const char* file, size_t line, const char* what) :
        SocketCreatorError(file, line, what, 2) {}
};

class ProtocolError : public SocketCreatorError {
public:
    ProtocolError(const char* file, size_t line, const char* what) :
        SocketCreatorError(file, line, what, 3) {}
};

class InternalError : public SocketCreatorError {
public:
    InternalError(const char* file, size_t line, const char* what) :
        SocketCreatorError(file, line, what, 4) {}
};



77 78 79 80 81 82 83 84 85 86 87 88 89
/// \short Create a socket and bind it.
///
/// This is just a bundle of socket() and bind() calls. The sa_family of
/// bind_addr is used to determine the domain of the socket.
///
/// \param type The type of socket to create (SOCK_STREAM, SOCK_DGRAM, etc).
/// \param bind_addr The address to bind.
/// \param addr_len The actual length of bind_addr.
///
/// \return The file descriptor of the newly created socket, if everything
///         goes well. A negative number is returned if an error occurs -
///         -1 if the socket() call fails or -2 if bind() fails. In case of
///         error, errno is set (or left intact from socket() or bind()).
90
int
91
get_sock(const int type, struct sockaddr *bind_addr, const socklen_t addr_len);
92

93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
// Define some types for functions used to perform socket-related operations.
// These are typedefed so that alternatives can be passed through to the
// main functions for testing purposes.

// Type of the get_sock function, to pass it as parameter.  Arguments are
// those described above for get_sock().
typedef int (*get_sock_t)(const int, struct sockaddr *, const socklen_t);

// Type of the send_fd() function, so it can be passed as a parameter.
// Arguments are the same as those of the send_fd() function.
typedef int (*send_fd_t)(const int, const int);

// Type of the close() function, so it can be passed as a parameter.
// Argument is the same as that for close(2).
typedef int (*close_t)(int);


/// \brief Infinite loop parsing commands and returning the sockets.
///
/// This reads commands and socket descriptions from the input_fd file
/// descriptor, creates sockets and writes the results (socket or error) to
/// output_fd.
///
/// It terminates either if a command asks it to or when unrecoverable error
/// happens.
///
/// \param input_fd File descriptor of the stream from which the input commands
///        are read.
/// \param output_fd File descriptor of the stream to which the output
///        (message/socket or error message) is written.
/// \param get_sock_fun The function that is used to create the sockets.
///        This should be left on the default value, the parameter is here
///        for testing purposes.
/// \param send_fd_fun The function that is used to send the socket over
///        a file descriptor. This should be left on the default value, it is
///        here for testing purposes.
/// \param close_fun The close function used to close sockets, coming from
///        unistd.h. It can be overriden in tests.
///
/// \exception isc::socket_creator::ReadError Error reading from input
/// \exception isc::socket_creator::WriteError Error writing to output
/// \exception isc::socket_creator::ProtocolError Unrecognised command received
/// \exception isc::socket_creator::InternalError Other error
Stephen Morris's avatar
Stephen Morris committed
136
void
137 138
run(const int input_fd, const int output_fd,
    const get_sock_t get_sock_fun = get_sock,
139
    const send_fd_t send_fd_fun = isc::util::io::send_fd,
140
    const close_t close_fun = close);
141

142 143
}   // namespace socket_creator
}   // NAMESPACE ISC
144 145

#endif // __SOCKCREATOR_H