/* Copyright (C) 2009 Jonathon Jongsma
*
* 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 library. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
_DEFS(giomm,gio)
_PINCLUDE(glibmm/private/object_p.h)
namespace Gio
{
class SocketSource;
/** @defgroup NetworkIO Portable Network I/O Functionality
*/
/** Low-level socket object
*
* A Socket is a low-level networking primitive. It is a more or less direct
* mapping of the BSD socket API in a portable GObject based API. It supports
* both the UNIX socket implementations and winsock2 on Windows.
*
* Socket is the platform independent base upon which the higher level network
* primitives are based. Applications are not typically meant to use it
* directly, but rather through classes like SocketClient, SocketService and
* SocketConnection. However there may be cases where direct use of Socket is
* useful.
*
* Socket implements the Initable interface, and since initialization can fail,
* the constructor may throw an exception.
*
* Sockets operate in two general modes, blocking or non-blocking. When in
* blocking mode all operations block until the requested operation is finished
* or there is an error. In non-blocking mode all calls that would block return
* immediately with a Gio::Error::WOULD_BLOCK error. To know when a call would
* successfully run you can call condition_check(), or condition_wait(). You can
* also use create_source() and attach it to a Glib::MainContext to get
* callbacks when I/O is possible. Note that all sockets are always set to non
* blocking mode in the system, and blocking mode is emulated in Socket.
*
* When working in non-blocking mode applications should always be able to
* handle getting a Gio::Error::WOULD_BLOCK error even when some other function
* said that I/O was possible. This can easily happen in case of a race
* condition in the application, but it can also happen for other reasons. For
* instance, on Windows a socket is always seen as writable until a write
* returns Gio::Error::WOULD_BLOCK.
*
* Sockets can be either connection oriented or datagram based. For connection
* oriented types you must first establish a connection by either connecting to
* an address or accepting a connection from another address. For connectionless
* socket types the target/source address is specified or received in each I/O
* operation.
*
* All socket file descriptors are set to be close-on-exec.
*
* Note that creating a Socket causes the signal SIGPIPE to be ignored for the
* remainder of the program. If you are writing a command-line utility that uses
* Socket, you may need to take into account the fact that your program will not
* automatically be killed if it tries to write to stdout after it has been
* closed.
*
* @newin{2,24}
* @ingroup NetworkIO
*/
class GIOMM_API Socket : public Glib::Object, public Initable
{
_CLASS_GOBJECT(Socket, GSocket, G_SOCKET, Glib::Object, GObject, , , GIOMM_API)
_IMPLEMENTS_INTERFACE(Initable)
public:
_WRAP_ENUM(Type, GSocketType, decl_prefix GIOMM_API)
_WRAP_ENUM(Protocol, GSocketProtocol, decl_prefix GIOMM_API)
_WRAP_ENUM(MsgFlags, GSocketMsgFlags, decl_prefix GIOMM_API)
protected:
Socket(SocketFamily family, Type type, Protocol protocol,
const Glib::RefPtr& cancellable);
Socket(int fd, const Glib::RefPtr& cancellable);
public:
_WRAP_METHOD_DOCS_ONLY(g_socket_new)
/** @param cancellable A Cancellable object which can be used to cancel the operation.
* @throw Glib::Error
*/
static Glib::RefPtr
create(SocketFamily family, Type type, Protocol protocol,
const Glib::RefPtr& cancellable = {});
// gmmproc thinks that this function should be wrapped in this class because
// its only parameter is a GSocket. In fact, it is wrapped in the
// SocketConnection class.
_IGNORE(g_socket_connection_factory_create_connection)
_WRAP_METHOD_DOCS_ONLY(g_socket_new_from_fd)
/** @param cancellable A Cancellable object which can be used to cancel the operation.
* @throw Glib::Error
*/
static Glib::RefPtr create_from_fd(int fd, const Glib::RefPtr&
cancellable = {});
/** When a socket is created it is attached to an address family, but it doesn't
* have an address in this family. Socket::bind() assigns the address (sometimes
* called name) of the socket.
*
* It is generally required to bind to a local address before you can receive
* connections. (See Socket::listen() and Socket::accept()). In certain situations,
* you may also want to bind a socket that will be used to initiate connections,
* though this is not normally required.
*
* If socket is a TCP socket, then @a allow_reuse controls the setting of the SO_REUSEADDR
* socket option; normally it should be true for server sockets (sockets that you
* will eventually call Socket::accept() on), and false for client sockets.
* (Failing to set this flag on a server socket may cause Socket::bind() to
* throw Gio::Error with ADDRESS_IN_USE if the server program
* is stopped and then immediately restarted.)
*
* If socket is a UDP socket, then @a allow_reuse determines whether or not
* other UDP sockets can be bound to the same address at the same time. In particular,
* you can have several UDP sockets bound to the same address, and they will all
* receive all of the multicast and broadcast packets sent to that address.
* (The behavior of unicast UDP packets to an address with multiple listeners is not defined.)
*
* @param address a SocketAddress specifying the local address.
* @param allow_reuse whether to allow reusing this address
*
* @throw Gio::Error
*/
_WRAP_METHOD(void bind(const Glib::RefPtr& address, bool allow_reuse), g_socket_bind, errthrow)
/** Marks the socket as a server socket - a socket that is used to accept
* incoming requests using Socket::accept().
*
* Before calling this the socket must be bound to a local address using Socket::bind().
*
* To set the maximum amount of outstanding clients, use Socket::set_listen_backlog().
*
* @throw Gio::Error
*/
_WRAP_METHOD(void listen(), g_socket_listen, errthrow)
/** Accept incoming connections on a connection-based socket. This removes the
* first outstanding connection request from the listening socket and creates
* a GSocket object for it.
*
* The socket must be bound to a local address with g_socket_bind() and must
* be listening for incoming connections (Socket::listen()).
*
* If there are no outstanding connections then the operation will block or
* throw Gio::Error with ERROR_WOULD_BLOCK if non-blocking
* I/O is enabled. To be notified of an incoming connection, wait for the
* Glib::IO_IN condition.
*
* @param cancellable A Cancellable object which can be used to cancel the operation.
*
* @return a Gio::Socket
*
* @throw Gio::Error
*/
_WRAP_METHOD(Glib::RefPtr accept(const Glib::RefPtr& cancellable{?}), g_socket_accept, errthrow)
/** Connect the socket to the specified remote address.
*
* For connection oriented socket this generally means we attempt to make a
* connection to the address . For a connection-less socket it sets the default
* address for Socket::send() and discards all incoming datagrams from other sources.
*
* Generally connection oriented sockets can only connect once, but
* connection-less sockets can connect multiple times to change the default address.
*
* If the connect call needs to do network I/O it will block, unless non-blocking
* I/O is enabled. Then Gio::Error with ERROR_PENDING is thrown
* and the user can be notified of the connection finishing by waiting for the
* Glib::IO_OUT condition. The result of the connection must then be checked
* with Socket::check_connect_result().
*
* @param address a SocketAddress specifying the remote address.
* @param cancellable A Cancellable object which can be used to cancel the operation.
*
* @throw Gio::Error
*/
_WRAP_METHOD(void connect(const Glib::RefPtr& address, const Glib::RefPtr& cancellable{?}), g_socket_connect, errthrow)
// FIXME: it doesn't really seem like this is a proper use of exceptions...
_WRAP_METHOD(void check_connect_result(), g_socket_check_connect_result, errthrow)
// TODO: std::string overload?
_WRAP_METHOD(gssize receive(char* buffer, gsize size, const Glib::RefPtr& cancellable{?}), g_socket_receive, errthrow)
_IGNORE(g_socket_receive_from)
gssize receive_from(Glib::RefPtr& address, char* buffer, gsize size, const Glib::RefPtr& cancellable);
gssize receive_from(Glib::RefPtr& address, char* buffer, gsize size);
// TODO: wrap g_socket_receive_message -- figure out this GInputVector thing
// TODO: std::string overload?
_WRAP_METHOD(gssize send(const gchar* buffer, gsize size, const Glib::RefPtr& cancellable{?}), g_socket_send, errthrow)
// TODO: std::string overload?
_WRAP_METHOD(gssize send_to(const Glib::RefPtr& address, const char* buffer, gsize size, const Glib::RefPtr& cancellable{?}), g_socket_send_to, errthrow)
// TODO: wrap g_socket_send_message -- figure out this GOutputVector thing
_WRAP_METHOD(void close(), g_socket_close, errthrow)
_WRAP_METHOD(bool is_closed(), g_socket_is_closed)
/** Creates a SocketSource that can be attached to a Glib::MainContext to monitor
* for the availability of the specified @a condition on the socket.
*
* Create a slot from a function to be called when @a condition is met
* for the socket with sigc::ptr_fun() or sigc::mem_fun() and pass
* it into the connect() function of the returned SocketSource object.
* Polling of the socket will start when you attach a Glib::MainContext
* object to the returned SocketSource object using its attach() function.
*
* It is meaningless to specify Glib::IO_ERR or Glib::IO_HUP in @a condition;
* these conditions will always be reported output if they are true.
*
* @a cancellable can be used to cancel the source, which will
* cause the source to trigger, reporting the current condition (which
* is likely 0 unless cancellation happened at the same time as a
* condition change). You can check for this in the callback using
* Cancellable::is_cancelled().
*
* If the socket has a timeout set, and it is reached before @a condition
* occurs, the source will then trigger anyway, reporting Glib::IO_IN or
* Glib::IO_OUT depending on @a condition. However, the socket will have been
* marked as having had a timeout, and so the next Socket I/O method
* you call will then fail with a Gio::IO_ERROR_TIMED_OUT.
*
* Gio::signal_socket().connect() is a simpler interface to the same functionality.
*
* @newin{2,42}
*
* @param condition A Glib::IOCondition mask to monitor.
* @param cancellable A Cancellable. The default value means the source is not cancellable.
* @return A newly allocated SocketSource.
*/
Glib::RefPtr create_source(Glib::IOCondition condition, const Glib::RefPtr& cancellable = {});
_IGNORE(g_socket_create_source)
_WRAP_METHOD(void shutdown(bool shutdown_read, bool shutdown_write), g_socket_shutdown, errthrow)
_WRAP_METHOD(bool is_connected(), g_socket_is_connected)
_WRAP_METHOD(gssize get_available_bytes() const, g_socket_get_available_bytes)
_WRAP_METHOD(Glib::IOCondition condition_check(Glib::IOCondition condition), g_socket_condition_check)
_WRAP_METHOD(void condition_wait(Glib::IOCondition condition, const Glib::RefPtr& cancellable{?}), g_socket_condition_wait, errthrow)
_WRAP_METHOD(void condition_timed_wait(Glib::IOCondition condition, gint64 timeout, const Glib::RefPtr& cancellable{?}), g_socket_condition_timed_wait, errthrow)
_WRAP_METHOD(void set_listen_backlog(int backlog), g_socket_set_listen_backlog)
_WRAP_METHOD(int get_listen_backlog() const, g_socket_get_listen_backlog)
_WRAP_METHOD(void set_blocking(bool blocking), g_socket_set_blocking)
_WRAP_METHOD(bool get_blocking() const, g_socket_get_blocking)
_WRAP_METHOD(void set_keepalive(bool keepalive), g_socket_set_keepalive)
_WRAP_METHOD(bool get_keepalive() const, g_socket_get_keepalive)
_WRAP_METHOD(SocketFamily get_family() const, g_socket_get_family)
_WRAP_METHOD(int get_fd() const, g_socket_get_fd)
_WRAP_METHOD(Glib::RefPtr get_local_address() const, g_socket_get_local_address, errthrow)
_WRAP_METHOD(Glib::RefPtr get_remote_address() const, g_socket_get_remote_address, errthrow)
_WRAP_METHOD(Protocol get_protocol() const, g_socket_get_protocol)
_WRAP_METHOD(Type get_socket_type() const, g_socket_get_socket_type)
_WRAP_METHOD(bool speaks_ipv4() const, g_socket_speaks_ipv4)
_WRAP_METHOD(Glib::RefPtr get_credentials(), g_socket_get_credentials, errthrow)
_WRAP_METHOD(Glib::RefPtr get_credentials() const, g_socket_get_credentials, errthrow)
_WRAP_METHOD(guint get_timeout() const, g_socket_get_timeout)
_WRAP_METHOD(void set_timeout(guint timeout), g_socket_set_timeout)
_WRAP_METHOD_DOCS_ONLY(g_socket_receive_with_blocking)
gssize receive_with_blocking(gchar* buffer, gsize size, bool blocking, const Glib::RefPtr& cancellable = {});
_WRAP_METHOD_DOCS_ONLY(g_socket_send_with_blocking)
gssize send_with_blocking(gchar* buffer, gsize size, bool blocking, const Glib::RefPtr& cancellable = {});
_WRAP_METHOD(bool get_option(int level, int optname, int& value) const, g_socket_get_option, errthrow)
_WRAP_METHOD(bool set_option(int level, int optname, int value), g_socket_set_option, errthrow)
_WRAP_METHOD(guint get_ttl() const, g_socket_get_ttl)
_WRAP_METHOD(void set_ttl(guint ttl), g_socket_set_ttl)
_WRAP_METHOD(bool get_broadcast() const, g_socket_get_broadcast )
_WRAP_METHOD(void set_broadcast(bool broadcast), g_socket_set_broadcast)
_WRAP_METHOD(bool get_multicast_loopback() const, g_socket_get_multicast_loopback)
_WRAP_METHOD(void set_multicast_loopback(bool loopback), g_socket_set_multicast_loopback)
_WRAP_METHOD(guint get_multicast_ttl() const, g_socket_get_multicast_ttl)
_WRAP_METHOD(void set_multicast_ttl(guint ttl), g_socket_set_multicast_ttl)
_WRAP_METHOD(bool join_multicast_group(const Glib::RefPtr& group, bool source_specific, const std::string& iface{?}), g_socket_join_multicast_group, errthrow)
_WRAP_METHOD(bool leave_multicast_group(const Glib::RefPtr& group, bool source_specific, const std::string& iface{?}), g_socket_leave_multicast_group, errthrow)
_WRAP_PROPERTY("blocking", bool)
_WRAP_PROPERTY("family", SocketFamily)
_WRAP_PROPERTY("fd", int)
_WRAP_PROPERTY("keepalive", bool)
_WRAP_PROPERTY("listen-backlog", int)
_WRAP_PROPERTY("local-address", Glib::RefPtr)
_WRAP_PROPERTY("remote-address", Glib::RefPtr)
_WRAP_PROPERTY("timeout", guint)
_WRAP_PROPERTY("protocol", Protocol)
_WRAP_PROPERTY("broadcast", bool)
_WRAP_PROPERTY("type", Type)
_WRAP_PROPERTY("ttl", guint)
_WRAP_PROPERTY("multicast-loopback", bool)
_WRAP_PROPERTY("multicast-ttl", guint)
};
} // namespace Gio