sockcreator.h 5.6 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
#ifndef SOCKCREATOR_H
#define SOCKCREATOR_H 1
23

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
};

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) {}
};


76 77 78
// 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);
Stephen Morris's avatar
Stephen Morris committed
79

80 81 82 83 84 85 86 87
/// \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.
88
/// \param close_fun The function used to close a socket if there's an error
89
///     after the creation.
90 91 92 93 94
///
/// \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()).
95
int
96 97
getSock(const int type, struct sockaddr* bind_addr, const socklen_t addr_len,
        const close_t close_fun);
98

99
// Define some types for functions used to perform socket-related operations.
Francis Dupont's avatar
Francis Dupont committed
100
// These are typedef'ed so that alternatives can be passed through to the
101 102
// main functions for testing purposes.

103 104
// Type of the function to get a socket and to pass it as parameter.
// Arguments are those described above for getSock().
105 106
typedef int (*get_sock_t)(const int, struct sockaddr *, const socklen_t,
                          const close_t close_fun);
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121

// 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);


/// \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.
///
122
/// \param input_fd File number of the stream from which the input commands
123
///        are read.
124 125 126
/// \param output_fd File number of the stream to which the response is
///        written.  The socket is sent as part of a control message associated
///        with that stream.
127 128 129 130 131 132 133
/// \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
Francis Dupont's avatar
Francis Dupont committed
134
///        unistd.h. It can be overridden in tests.
135 136 137
///
/// \exception isc::socket_creator::ReadError Error reading from input
/// \exception isc::socket_creator::WriteError Error writing to output
Francis Dupont's avatar
Francis Dupont committed
138
/// \exception isc::socket_creator::ProtocolError Unrecognized command received
139
/// \exception isc::socket_creator::InternalError Other error
Stephen Morris's avatar
Stephen Morris committed
140
void
141 142
run(const int input_fd, const int output_fd, get_sock_t get_sock_fun,
    send_fd_t send_fd_fun, close_t close_fun);
143

144 145
}   // namespace socket_creator
}   // NAMESPACE ISC
146

147
#endif // SOCKCREATOR_H