summaryrefslogtreecommitdiff
path: root/gio/src/socket.hg
blob: 602d04522dd0008bb20ba7b1e5244b282e0c0e80 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
// -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 2 -*-

/* 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, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <glibmm/iochannel.h>
#include <glibmm/object.h>
#include <giomm/initable.h>
#include <giomm/credentials.h>
#include <giomm/socketconnectable.h>
#include <giomm/socketaddress.h>
#include <giomm/enums.h>
#include <giomm/inetaddress.h>

_DEFS(giomm,gio)
_PINCLUDE(glibmm/private/object_p.h)

namespace Gio
{

_WRAP_ENUM(SocketType, GSocketType)
_WRAP_ENUM(SocketProtocol, GSocketProtocol)
_WRAP_ENUM(SocketMsgFlags, GSocketMsgFlags)

/** @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 Socket : public Glib::Object, public Initable
{
  _CLASS_GOBJECT(Socket, GSocket, G_SOCKET, Glib::Object, GObject)
  _IMPLEMENTS_INTERFACE(Initable)

protected:
  Socket(SocketFamily family, SocketType type, SocketProtocol protocol,
         const Glib::RefPtr<Cancellable>& cancellable);

  Socket(int fd, const Glib::RefPtr<Cancellable>& cancellable);

public:
  _WRAP_METHOD_DOCS_ONLY(g_socket_new)
  /** @throw Glib::Error
   */
  static Glib::RefPtr<Socket>
  create(SocketFamily family, SocketType type, SocketProtocol protocol,
         const Glib::RefPtr<Cancellable>& cancellable = 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)
  /** @throw Glib::Error
   */
  static Glib::RefPtr<Socket> create_from_fd(int fd, const Glib::RefPtr<Cancellable>&
                                             cancellable = Glib::RefPtr<Cancellable>());

  //TODO: Write custom documetation, mentioning, for instance, the exception, instead of a bool return.
  _WRAP_METHOD(void bind(const Glib::RefPtr<SocketAddress>& address, bool allow_reuse), g_socket_bind, errthrow)
  _WRAP_METHOD(void listen(), g_socket_listen, errthrow)
  _WRAP_METHOD(Glib::RefPtr<Socket> accept(const Glib::RefPtr<Cancellable>& cancellable{?}), g_socket_accept, errthrow)

  //TODO: Write custom documetation, mentioning, for instance, the exception, instead of a bool return.
  _WRAP_METHOD(void connect(const Glib::RefPtr<SocketAddress>& address, const Glib::RefPtr<Cancellable>& 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>& cancellable{?}), g_socket_receive, errthrow)

  _IGNORE(g_socket_receive_from)
  gssize receive_from(Glib::RefPtr<SocketAddress>& address, char* buffer, gsize size, const Glib::RefPtr<Cancellable>& cancellable);
  gssize receive_from(Glib::RefPtr<SocketAddress>& 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>& cancellable{?}), g_socket_send, errthrow)

  // TODO: std::string overload?
  _WRAP_METHOD(gssize send_to(const Glib::RefPtr<SocketAddress>& address, const char* buffer, gsize size, const Glib::RefPtr<Cancellable>& 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)

  //TODO: Glib::Source has no wrap() method: _WRAP_METHOD(Glib::RefPtr<Glib::Source> create_source(Glib::IOCondition condition, const Glib::RefPtr<Cancellable>& cancellable{?}), 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)

  // TODO: non-cancellable version
  // This won't work because Glib::Source is abstract, and Glib::IOSource has no
  // constructor that takes a GSource*
//#m4 _CONVERSION(`GSource*',`Glib::RefPtr<Glib::Source>',`Glib::RefPtr<Glib::Source>(new ::Glib::Source($3))')
  //_WRAP_METHOD(Glib::RefPtr<Glib::Source> create_source(Glib::IOCondition condition, const Glib::RefPtr<Cancellable>& cancellable{?}), g_socket_create_source)

  _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>& cancellable{?}), g_socket_condition_wait, errthrow)

  _WRAP_METHOD(void condition_timed_wait(Glib::IOCondition condition, gint64 timeout, const Glib::RefPtr<Cancellable>& 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<SocketAddress> get_local_address() const, g_socket_get_local_address, errthrow)
  _WRAP_METHOD(Glib::RefPtr<SocketAddress> get_remote_address() const, g_socket_get_remote_address, errthrow)
  _WRAP_METHOD(SocketProtocol get_protocol() const, g_socket_get_protocol)
  _WRAP_METHOD(SocketType get_socket_type() const, g_socket_get_socket_type)
  _WRAP_METHOD(bool speaks_ipv4() const, g_socket_speaks_ipv4)

  _WRAP_METHOD(Glib::RefPtr<Credentials> get_credentials(), g_socket_get_credentials, errthrow)
  _WRAP_METHOD(Glib::RefPtr<const Credentials> 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>& cancellable = 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>& cancellable = Glib::RefPtr<Cancellable>());

  _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<InetAddress>& group, bool source_specific, const std::string& iface{?}), g_socket_join_multicast_group, errthrow)
  _WRAP_METHOD(bool leave_multicast_group(const Glib::RefPtr<InetAddress>& ggroup, 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<SocketAddress>)
  _WRAP_PROPERTY("remote-address", Glib::RefPtr<SocketAddress>)
  _WRAP_PROPERTY("timeout", guint)
  _WRAP_PROPERTY("protocol", SocketProtocol)
  _WRAP_PROPERTY("broadcast", bool)
  _WRAP_PROPERTY("type", SocketType)
  _WRAP_PROPERTY("ttl", guint)
  _WRAP_PROPERTY("multicast-loopback", bool)
  _WRAP_PROPERTY("multicast-ttl", guint)
};

} // namespace Gio