/libgebr/comm/gebr-comm-socket.c
C | 456 lines | 319 code | 93 blank | 44 comment | 43 complexity | 65afd4fca846d996b114a365ce692985 MD5 | raw file
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 20#include <stdio.h> 21#include <string.h> 22#include <sys/types.h> 23#include <sys/socket.h> 24#include <sys/ioctl.h> 25#include <netdb.h> 26#include <netinet/in.h> 27#include <netinet/ip.h> 28#include <arpa/inet.h> 29#include <errno.h> 30 31#include "gebr-comm-socket.h" 32#include "gebr-comm-socketprivate.h" 33#include "gebr-comm-socketaddressprivate.h" 34 35/* 36 * gobject stuff 37 */ 38 39enum { 40 READY_READ, 41 READY_WRITE, 42 ERROR, 43 LAST_SIGNAL 44}; 45static guint object_signals[LAST_SIGNAL]; 46 47static void gebr_comm_socket_class_init(GebrCommSocketClass * class) 48{ 49 /* virtual */ 50 class->connected = NULL; 51 class->disconnected = NULL; 52 class->new_connection = NULL; 53 54 /* signals */ 55 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 */ 56 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); 57 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 */ 58 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); 59 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 */ 60 g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); 61} 62 63static void gebr_comm_socket_init(GebrCommSocket * socket) 64{ 65 socket->io_channel = NULL; 66} 67 68G_DEFINE_TYPE(GebrCommSocket, gebr_comm_socket, G_TYPE_OBJECT) 69 70/* 71 * internal functions 72 */ 73static gboolean __gebr_comm_socket_read(GIOChannel * source, GIOCondition condition, GebrCommSocket * socket) 74{ 75 if (condition & G_IO_NVAL) { 76 /* probably a fd change */ 77 return FALSE; 78 } 79 if (condition & G_IO_ERR) { 80 _gebr_comm_socket_emit_error(socket, GEBR_COMM_SOCKET_ERROR_CONNECTION_REFUSED); 81 return FALSE; 82 } 83 if (condition & G_IO_HUP) { 84 GebrCommSocketClass *klass; 85 86 klass = GEBR_COMM_SOCKET_GET_CLASS(socket); 87 switch (socket->state) { 88 case GEBR_COMM_SOCKET_STATE_CONNECTED: 89 socket->state = GEBR_COMM_SOCKET_STATE_UNCONNECTED; 90 if (klass->disconnected != NULL) 91 klass->disconnected(socket); 92 break; 93 default: 94 break; 95 } 96 97 return FALSE; 98 } 99 if (!gebr_comm_socket_bytes_available(socket)) { 100 GebrCommSocketClass *klass; 101 gboolean ret; 102 103 klass = GEBR_COMM_SOCKET_GET_CLASS(socket); 104 switch (socket->state) { 105 case GEBR_COMM_SOCKET_STATE_LISTENING: 106 if (klass->new_connection != NULL) 107 klass->new_connection(socket); 108 109 ret = TRUE; 110 break; 111 case GEBR_COMM_SOCKET_STATE_CONNECTED: 112 socket->state = GEBR_COMM_SOCKET_STATE_UNCONNECTED; 113 if (klass->disconnected != NULL) 114 klass->disconnected(socket); 115 116 ret = FALSE; 117 break; 118 default: 119 ret = TRUE; 120 break; 121 } 122 123 return ret; 124 } 125 126 g_signal_emit(socket, object_signals[READY_READ], 0); 127 128 return TRUE; 129} 130 131void __gebr_comm_socket_write_queue(GebrCommSocket * socket) 132{ 133 g_return_if_fail(socket->state == GEBR_COMM_SOCKET_STATE_CONNECTED); 134 /* write queud bytes */ 135 if (socket->queue_write_bytes->len) { 136 ssize_t written_bytes; 137 138 _gebr_comm_socket_enable_write_watch(socket); 139 140 written_bytes = send(_gebr_comm_socket_get_fd(socket), socket->queue_write_bytes->data, 141 socket->queue_write_bytes->len > 4096 ? 4096 : socket->queue_write_bytes->len, 0); 142 143 if (written_bytes != -1) 144 g_byte_array_remove_range(socket->queue_write_bytes, 0, written_bytes); 145 } 146} 147 148static gboolean __gebr_comm_socket_write(GIOChannel * source, GIOCondition condition, GebrCommSocket * socket) 149{ 150 if (condition & G_IO_NVAL) { 151 /* probably a fd change */ 152 goto out; 153 } 154 if (condition & G_IO_ERR) { 155 switch (errno) { 156 case ECONNREFUSED: 157 _gebr_comm_socket_emit_error(socket, GEBR_COMM_SOCKET_ERROR_CONNECTION_REFUSED); 158 break; 159 case EINPROGRESS: 160 return TRUE; 161 case 0: 162 return FALSE; 163 default: 164 _gebr_comm_socket_emit_error(socket, GEBR_COMM_SOCKET_ERROR_UNKNOWN); 165 break; 166 } 167 if (socket->state == GEBR_COMM_SOCKET_STATE_CONNECTED) { 168 GebrCommSocketClass *klass; 169 170 klass = GEBR_COMM_SOCKET_GET_CLASS(socket); 171 socket->state = GEBR_COMM_SOCKET_STATE_UNCONNECTED; 172 if (klass->disconnected != NULL) 173 klass->disconnected(socket); 174 } 175 goto out; 176 } 177 if (condition & G_IO_HUP) { 178 /* TODO: */ 179 goto out; 180 } 181 if (socket->state != GEBR_COMM_SOCKET_STATE_CONNECTED) { 182 GebrCommSocketClass *klass; 183 184 klass = GEBR_COMM_SOCKET_GET_CLASS(socket); 185 switch (socket->state) { 186 case GEBR_COMM_SOCKET_STATE_CONNECTING: 187 socket->state = GEBR_COMM_SOCKET_STATE_CONNECTED; 188 if (klass->connected != NULL) 189 klass->connected(socket); 190 break; 191 default: 192 break; 193 } 194 195 goto out; 196 } 197 198 __gebr_comm_socket_write_queue(socket); 199 200 out: return FALSE; 201} 202 203/* 204 * private functions 205 */ 206 207void _gebr_comm_socket_init(GebrCommSocket * socket, int fd, enum GebrCommSocketAddressType address_type) 208{ 209 GError *error; 210 211 /* free previous stuff */ 212 _gebr_comm_socket_close(socket); 213 214 error = NULL; 215 socket->write_watch_id = 0; 216 socket->read_watch_id = 0; 217 socket->address_type = address_type; 218 socket->state = GEBR_COMM_SOCKET_STATE_NONE; 219 socket->last_error = GEBR_COMM_SOCKET_ERROR_NONE; 220 /* IO channel */ 221 socket->io_channel = g_io_channel_unix_new(fd); 222 g_io_channel_set_encoding(socket->io_channel, NULL, &error); 223 g_io_channel_set_close_on_unref(socket->io_channel, TRUE); 224 /* byte array */ 225 socket->queue_write_bytes = g_byte_array_new(); 226} 227 228void _gebr_comm_socket_close(GebrCommSocket * socket) 229{ 230 if (socket->io_channel != NULL) { 231 if (socket->write_watch_id) 232 g_source_remove(socket->write_watch_id); 233 234 if (socket->read_watch_id) 235 g_source_remove(socket->read_watch_id); 236 237 g_io_channel_unref(socket->io_channel); 238 socket->io_channel = NULL; 239 g_byte_array_free(socket->queue_write_bytes, TRUE); 240 } 241} 242 243int _gebr_comm_socket_get_fd(GebrCommSocket * socket) 244{ 245 return g_io_channel_unix_get_fd(socket->io_channel); 246} 247 248void _gebr_comm_socket_enable_read_watch(GebrCommSocket * socket) 249{ 250 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, 251 (GIOFunc) __gebr_comm_socket_read, socket); 252} 253 254void _gebr_comm_socket_enable_write_watch(GebrCommSocket * socket) 255{ 256 socket->write_watch_id = g_io_add_watch(socket->io_channel, G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL, 257 (GIOFunc) __gebr_comm_socket_write, socket); 258} 259 260void _gebr_comm_socket_emit_error(GebrCommSocket * socket, enum GebrCommSocketError error) 261{ 262 socket->last_error = error; 263 g_signal_emit(socket, object_signals[ERROR], 0, error); 264} 265 266/* 267 * user functions 268 */ 269 270void gebr_comm_socket_close(GebrCommSocket * socket) 271{ 272 g_return_if_fail(GEBR_COMM_IS_SOCKET(socket)); 273 274 _gebr_comm_socket_close(socket); 275 276 g_object_unref(G_OBJECT(socket)); 277} 278 279void gebr_comm_socket_flush(GebrCommSocket * socket) 280{ 281 g_return_if_fail(GEBR_COMM_IS_SOCKET(socket)); 282 283 GError *error; 284 gint flags; 285 286 flags = g_io_channel_get_flags(socket->io_channel); 287 288 error = NULL; 289 g_io_channel_set_flags(socket->io_channel, 0, &error); 290 error = NULL; 291 g_io_channel_flush(socket->io_channel, &error); 292 293 error = NULL; 294 g_io_channel_set_flags(socket->io_channel, flags, &error); 295} 296 297void gebr_comm_socket_set_blocking(GebrCommSocket * socket, gboolean blocking_operations) 298{ 299 g_return_if_fail(GEBR_COMM_IS_SOCKET(socket)); 300 301 GError *error; 302 303 error = NULL; 304 if (!blocking_operations) 305 g_io_channel_set_flags(socket->io_channel, g_io_channel_get_flags(socket->io_channel) | G_IO_FLAG_NONBLOCK, &error); 306 else 307 g_io_channel_set_flags(socket->io_channel, g_io_channel_get_flags(socket->io_channel) & ~G_IO_FLAG_NONBLOCK, &error); 308 309} 310 311enum GebrCommSocketState gebr_comm_socket_get_state(GebrCommSocket * socket) 312{ 313 g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), GEBR_COMM_SOCKET_STATE_NONE); 314 315 return socket->state; 316} 317 318enum GebrCommSocketError gebr_comm_socket_get_last_error(GebrCommSocket * socket) 319{ 320 g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), GEBR_COMM_SOCKET_ERROR_NONE); 321 322 return socket->last_error; 323} 324 325GebrCommSocketAddress gebr_comm_socket_get_address(GebrCommSocket * socket) 326{ 327 g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), _gebr_comm_socket_address_unknown()); 328 329 GebrCommSocketAddress address; 330 331 _gebr_comm_socket_address_getsockname(&address, socket->address_type, _gebr_comm_socket_get_fd(socket)); 332 333 return address; 334} 335 336gulong gebr_comm_socket_bytes_available(GebrCommSocket * socket) 337{ 338 g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), 0); 339 340 /* Adapted from QNativeSocketEnginePrivate::nativeBytesAvailable() 341 * (qnativesocketengine_unix.cpp:528 of Qt 4.3.0) 342 */ 343 size_t nbytes = 0; 344 gulong available = 0; 345 346 if (ioctl(_gebr_comm_socket_get_fd(socket), FIONREAD, (char *)&nbytes) >= 0) 347 available = (gulong) nbytes; 348 349 return available; 350} 351 352gulong gebr_comm_socket_bytes_to_write(GebrCommSocket * socket) 353{ 354 g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), 0); 355 356 return socket->queue_write_bytes->len; 357} 358 359GByteArray *gebr_comm_socket_read(GebrCommSocket * socket, gsize max_size) 360{ 361 g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), NULL); 362 363 if (socket->state != GEBR_COMM_SOCKET_STATE_CONNECTED) 364 return NULL; 365 366 guint8 buffer[max_size]; 367 size_t read_bytes; 368 GByteArray *byte_array; 369 370 read_bytes = recv(_gebr_comm_socket_get_fd(socket), buffer, max_size, 0); 371 if (read_bytes == -1) 372 return NULL; 373 374 byte_array = g_byte_array_new(); 375 g_byte_array_append(byte_array, buffer, read_bytes); 376 377 return byte_array; 378} 379 380GString *gebr_comm_socket_read_string(GebrCommSocket * socket, gsize max_size) 381{ 382 g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), NULL); 383 384 if (socket->state != GEBR_COMM_SOCKET_STATE_CONNECTED) 385 return NULL; 386 387 gchar buffer[max_size + 1]; 388 size_t read_bytes; 389 GString *string; 390 391 read_bytes = recv(_gebr_comm_socket_get_fd(socket), buffer, max_size, 0); 392 if (read_bytes == -1) 393 return NULL; 394 395 buffer[read_bytes] = '\0'; 396 string = g_string_new(NULL); 397 g_string_assign(string, buffer); 398 399 return string; 400} 401 402GByteArray *gebr_comm_socket_read_all(GebrCommSocket * socket) 403{ 404 g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), NULL); 405 406 /* trick for lazyness */ 407 return gebr_comm_socket_read(socket, gebr_comm_socket_bytes_available(socket)); 408} 409 410GString *gebr_comm_socket_read_string_all(GebrCommSocket * socket) 411{ 412 g_return_val_if_fail(GEBR_COMM_IS_SOCKET(socket), NULL); 413 414 /* trick for lazyness */ 415 return gebr_comm_socket_read_string(socket, gebr_comm_socket_bytes_available(socket)); 416} 417 418void gebr_comm_socket_write(GebrCommSocket * socket, GByteArray * byte_array) 419{ 420 g_return_if_fail(GEBR_COMM_IS_SOCKET(socket)); 421 422 g_byte_array_append(socket->queue_write_bytes, byte_array->data, byte_array->len); 423 _gebr_comm_socket_enable_write_watch(socket); 424} 425 426void gebr_comm_socket_write_immediately(GebrCommSocket * socket, GByteArray * byte_array) 427{ 428 g_return_if_fail(GEBR_COMM_IS_SOCKET(socket)); 429 430 g_byte_array_append(socket->queue_write_bytes, byte_array->data, byte_array->len); 431 __gebr_comm_socket_write_queue(socket); 432} 433 434void gebr_comm_socket_write_string(GebrCommSocket * socket, GString * string) 435{ 436 g_return_if_fail(GEBR_COMM_IS_SOCKET(socket)); 437 438 GByteArray byte_array; 439 440 byte_array.data = (guint8 *)string->str; 441 byte_array.len = string->len; 442 443 gebr_comm_socket_write(socket, &byte_array); 444} 445 446void gebr_comm_socket_write_string_immediately(GebrCommSocket * socket, GString * string) 447{ 448 g_return_if_fail(GEBR_COMM_IS_SOCKET(socket)); 449 450 GByteArray byte_array; 451 452 byte_array.data = (guint8 *)string->str; 453 byte_array.len = string->len; 454 455 gebr_comm_socket_write_immediately(socket, &byte_array); 456}