PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/libgebr/comm/gebr-comm-socket.c

https://bitbucket.org/gebrproject/gebr
C | 456 lines | 319 code | 93 blank | 44 comment | 43 complexity | 65afd4fca846d996b114a365ce692985 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. /* libgebr - GeBR Library
  2. * Copyright (C) 2007-2009 GeBR core team (http://www.gebrproject.com/)
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * Inspired on Qt 4.3 version of QAbstractSocket, by Trolltech
  18. */
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <sys/types.h>
  22. #include <sys/socket.h>
  23. #include <sys/ioctl.h>
  24. #include <netdb.h>
  25. #include <netinet/in.h>
  26. #include <netinet/ip.h>
  27. #include <arpa/inet.h>
  28. #include <errno.h>
  29. #include "gebr-comm-socket.h"
  30. #include "gebr-comm-socketprivate.h"
  31. #include "gebr-comm-socketaddressprivate.h"
  32. /*
  33. * gobject stuff
  34. */
  35. enum {
  36. READY_READ,
  37. READY_WRITE,
  38. ERROR,
  39. LAST_SIGNAL
  40. };
  41. static guint object_signals[LAST_SIGNAL];
  42. static void gebr_comm_socket_class_init(GebrCommSocketClass * class)
  43. {
  44. /* virtual */
  45. class->connected = NULL;
  46. class->disconnected = NULL;
  47. class->new_connection = NULL;
  48. /* signals */
  49. object_signals[READY_READ] = g_signal_new("ready-read", GEBR_COMM_SOCKET_TYPE, (GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), G_STRUCT_OFFSET(GebrCommSocketClass, ready_read), NULL, NULL, /* acumulators */
  50. g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
  51. object_signals[READY_WRITE] = g_signal_new("ready-write", GEBR_COMM_SOCKET_TYPE, (GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), G_STRUCT_OFFSET(GebrCommSocketClass, ready_write), NULL, NULL, /* acumulators */
  52. g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
  53. object_signals[ERROR] = g_signal_new("error", GEBR_COMM_SOCKET_TYPE, (GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), G_STRUCT_OFFSET(GebrCommSocketClass, error), NULL, NULL, /* acumulators */
  54. g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
  55. }
  56. static void gebr_comm_socket_init(GebrCommSocket * socket)
  57. {
  58. socket->io_channel = NULL;
  59. }
  60. G_DEFINE_TYPE(GebrCommSocket, gebr_comm_socket, G_TYPE_OBJECT)
  61. /*
  62. * internal functions
  63. */
  64. static gboolean __gebr_comm_socket_read(GIOChannel * source, GIOCondition condition, GebrCommSocket * socket)
  65. {
  66. if (condition & G_IO_NVAL) {
  67. /* probably a fd change */
  68. return FALSE;
  69. }
  70. if (condition & G_IO_ERR) {
  71. _gebr_comm_socket_emit_error(socket, GEBR_COMM_SOCKET_ERROR_CONNECTION_REFUSED);
  72. return FALSE;
  73. }
  74. if (condition & G_IO_HUP) {
  75. GebrCommSocketClass *klass;
  76. klass = GEBR_COMM_SOCKET_GET_CLASS(socket);
  77. switch (socket->state) {
  78. case GEBR_COMM_SOCKET_STATE_CONNECTED:
  79. socket->state = GEBR_COMM_SOCKET_STATE_UNCONNECTED;
  80. if (klass->disconnected != NULL)
  81. klass->disconnected(socket);
  82. break;
  83. default:
  84. break;
  85. }
  86. return FALSE;
  87. }
  88. if (!gebr_comm_socket_bytes_available(socket)) {
  89. GebrCommSocketClass *klass;
  90. gboolean ret;
  91. klass = GEBR_COMM_SOCKET_GET_CLASS(socket);
  92. switch (socket->state) {
  93. case GEBR_COMM_SOCKET_STATE_LISTENING:
  94. if (klass->new_connection != NULL)
  95. klass->new_connection(socket);
  96. ret = TRUE;
  97. break;
  98. case GEBR_COMM_SOCKET_STATE_CONNECTED:
  99. socket->state = GEBR_COMM_SOCKET_STATE_UNCONNECTED;
  100. if (klass->disconnected != NULL)
  101. klass->disconnected(socket);
  102. ret = FALSE;
  103. break;
  104. default:
  105. ret = TRUE;
  106. break;
  107. }
  108. return ret;
  109. }
  110. g_signal_emit(socket, object_signals[READY_READ], 0);
  111. return TRUE;
  112. }
  113. void __gebr_comm_socket_write_queue(GebrCommSocket * socket)
  114. {
  115. g_return_if_fail(socket->state == GEBR_COMM_SOCKET_STATE_CONNECTED);
  116. /* write queud bytes */
  117. if (socket->queue_write_bytes->len) {
  118. ssize_t written_bytes;
  119. _gebr_comm_socket_enable_write_watch(socket);
  120. written_bytes = send(_gebr_comm_socket_get_fd(socket), socket->queue_write_bytes->data,
  121. socket->queue_write_bytes->len > 4096 ? 4096 : socket->queue_write_bytes->len, 0);
  122. if (written_bytes != -1)
  123. g_byte_array_remove_range(socket->queue_write_bytes, 0, written_bytes);
  124. }
  125. }
  126. static gboolean __gebr_comm_socket_write(GIOChannel * source, GIOCondition condition, GebrCommSocket * socket)
  127. {
  128. if (condition & G_IO_NVAL) {
  129. /* probably a fd change */
  130. goto out;
  131. }
  132. if (condition & G_IO_ERR) {
  133. switch (errno) {
  134. case ECONNREFUSED:
  135. _gebr_comm_socket_emit_error(socket, GEBR_COMM_SOCKET_ERROR_CONNECTION_REFUSED);
  136. break;
  137. case EINPROGRESS:
  138. return TRUE;
  139. case 0:
  140. return FALSE;
  141. default:
  142. _gebr_comm_socket_emit_error(socket, GEBR_COMM_SOCKET_ERROR_UNKNOWN);
  143. break;
  144. }
  145. if (socket->state == GEBR_COMM_SOCKET_STATE_CONNECTED) {
  146. GebrCommSocketClass *klass;
  147. klass = GEBR_COMM_SOCKET_GET_CLASS(socket);
  148. socket->state = GEBR_COMM_SOCKET_STATE_UNCONNECTED;
  149. if (klass->disconnected != NULL)
  150. klass->disconnected(socket);
  151. }
  152. goto out;
  153. }
  154. if (condition & G_IO_HUP) {
  155. /* TODO: */
  156. goto out;
  157. }
  158. if (socket->state != GEBR_COMM_SOCKET_STATE_CONNECTED) {
  159. GebrCommSocketClass *klass;
  160. klass = GEBR_COMM_SOCKET_GET_CLASS(socket);
  161. switch (socket->state) {
  162. case GEBR_COMM_SOCKET_STATE_CONNECTING:
  163. socket->state = GEBR_COMM_SOCKET_STATE_CONNECTED;
  164. if (klass->connected != NULL)
  165. klass->connected(socket);
  166. break;
  167. default:
  168. break;
  169. }
  170. goto out;
  171. }
  172. __gebr_comm_socket_write_queue(socket);
  173. out: return FALSE;
  174. }
  175. /*
  176. * private functions
  177. */
  178. void _gebr_comm_socket_init(GebrCommSocket * socket, int fd, enum GebrCommSocketAddressType address_type)
  179. {
  180. GError *error;
  181. /* free previous stuff */
  182. _gebr_comm_socket_close(socket);
  183. error = NULL;
  184. socket->write_watch_id = 0;
  185. socket->read_watch_id = 0;
  186. socket->address_type = address_type;
  187. socket->state = GEBR_COMM_SOCKET_STATE_NONE;
  188. socket->last_error = GEBR_COMM_SOCKET_ERROR_NONE;
  189. /* IO channel */
  190. socket->io_channel = g_io_channel_unix_new(fd);
  191. g_io_channel_set_encoding(socket->io_channel, NULL, &error);
  192. g_io_channel_set_close_on_unref(socket->io_channel, TRUE);
  193. /* byte array */
  194. socket->queue_write_bytes = g_byte_array_new();
  195. }
  196. void _gebr_comm_socket_close(GebrCommSocket * socket)
  197. {
  198. if (socket->io_channel != NULL) {
  199. if (socket->write_watch_id)
  200. g_source_remove(socket->write_watch_id);
  201. if (socket->read_watch_id)
  202. g_source_remove(socket->read_watch_id);
  203. g_io_channel_unref(socket->io_channel);
  204. socket->io_channel = NULL;
  205. g_byte_array_free(socket->queue_write_bytes, TRUE);
  206. }
  207. }
  208. int _gebr_comm_socket_get_fd(GebrCommSocket * socket)
  209. {
  210. return g_io_channel_unix_get_fd(socket->io_channel);
  211. }
  212. void _gebr_comm_socket_enable_read_watch(GebrCommSocket * socket)
  213. {
  214. socket->read_watch_id = g_io_add_watch(socket->io_channel, G_IO_IN | G_IO_PRI | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
  215. (GIOFunc) __gebr_comm_socket_read, socket);
  216. }
  217. void _gebr_comm_socket_enable_write_watch(GebrCommSocket * socket)
  218. {
  219. socket->write_watch_id = g_io_add_watch(socket->io_channel, G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
  220. (GIOFunc) __gebr_comm_socket_write, socket);
  221. }
  222. void _gebr_comm_socket_emit_error(GebrCommSocket * socket, enum GebrCommSocketError error)
  223. {
  224. socket->last_error = error;
  225. g_signal_emit(socket, object_signals[ERROR], 0, error);
  226. }
  227. /*
  228. * user functions
  229. */
  230. void gebr_comm_socket_close(GebrCommSocket * socket)
  231. {
  232. g_return_if_fail(GEBR_COMM_IS_SOCKET(socket));
  233. _gebr_comm_socket_close(socket);
  234. g_object_unref(G_OBJECT(socket));
  235. }
  236. void gebr_comm_socket_flush(GebrCommSocket * socket)
  237. {
  238. g_return_if_fail(GEBR_COMM_IS_SOCKET(socket));
  239. GError *error;
  240. gint flags;
  241. flags = g_io_channel_get_flags(socket->io_channel);
  242. error = NULL;
  243. g_io_channel_set_flags(socket->io_channel, 0, &error);
  244. error = NULL;
  245. g_io_channel_flush(socket->io_channel, &error);
  246. error = NULL;
  247. g_io_channel_set_flags(socket->io_channel, flags, &error);
  248. }
  249. void gebr_comm_socket_set_blocking(GebrCommSocket * socket, gboolean blocking_operations)
  250. {
  251. g_return_if_fail(GEBR_COMM_IS_SOCKET(socket));
  252. GError *error;
  253. error = NULL;
  254. if (!blocking_operations)
  255. g_io_channel_set_flags(socket->io_channel, g_io_channel_get_flags(socket->io_channel) | G_IO_FLAG_NONBLOCK, &error);
  256. else
  257. g_io_channel_set_flags(socket->io_channel, g_io_channel_get_flags(socket->io_channel) & ~G_IO_FLAG_NONBLOCK, &error);
  258. }
  259. enum GebrCommSocketState gebr_comm_socket_get_state(GebrCommSocket * socket)
  260. {
  261. g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), GEBR_COMM_SOCKET_STATE_NONE);
  262. return socket->state;
  263. }
  264. enum GebrCommSocketError gebr_comm_socket_get_last_error(GebrCommSocket * socket)
  265. {
  266. g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), GEBR_COMM_SOCKET_ERROR_NONE);
  267. return socket->last_error;
  268. }
  269. GebrCommSocketAddress gebr_comm_socket_get_address(GebrCommSocket * socket)
  270. {
  271. g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), _gebr_comm_socket_address_unknown());
  272. GebrCommSocketAddress address;
  273. _gebr_comm_socket_address_getsockname(&address, socket->address_type, _gebr_comm_socket_get_fd(socket));
  274. return address;
  275. }
  276. gulong gebr_comm_socket_bytes_available(GebrCommSocket * socket)
  277. {
  278. g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), 0);
  279. /* Adapted from QNativeSocketEnginePrivate::nativeBytesAvailable()
  280. * (qnativesocketengine_unix.cpp:528 of Qt 4.3.0)
  281. */
  282. size_t nbytes = 0;
  283. gulong available = 0;
  284. if (ioctl(_gebr_comm_socket_get_fd(socket), FIONREAD, (char *)&nbytes) >= 0)
  285. available = (gulong) nbytes;
  286. return available;
  287. }
  288. gulong gebr_comm_socket_bytes_to_write(GebrCommSocket * socket)
  289. {
  290. g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), 0);
  291. return socket->queue_write_bytes->len;
  292. }
  293. GByteArray *gebr_comm_socket_read(GebrCommSocket * socket, gsize max_size)
  294. {
  295. g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), NULL);
  296. if (socket->state != GEBR_COMM_SOCKET_STATE_CONNECTED)
  297. return NULL;
  298. guint8 buffer[max_size];
  299. size_t read_bytes;
  300. GByteArray *byte_array;
  301. read_bytes = recv(_gebr_comm_socket_get_fd(socket), buffer, max_size, 0);
  302. if (read_bytes == -1)
  303. return NULL;
  304. byte_array = g_byte_array_new();
  305. g_byte_array_append(byte_array, buffer, read_bytes);
  306. return byte_array;
  307. }
  308. GString *gebr_comm_socket_read_string(GebrCommSocket * socket, gsize max_size)
  309. {
  310. g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), NULL);
  311. if (socket->state != GEBR_COMM_SOCKET_STATE_CONNECTED)
  312. return NULL;
  313. gchar buffer[max_size + 1];
  314. size_t read_bytes;
  315. GString *string;
  316. read_bytes = recv(_gebr_comm_socket_get_fd(socket), buffer, max_size, 0);
  317. if (read_bytes == -1)
  318. return NULL;
  319. buffer[read_bytes] = '\0';
  320. string = g_string_new(NULL);
  321. g_string_assign(string, buffer);
  322. return string;
  323. }
  324. GByteArray *gebr_comm_socket_read_all(GebrCommSocket * socket)
  325. {
  326. g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), NULL);
  327. /* trick for lazyness */
  328. return gebr_comm_socket_read(socket, gebr_comm_socket_bytes_available(socket));
  329. }
  330. GString *gebr_comm_socket_read_string_all(GebrCommSocket * socket)
  331. {
  332. g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), NULL);
  333. /* trick for lazyness */
  334. return gebr_comm_socket_read_string(socket, gebr_comm_socket_bytes_available(socket));
  335. }
  336. void gebr_comm_socket_write(GebrCommSocket * socket, GByteArray * byte_array)
  337. {
  338. g_return_if_fail(GEBR_COMM_IS_SOCKET(socket));
  339. g_byte_array_append(socket->queue_write_bytes, byte_array->data, byte_array->len);
  340. _gebr_comm_socket_enable_write_watch(socket);
  341. }
  342. void gebr_comm_socket_write_immediately(GebrCommSocket * socket, GByteArray * byte_array)
  343. {
  344. g_return_if_fail(GEBR_COMM_IS_SOCKET(socket));
  345. g_byte_array_append(socket->queue_write_bytes, byte_array->data, byte_array->len);
  346. __gebr_comm_socket_write_queue(socket);
  347. }
  348. void gebr_comm_socket_write_string(GebrCommSocket * socket, GString * string)
  349. {
  350. g_return_if_fail(GEBR_COMM_IS_SOCKET(socket));
  351. GByteArray byte_array;
  352. byte_array.data = (guint8 *)string->str;
  353. byte_array.len = string->len;
  354. gebr_comm_socket_write(socket, &byte_array);
  355. }
  356. void gebr_comm_socket_write_string_immediately(GebrCommSocket * socket, GString * string)
  357. {
  358. g_return_if_fail(GEBR_COMM_IS_SOCKET(socket));
  359. GByteArray byte_array;
  360. byte_array.data = (guint8 *)string->str;
  361. byte_array.len = string->len;
  362. gebr_comm_socket_write_immediately(socket, &byte_array);
  363. }