X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcsocketstream.c;h=c320644737440f01c2991fe79636de0fea0a493e;hb=9905799a86c606304fd7df2cd401de1740a272a1;hp=e3521a1f48d3c65f3ccdc0cb3487a78997be111d;hpb=0f0340b9fbce9704cc7171f8f0104ce9103d2de6;p=silc.git diff --git a/lib/silcutil/silcsocketstream.c b/lib/silcutil/silcsocketstream.c index e3521a1f..c3206447 100644 --- a/lib/silcutil/silcsocketstream.c +++ b/lib/silcutil/silcsocketstream.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2005 Pekka Riikonen + Copyright (C) 2005 - 2006 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 @@ -17,19 +17,28 @@ */ -#include "silcincludes.h" +#include "silc.h" -#define SILC_IS_SOCKET_STREAM(s) (s->ops == &silc_socket_stream_ops) +/************************** Types and definitions ***************************/ -const SilcStreamOps silc_socket_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, SilcUInt32 data_len); -bool silc_socket_stream_close(SilcStream stream); +SilcBool silc_socket_stream_close(SilcStream stream); +void silc_socket_stream_destroy(SilcStream stream); +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); +void 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 { @@ -42,29 +51,8 @@ typedef struct { unsigned int aborted : 1; } *SilcSocketHostLookup; -/* 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; - } -} +/************************ Static utility functions **************************/ /* Finishing timeout callback that will actually call the user specified host lookup callback. This is executed back in the calling thread and @@ -77,33 +65,19 @@ 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); + stream->schedule = NULL; + silc_socket_stream_destroy(stream); stream = lookup->stream = NULL; } - /* Add the socket to scheduler */ - if (stream) { - silc_schedule_task_add_fd(stream->schedule, stream->sock, - silc_socket_stream_io, stream); - - /* Initially set socket for reading */ - silc_schedule_set_listen_fd(stream->schedule, stream->sock, - SILC_TASK_READ, FALSE); - } - /* Return the created socket stream to the caller */ if (lookup->callback) lookup->callback(lookup->status, stream, lookup->context); @@ -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; } @@ -163,17 +137,27 @@ static void silc_socket_host_lookup_abort(SilcAsyncOperation op, lookup->aborted = TRUE; } -/* Creates socket stream */ + +/******************************* Public API *********************************/ + +/* Creates TCP socket stream */ SilcAsyncOperation -silc_socket_stream_create(int sock, bool lookup, bool require_fqdn, - SilcSchedule schedule, - SilcSocketStreamCallback callback, - void *context) +silc_socket_tcp_stream_create(SilcSocket sock, SilcBool lookup, + SilcBool require_fqdn, + SilcSchedule schedule, + SilcSocketStreamCallback callback, + void *context) { SilcSocketStream stream; SilcSocketHostLookup l; + if (!sock) { + if (callback) + callback(SILC_SOCKET_ERROR, NULL, context); + return NULL; + } + stream = silc_calloc(1, sizeof(*stream)); if (!stream) { if (callback) @@ -181,7 +165,7 @@ silc_socket_stream_create(int sock, bool lookup, bool require_fqdn, return NULL; } - SILC_LOG_DEBUG(("Creating new socket stream %p", stream)); + SILC_LOG_DEBUG(("Creating TCP socket stream %p", stream)); stream->ops = &silc_socket_stream_ops; stream->sock = sock; @@ -225,38 +209,87 @@ silc_socket_stream_create(int sock, bool lookup, bool require_fqdn, } } +/* Creates UDP socket stream */ + +SilcStream silc_socket_udp_stream_create(SilcSocket sock, SilcBool ipv6, + SilcBool connected, + SilcSchedule schedule) +{ + SilcSocketStream stream; + + stream = silc_calloc(1, sizeof(*stream)); + if (!stream) + return NULL; + + SILC_LOG_DEBUG(("Creating UDP socket stream %p", stream)); + + stream->ops = &silc_socket_udp_stream_ops; + 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 */ -bool silc_socket_stream_get_info(SilcStream stream, - int *sock, const char **hostname, - const char **ip, SilcUInt16 *port) +SilcBool silc_socket_stream_get_info(SilcStream stream, + 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) + if (hostname) { + if (!socket_stream->hostname) + return FALSE; *hostname = socket_stream->hostname; - if (ip) + } + if (ip) { + if (!socket_stream->ip) + return FALSE; *ip = socket_stream->ip; - if (port) + } + if (port) { + if (!socket_stream->port) + return FALSE; *port = socket_stream->port; + } return TRUE; } /* Set socket information */ -bool silc_socket_stream_set_info(SilcStream stream, - const char *hostname, - const char *ip, SilcUInt16 port) +SilcBool silc_socket_stream_set_info(SilcStream stream, + 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 (hostname) { @@ -270,6 +303,11 @@ bool 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; @@ -283,7 +321,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; @@ -291,15 +330,16 @@ int silc_socket_stream_get_error(SilcStream stream) /* Set QoS for socket stream */ -bool silc_socket_stream_set_qos(SilcStream stream, - SilcUInt32 read_rate, - SilcUInt32 read_limit_bytes, - SilcUInt32 limit_sec, - SilcUInt32 limit_usec) +SilcBool silc_socket_stream_set_qos(SilcStream stream, + SilcUInt32 read_rate, + SilcUInt32 read_limit_bytes, + SilcUInt32 limit_sec, + SilcUInt32 limit_usec) { 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")); @@ -335,63 +375,17 @@ bool silc_socket_stream_set_qos(SilcStream stream, return TRUE; } -/* Closes socket */ - -bool 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); - - 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_free(socket_stream); -} - -/* Sets stream notification callback for the stream */ +/* Return associated scheduler */ -void silc_socket_stream_notifier(SilcStream stream, - SilcStreamNotifier callback, - void *context) +SilcSchedule silc_socket_stream_get_schedule(SilcStream stream) { SilcSocketStream socket_stream = stream; - if (!SILC_IS_SOCKET_STREAM(socket_stream)) - return; - - SILC_LOG_DEBUG(("Setting stream notifier callback")); + if (!SILC_IS_SOCKET_STREAM(socket_stream) && + !SILC_IS_SOCKET_STREAM_UDP(socket_stream)) + return NULL; - socket_stream->notifier = callback; - socket_stream->notifier_context = context; + return socket_stream->schedule; } /* SILC Socket Stream ops. Functions are implemented under the @@ -403,4 +397,14 @@ const SilcStreamOps silc_socket_stream_ops = silc_socket_stream_close, silc_socket_stream_destroy, silc_socket_stream_notifier, + silc_socket_stream_get_schedule, +}; +const SilcStreamOps silc_socket_udp_stream_ops = +{ + silc_socket_udp_stream_read, + silc_socket_udp_stream_write, + silc_socket_stream_close, + silc_socket_stream_destroy, + silc_socket_stream_notifier, + silc_socket_stream_get_schedule, };