X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcsocketstream.c;h=e4b59f5a601c6d0019632438514f780a48729507;hb=196824372226561334cd638d6471267cbffb354c;hp=b599dabf732f46664ab32fae32f67f68a864dff5;hpb=c14dc73816933bb82e63a2ffbc90eaca9c9895d3;p=silc.git diff --git a/lib/silcutil/silcsocketstream.c b/lib/silcutil/silcsocketstream.c index b599dabf..e4b59f5a 100644 --- a/lib/silcutil/silcsocketstream.c +++ b/lib/silcutil/silcsocketstream.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2005 - 2006 Pekka Riikonen + Copyright (C) 2005 - 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,12 +21,7 @@ /************************** Types and definitions ***************************/ -#define SILC_IS_SOCKET_STREAM(s) (s->ops == &silc_socket_stream_ops) - -const SilcStreamOps silc_socket_stream_ops; -const SilcStreamOps silc_socket_udp_stream_ops; - -/* Platform specific functions */ +/* Stream operation functions (platform specific) */ int silc_socket_stream_read(SilcStream stream, unsigned char *buf, SilcUInt32 buf_len); int silc_socket_stream_write(SilcStream stream, const unsigned char *data, @@ -37,6 +32,13 @@ int silc_socket_udp_stream_read(SilcStream stream, unsigned char *buf, SilcUInt32 buf_len); int silc_socket_udp_stream_write(SilcStream stream, const unsigned char *data, SilcUInt32 data_len); +SilcBool silc_socket_stream_close(SilcStream stream); +void silc_socket_stream_destroy(SilcStream stream); +SilcBool silc_socket_stream_notifier(SilcStream stream, + SilcSchedule schedule, + SilcStreamNotifier callback, + void *context); +SilcSchedule silc_socket_stream_get_schedule(SilcStream stream); /* Internal async host lookup context. */ typedef struct { @@ -52,30 +54,6 @@ typedef struct { /************************ Static utility functions **************************/ -/* The IO process callback that calls the notifier callback to upper - layer. */ - -SILC_TASK_CALLBACK(silc_socket_stream_io) -{ - SilcSocketStream stream = context; - - if (!stream->notifier) - return; - - switch (type) { - case SILC_TASK_WRITE: - stream->notifier(stream, SILC_STREAM_CAN_WRITE, stream->notifier_context); - break; - - case SILC_TASK_READ: - stream->notifier(stream, SILC_STREAM_CAN_READ, stream->notifier_context); - break; - - default: - break; - } -} - /* Finishing timeout callback that will actually call the user specified host lookup callback. This is executed back in the calling thread and not in the lookup thread. */ @@ -87,20 +65,16 @@ SILC_TASK_CALLBACK(silc_socket_host_lookup_finish) if (lookup->aborted) { SILC_LOG_DEBUG(("Socket stream creation was aborted")); - silc_net_close_connection(stream->sock); - silc_free(stream->ip); - silc_free(stream->hostname); - silc_free(stream); + stream->schedule = NULL; + silc_socket_stream_destroy(stream); silc_free(lookup); return; } if (lookup->status != SILC_SOCKET_OK) { - SILC_LOG_DEBUG(("Socket stream failed")); - silc_net_close_connection(stream->sock); - silc_free(stream->ip); - silc_free(stream->hostname); - silc_free(stream); + SILC_LOG_DEBUG(("Socket stream lookup failed")); + stream->schedule = NULL; + silc_socket_stream_destroy(stream); stream = lookup->stream = NULL; } @@ -146,7 +120,7 @@ static void *silc_socket_host_lookup_start(void *context) out: silc_schedule_task_add_timeout(schedule, silc_socket_host_lookup_finish, - lookup, 0, 1); + lookup, 0, 0); silc_schedule_wakeup(schedule); return NULL; } @@ -169,7 +143,7 @@ static void silc_socket_host_lookup_abort(SilcAsyncOperation op, /* Creates TCP socket stream */ SilcAsyncOperation -silc_socket_tcp_stream_create(int sock, SilcBool lookup, +silc_socket_tcp_stream_create(SilcSocket sock, SilcBool lookup, SilcBool require_fqdn, SilcSchedule schedule, SilcSocketStreamCallback callback, @@ -178,6 +152,13 @@ silc_socket_tcp_stream_create(int sock, SilcBool lookup, SilcSocketStream stream; SilcSocketHostLookup l; + if (!sock || !schedule) { + SILC_LOG_ERROR(("Missing arguments to silc_socket_tcp_stream_create")); + if (callback) + callback(SILC_SOCKET_ERROR, NULL, context); + return NULL; + } + stream = silc_calloc(1, sizeof(*stream)); if (!stream) { if (callback) @@ -185,11 +166,12 @@ silc_socket_tcp_stream_create(int sock, SilcBool lookup, return NULL; } - SILC_LOG_DEBUG(("Creating TCP socket stream %p", stream)); + SILC_LOG_DEBUG(("Creating TCP socket stream %p, sock %lu", stream, sock)); stream->ops = &silc_socket_stream_ops; stream->sock = sock; stream->schedule = schedule; + stream->connected = TRUE; l = silc_calloc(1, sizeof(*l)); if (!l) { @@ -231,7 +213,8 @@ silc_socket_tcp_stream_create(int sock, SilcBool lookup, /* Creates UDP socket stream */ -SilcStream silc_socket_udp_stream_create(int sock, SilcBool ipv6, +SilcStream silc_socket_udp_stream_create(SilcSocket sock, SilcBool ipv6, + SilcBool connected, SilcSchedule schedule) { SilcSocketStream stream; @@ -246,29 +229,55 @@ SilcStream silc_socket_udp_stream_create(int sock, SilcBool ipv6, stream->sock = sock; stream->schedule = schedule; stream->ipv6 = ipv6; + stream->connected = connected; return (SilcStream)stream; } +/* Returns TRUE if the stream is UDP stream */ + +SilcBool silc_socket_stream_is_udp(SilcStream stream, SilcBool *connected) +{ + SilcSocketStream socket_stream = stream; + + if (!SILC_IS_SOCKET_STREAM_UDP(socket_stream)) + return FALSE; + + if (connected) + *connected = socket_stream->connected; + + return TRUE; +} + /* Returns socket stream information */ SilcBool silc_socket_stream_get_info(SilcStream stream, - int *sock, const char **hostname, + SilcSocket *sock, const char **hostname, const char **ip, SilcUInt16 *port) { SilcSocketStream socket_stream = stream; - if (!SILC_IS_SOCKET_STREAM(socket_stream)) + if (!SILC_IS_SOCKET_STREAM(socket_stream) && + !SILC_IS_SOCKET_STREAM_UDP(socket_stream)) return FALSE; if (sock) *sock = socket_stream->sock; - if (hostname) - *hostname = socket_stream->hostname; - if (ip) - *ip = socket_stream->ip; - if (port) + if (port) { + if (!socket_stream->port) + return FALSE; *port = socket_stream->port; + } + if (ip) { + if (!socket_stream->ip) + return FALSE; + *ip = socket_stream->ip; + } + if (hostname) { + if (!socket_stream->hostname) + return FALSE; + *hostname = socket_stream->hostname; + } return TRUE; } @@ -281,7 +290,8 @@ SilcBool silc_socket_stream_set_info(SilcStream stream, { SilcSocketStream socket_stream = stream; - if (!SILC_IS_SOCKET_STREAM(socket_stream)) + if (!SILC_IS_SOCKET_STREAM(socket_stream) && + !SILC_IS_SOCKET_STREAM_UDP(socket_stream)) return FALSE; if (hostname) { @@ -295,6 +305,11 @@ SilcBool silc_socket_stream_set_info(SilcStream stream, socket_stream->ip = strdup(ip); if (!socket_stream->ip) return FALSE; + if (!socket_stream->hostname) { + socket_stream->hostname = strdup(ip); + if (!socket_stream->hostname) + return FALSE; + } } if (port) socket_stream->port = port; @@ -308,7 +323,8 @@ int silc_socket_stream_get_error(SilcStream stream) { SilcSocketStream socket_stream = stream; - if (!SILC_IS_SOCKET_STREAM(socket_stream)) + if (!SILC_IS_SOCKET_STREAM(socket_stream) && + !SILC_IS_SOCKET_STREAM_UDP(socket_stream)) return 0; return socket_stream->sock_error; @@ -324,7 +340,8 @@ SilcBool silc_socket_stream_set_qos(SilcStream stream, { SilcSocketStream socket_stream = stream; - if (!SILC_IS_SOCKET_STREAM(socket_stream)) + if (!SILC_IS_SOCKET_STREAM(socket_stream) && + !SILC_IS_SOCKET_STREAM_UDP(socket_stream)) return FALSE; SILC_LOG_DEBUG(("Setting QoS for socket stream")); @@ -360,95 +377,14 @@ SilcBool silc_socket_stream_set_qos(SilcStream stream, return TRUE; } -/* Closes socket */ - -SilcBool silc_socket_stream_close(SilcStream stream) -{ - SilcSocketStream socket_stream = stream; - - if (!SILC_IS_SOCKET_STREAM(socket_stream)) - return FALSE; - - silc_schedule_unset_listen_fd(socket_stream->schedule, socket_stream->sock); - silc_net_close_connection(socket_stream->sock); - - return TRUE; -} - -/* Destroys the stream */ - -void silc_socket_stream_destroy(SilcStream stream) -{ - SilcSocketStream socket_stream = stream; - - if (!SILC_IS_SOCKET_STREAM(socket_stream)) - return; - - silc_socket_stream_close(socket_stream); - silc_free(socket_stream->ip); - silc_free(socket_stream->hostname); - silc_schedule_task_del_by_fd(socket_stream->schedule, socket_stream->sock); - - if (socket_stream->qos) { - silc_schedule_task_del_by_context(socket_stream->schedule, - socket_stream->qos); - if (socket_stream->qos->buffer) { - memset(socket_stream->qos->buffer, 0, - socket_stream->qos->read_limit_bytes); - silc_free(socket_stream->qos->buffer); - } - silc_free(socket_stream->qos); - } - - silc_schedule_wakeup(socket_stream->schedule); - - silc_free(socket_stream); -} - -/* Sets stream notification callback for the stream */ - -void silc_socket_stream_notifier(SilcStream stream, - SilcSchedule schedule, - SilcStreamNotifier callback, - void *context) -{ - SilcSocketStream socket_stream = stream; - - if (!SILC_IS_SOCKET_STREAM(socket_stream)) - return; - - SILC_LOG_DEBUG(("Setting stream notifier callback")); - - socket_stream->notifier = callback; - socket_stream->notifier_context = context; - socket_stream->schedule = schedule; - - if (socket_stream->notifier) { - /* Add the socket to scheduler. Safe to call if already added. */ - silc_schedule_task_add_fd(socket_stream->schedule, socket_stream->sock, - silc_socket_stream_io, socket_stream); - - /* Initially set socket for reading */ - silc_schedule_set_listen_fd(socket_stream->schedule, socket_stream->sock, - SILC_TASK_READ, FALSE); - silc_schedule_wakeup(socket_stream->schedule); - } else { - /* Unschedule the socket */ - silc_schedule_unset_listen_fd(socket_stream->schedule, - socket_stream->sock); - silc_schedule_task_del_by_fd(socket_stream->schedule, - socket_stream->sock); - silc_schedule_wakeup(socket_stream->schedule); - } -} - /* Return associated scheduler */ SilcSchedule silc_socket_stream_get_schedule(SilcStream stream) { SilcSocketStream socket_stream = stream; - if (!SILC_IS_SOCKET_STREAM(socket_stream)) + if (!SILC_IS_SOCKET_STREAM(socket_stream) && + !SILC_IS_SOCKET_STREAM_UDP(socket_stream)) return NULL; return socket_stream->schedule;