From: Pekka Riikonen Date: Wed, 19 Jul 2006 09:36:08 +0000 (+0000) Subject: Moved silcidcache.[ch] from lib/silccore. X-Git-Tag: 1.2.beta1~729 X-Git-Url: http://git.silcnet.org/gitweb/?p=crypto.git;a=commitdiff_plain;h=8dc0b1dfbdf60e909f478f7fca161d3e37996354 Moved silcidcache.[ch] from lib/silccore. --- diff --git a/lib/silcutil/DIRECTORY b/lib/silcutil/DIRECTORY index 6aa43e1a..41050d54 100644 --- a/lib/silcutil/DIRECTORY +++ b/lib/silcutil/DIRECTORY @@ -24,6 +24,7 @@ @LINK=silcdlist.html:SILC Dynamic List Interface @LINK=silcvcard.html:SILC VCard Interface @LINK=silcapputil.html:SILC Application Utilities +@LINK=silcidcache.html:SILC ID Cache Interface --> SILC Utility Library diff --git a/lib/silcutil/Makefile.ad b/lib/silcutil/Makefile.ad index 3037fe24..9f5c80ce 100644 --- a/lib/silcutil/Makefile.ad +++ b/lib/silcutil/Makefile.ad @@ -67,7 +67,8 @@ libsilcutil_la_SOURCES = \ silcasync.c \ silctime.c \ silcmime.c \ - silcstack.c + silcstack.c \ + silcidcache.c #ifdef SILC_DIST_TOOLKIT include_HEADERS = \ @@ -104,7 +105,8 @@ include_HEADERS = \ silcasync.h \ silcasync_i.h \ silcstack.h \ - silcstack_i.h + silcstack_i.h \ + silcidcache.h SILC_EXTRA_DIST = tests #endif SILC_DIST_TOOLKIT diff --git a/lib/silcutil/silcbuffer.h b/lib/silcutil/silcbuffer.h index 64408502..f70c020d 100644 --- a/lib/silcutil/silcbuffer.h +++ b/lib/silcutil/silcbuffer.h @@ -212,8 +212,8 @@ typedef struct { * * SOURCE */ -#define silc_buffer_datalen(x) (x) ? silc_buffer_data(x) : NULL, \ - (x) ? silc_buffer_len(x) : 0 +#define silc_buffer_datalen(x) (x) ? silc_buffer_data((x)) : NULL, \ + (x) ? silc_buffer_len((x)) : 0 /***/ /* Inline functions */ diff --git a/lib/silcutil/silcidcache.c b/lib/silcutil/silcidcache.c new file mode 100644 index 00000000..05959388 --- /dev/null +++ b/lib/silcutil/silcidcache.c @@ -0,0 +1,341 @@ +/* + + silcidcache.c + + Author: Pekka Riikonen + + Copyright (C) 2000 - 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 + the Free Software Foundation; version 2 of the License. + + This program 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 General Public License for more details. + +*/ +/* $Id$ */ + +#include "silc.h" +#include "silcidcache.h" + +/************************** Types and definitions ***************************/ + +/* ID Cache context */ +struct SilcIDCacheStruct { + SilcHashTable id_table; /* ID hash table */ + SilcHashTable name_table; /* Name hash table */ + SilcHashTable context_table; /* Context hash table */ + SilcIDCacheDestructor destructor; /* Entry destructor */ + void *context; /* Destructor context */ + SilcIdType id_type; /* Type of ID cache */ +}; + + +/************************ Static utility functions **************************/ + +/* Callback that is called by the hash table routine when traversing + entries in the hash table. */ + +static void silc_idcache_get_all_foreach(void *key, void *context, + void *user_context) +{ + SilcList *list = user_context; + if (!context) + return; + silc_list_add(*list, context); +} + +/* Cache entry destructor */ + +static void silc_idcache_destructor(SilcIDCache cache, + SilcIDCacheEntry entry, + void *app_context) +{ + if (cache->destructor) + cache->destructor(cache, entry, cache->destructor, app_context); + + memset(entry, 'F', sizeof(*entry)); + silc_free(entry); +} + + +/****************************** Public API **********************************/ + +/* Allocates new ID cache object. */ + +SilcIDCache silc_idcache_alloc(SilcUInt32 count, SilcIdType id_type, + SilcIDCacheDestructor destructor, + void *destructor_context) +{ + SilcIDCache cache; + + SILC_LOG_DEBUG(("Allocating new cache")); + + cache = silc_calloc(1, sizeof(*cache)); + if (!cache) + return NULL; + + cache->id_table = silc_hash_table_alloc(count, silc_hash_id, + SILC_32_TO_PTR(id_type), + silc_hash_id_compare, + SILC_32_TO_PTR(id_type), + NULL, NULL, TRUE); + cache->name_table = silc_hash_table_alloc(count, silc_hash_utf8_string, NULL, + silc_hash_utf8_compare, NULL, + NULL, NULL, TRUE); + cache->context_table = silc_hash_table_alloc(count, silc_hash_ptr, NULL, + NULL, NULL, NULL, NULL, TRUE); + cache->destructor = destructor; + cache->context = destructor_context; + cache->id_type = id_type; + + if (!cache->id_table || !cache->name_table || !cache->context_table) { + if (cache->id_table) + silc_hash_table_free(cache->id_table); + if (cache->name_table) + silc_hash_table_free(cache->name_table); + if (cache->context_table) + silc_hash_table_free(cache->context_table); + silc_free(cache); + return NULL; + } + + return cache; +} + +/* Frees ID cache object and cache entries */ + +void silc_idcache_free(SilcIDCache cache) +{ + silc_hash_table_free(cache->id_table); + silc_hash_table_free(cache->name_table); + silc_hash_table_free(cache->context_table); + silc_free(cache); +} + +/* Add new entry to cache */ + +SilcIDCacheEntry +silc_idcache_add(SilcIDCache cache, char *name, void *id, void *context) +{ + SilcIDCacheEntry c; + + if (!id) + return NULL; + + /* Allocate new cache entry */ + c = silc_calloc(1, sizeof(*c)); + if (!c) + return NULL; + + c->id = id; + c->name = name; + c->context = context; + + SILC_LOG_DEBUG(("Adding cache entry %p", c)); + + /* Add the new entry to the hash tables */ + + if (id) { + if (silc_idcache_find_by_id_one(cache, id, NULL)) { + SILC_LOG_ERROR(("Attempted to add same ID twice to ID Cache")); + goto err; + } + if (!silc_hash_table_add(cache->id_table, id, c)) + goto err; + } + if (name) + if (!silc_hash_table_add(cache->name_table, name, c)) + goto err; + if (context) + if (!silc_hash_table_add(cache->context_table, context, c)) + goto err; + + return c; + + err: + if (c->name) + silc_hash_table_del_by_context(cache->name_table, c->name, c); + if (c->context) + silc_hash_table_del_by_context(cache->context_table, c->context, c); + if (c->id) + silc_hash_table_del_by_context(cache->id_table, c->id, c); + silc_free(c); + + return NULL; +} + +/* Delete cache entry from cache. */ + +SilcBool silc_idcache_del(SilcIDCache cache, SilcIDCacheEntry entry, + void *app_context) +{ + SilcBool ret = FALSE; + + SILC_LOG_DEBUG(("Deleting cache entry %p", entry)); + + if (entry->name) + ret = silc_hash_table_del_by_context(cache->name_table, entry->name, + entry); + if (entry->context) + ret = silc_hash_table_del_by_context(cache->context_table, entry->context, + entry); + if (entry->id) + ret = silc_hash_table_del_by_context(cache->id_table, entry->id, + entry); + + if (ret) + silc_idcache_destructor(cache, entry, app_context); + + return ret; +} + +/* Deletes ID cache entry by ID. */ + +SilcBool silc_idcache_del_by_id(SilcIDCache cache, void *id, + void *app_context) +{ + SilcIDCacheEntry c; + + if (!silc_hash_table_find(cache->id_table, id, NULL, (void **)&c)) + return FALSE; + + return silc_idcache_del(cache, c, app_context); +} + +/* Deletes ID cache entry by context. */ + +SilcBool silc_idcache_del_by_context(SilcIDCache cache, void *context, + void *app_context) +{ + SilcIDCacheEntry c; + + if (!silc_hash_table_find(cache->context_table, context, NULL, (void **)&c)) + return FALSE; + + return silc_idcache_del(cache, c, app_context); +} + +/* Update entry */ + +SilcBool silc_idcache_update(SilcIDCache cache, SilcIDCacheEntry entry, + void *old_id, void *new_id, + char *old_name, char *new_name) +{ + if (old_id && new_id) { + if (!silc_hash_table_del_by_context(cache->id_table, old_id, entry)) + return FALSE; + + if (cache->id_type == SILC_ID_CLIENT) + *(SilcClientID *)entry->id = *(SilcClientID *)new_id; + if (cache->id_type == SILC_ID_SERVER) + *(SilcServerID *)entry->id = *(SilcServerID *)new_id; + if (cache->id_type == SILC_ID_CHANNEL) + *(SilcChannelID *)entry->id = *(SilcChannelID *)new_id; + + if (!silc_hash_table_add(cache->id_table, entry->id, entry)) + return FALSE; + } + + if (old_name && new_name) { + if (!silc_hash_table_del_by_context(cache->name_table, old_name, entry)) + return FALSE; + + entry->name = new_name; + + if (!silc_hash_table_add(cache->name_table, entry->name, entry)) + return FALSE; + } + + return TRUE; +} + +/* Returns all cache entrys from the ID cache to the `ret' ID Cache List. */ + +SilcBool silc_idcache_get_all(SilcIDCache cache, SilcList *ret_list) +{ + if (!ret_list) + return FALSE; + + if (!silc_hash_table_count(cache->id_table)) + return FALSE; + + silc_hash_table_foreach(cache->id_table, silc_idcache_get_all_foreach, + ret_list); + + if (!silc_list_count(*ret_list)) + return FALSE; + + return TRUE; +} + +/* Find ID Cache entry by ID. May return multiple entries. */ + +SilcBool silc_idcache_find_by_id(SilcIDCache cache, void *id, + SilcList *ret_list) +{ + if (!ret_list) + return FALSE; + + if (!silc_hash_table_count(cache->id_table)) + return FALSE; + + silc_hash_table_find_foreach(cache->id_table, id, + silc_idcache_get_all_foreach, ret_list); + + if (!silc_list_count(*ret_list)) + return FALSE; + + return TRUE; +} + +/* Find one specific ID entry. Compare full IDs */ + +SilcBool silc_idcache_find_by_id_one(SilcIDCache cache, void *id, + SilcIDCacheEntry *ret) +{ + return silc_hash_table_find_ext(cache->id_table, id, NULL, (void *)ret, + NULL, NULL, + silc_hash_id_compare_full, + SILC_32_TO_PTR(cache->id_type)); +} + +/* Finds cache entry by context. */ + +SilcBool silc_idcache_find_by_context(SilcIDCache cache, void *context, + SilcIDCacheEntry *ret) +{ + return silc_hash_table_find(cache->context_table, context, NULL, + (void *)ret); +} + +/* Find ID Cache entry by name. Returns list of cache entries. */ + +SilcBool silc_idcache_find_by_name(SilcIDCache cache, char *name, + SilcList *ret_list) +{ + if (!ret_list) + return FALSE; + + if (!silc_hash_table_count(cache->name_table)) + return FALSE; + + silc_hash_table_find_foreach(cache->name_table, name, + silc_idcache_get_all_foreach, ret_list); + + if (!silc_list_count(*ret_list)) + return FALSE; + + return TRUE; +} + +/* Find ID Cache entry by name. Returns one cache entry. */ + +SilcBool silc_idcache_find_by_name_one(SilcIDCache cache, char *name, + SilcIDCacheEntry *ret) +{ + return silc_hash_table_find(cache->name_table, name, NULL, (void *)ret); +} diff --git a/lib/silcutil/silcidcache.h b/lib/silcutil/silcidcache.h new file mode 100644 index 00000000..7b84e7bc --- /dev/null +++ b/lib/silcutil/silcidcache.h @@ -0,0 +1,332 @@ +/* + + silcidcache.h + + Author: Pekka Riikonen + + Copyright (C) 2000 - 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 + the Free Software Foundation; version 2 of the License. + + This program 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 General Public License for more details. + +*/ + +/****h* silccore/SILC ID Cache Interface + * + * DESCRIPTION + * + * SILC ID Cache is an cache for all kinds of ID's used in the SILC + * protocol. Application can save here the ID's it uses and the interface + * provides fast retrieval of the ID's from the cache. + * + ***/ + +#ifndef SILCIDCACHE_H +#define SILCIDCACHE_H + +/****s* silccore/SilcIDCacheAPI/SilcIDCacheEntry + * + * NAME + * + * typedef struct SilcIDCacheEntryStruct { ... } SilcIDCacheEntry; + * + * DESCRIPTION + * + * This is an entry in the SILC ID Cache system. This context is + * allocated by adding new entry to ID cache by calling silc_idcache_add. + * Each of the fields in the structure are allocated by the caller. + * + * SOURCE + */ +typedef struct SilcIDCacheEntryStruct { + struct SilcIDCacheEntryStruct *next; + void *id; /* Associated ID */ + char *name; /* Associated entry name */ + void *context; /* Associated context */ +} *SilcIDCacheEntry; +/***/ + +/****s* silccore/SilcIDCacheAPI/SilcIDCache + * + * NAME + * + * typedef struct SilcIDCacheStruct *SilcIDCache; + * + * DESCRIPTION + * + * This context is the actual ID Cache and is allocated by + * silc_idcache_alloc and given as argument usually to all + * silc_idcache_* functions. It is freed by the + * silc_idcache_free function. + * + ***/ +typedef struct SilcIDCacheStruct *SilcIDCache; + +/****f* silccore/SilcIDCacheAPI/SilcIDCacheDestructor + * + * SYNOPSIS + * + * typedef void (*SilcIDCacheDestructor)(SilcIDCache cache, + * const SilcIDCacheEntry entry, + * void *destructor_context, + * void *app_context); + * + * DESCRIPTION + * + * Destructor callback given as argument to silc_idcache_alloc. This + * is called when an entry is deleted from the cache. Application + * must free the contents of the `entry'. + * + ***/ +typedef void (*SilcIDCacheDestructor)(SilcIDCache cache, + const SilcIDCacheEntry entry, + void *destructor_context, + void *app_context); + +/* Prototypes */ + +/****f* silccore/SilcIDCacheAPI/silc_idcache_alloc + * + * SYNOPSIS + * + * SilcIDCache silc_idcache_alloc(SilcUInt32 count, SilcIdType id_type, + * SilcIDCacheDestructor destructor, + * void *destructor_context, + * SilcBool delete_id, SilcBool delete_name); + * + * DESCRIPTION + * + * Allocates new ID cache object. The initial amount of allocated entries + * can be sent as argument. If `count' is 0 the system uses default values. + * The `id_type' defines the types of the ID's that will be saved to the + * cache. + * + ***/ +SilcIDCache silc_idcache_alloc(SilcUInt32 count, SilcIdType id_type, + SilcIDCacheDestructor destructor, + void *destructor_context); + +/****f* silccore/SilcIDCacheAPI/silc_idcache_free + * + * SYNOPSIS + * + * void silc_idcache_free(SilcIDCache cache); + * + * DESCRIPTION + * + * Frees ID cache context and all cache entries. + * + ***/ +void silc_idcache_free(SilcIDCache cache); + +/****f* silccore/SilcIDCacheAPI/silc_idcache_add + * + * SYNOPSIS + * + * SilcIDCacheEntry + * silc_idcache_add(SilcIDCache cache, char *name, void *id, void *context); + * + * DESCRIPTION + * + * Add new entry to the cache. Returns the allocated cache entry if the + * entry was added successfully, or NULL if error occurred. The `name' is + * the name associated with the ID, the `id' the actual ID and the + * `context' a caller specific context. + * + * The `name', `id' and `context' pointers will be stored in the cache, + * and if the caller frees these pointers the caller is also responsible + * of deleting the cache entry. + * + ***/ +SilcIDCacheEntry +silc_idcache_add(SilcIDCache cache, char *name, void *id, void *context); + +/****f* silccore/SilcIDCacheAPI/silc_idcache_del + * + * SYNOPSIS + * + * SilcBool silc_idcache_del(SilcIDCache cache, SilcIDCacheEntry entry, + * void *app_context); + * + * DESCRIPTION + * + * Delete cache entry from cache. Returns TRUE if the entry was deleted. + * The destructor will be called for the entry. The `app_context' is + * delivered to the destructor. + * + ***/ +SilcBool silc_idcache_del(SilcIDCache cache, SilcIDCacheEntry entry, + void *app_context); + +/****f* silccore/SilcIDCacheAPI/silc_idcache_del_by_id + * + * SYNOPSIS + * + * SilcBool silc_idcache_del_by_id(SilcIDCache cache, void *id, + * void *app_context); + * + * DESCRIPTION + * + * Delete cache entry by ID. Returns TRUE if the entry was deleted. + * The destructor will be called for the entry. The `app_context' is + * delivered to the destructor. + * + ***/ +SilcBool silc_idcache_del_by_id(SilcIDCache cache, void *id, + void *app_context); + +/****f* silccore/SilcIDCacheAPI/silc_idcache_del_by_context + * + * SYNOPSIS + * + * SilcBool silc_idcache_del_by_context(SilcIDCache cache, void *context); + * + * DESCRIPTION + * + * Deletes cachen entry by the user specified context. Returns TRUE + * if the entry was deleted. The destructor will be called for the + * entry. The `app_context' is delivered to the destructor. + * + ***/ +SilcBool silc_idcache_del_by_context(SilcIDCache cache, void *context, + void *app_context); + +/****f* silccore/SilcIDCacheAPI/silc_idcache_update_id + * + * SYNOPSIS + * + * SilcBool silc_idcache_update(SilcIDCache cache, SilcIDCacheEntry entry, + * void *old_id, void *new_id, + * char *old_name, char *new_name); + * + * DESCRIPTION + * + * Updates cache `entry' with new values. If the `new_id' is non-NULL + * then the new value will be copied over the old value in the `entry'. + * If the `new_name' is non-NULL then the `entry' will be updated with + * `new_name'. The caller is responsible of freeing the old name if it + * was updated with new one. The old ID value does not need to be freed + * as the new value is copied over the old value. + * + ***/ +SilcBool silc_idcache_update(SilcIDCache cache, SilcIDCacheEntry entry, + void *old_id, void *new_id, + char *old_name, char *new_name); + +/****f* silccore/SilcIDCacheAPI/silc_idcache_get_all + * + * SYNOPSIS + * + * SilcBool silc_idcache_get_all(SilcIDCache cache, SilcList *ret_list); + * + * DESCRIPTION + * + * Returns all cache entries into the SilcList `ret_list' pointer. Each + * entry in the list is SilcIDCacheEntry. Returns FALSE if the cache + * is empty. + * + ***/ +SilcBool silc_idcache_get_all(SilcIDCache cache, SilcList *ret_list); + +/****f* silccore/SilcIDCacheAPI/silc_idcache_find_by_id + * + * SYNOPSIS + * + * SilcBool silc_idcache_find_by_id(SilcIDCache cache, void *id, + * SilcList *ret_list); + * + * DESCRIPTION + * + * Find ID Cache entry by ID. This may return multiple entries. + * The entires are returned into the `ret_list' SilcList context. + * Returns TRUE if entry was found. + * + * NOTES + * + * If this function is used to find Client ID (SilcClientID), only the + * hash portion of the Client ID is compared. Use the function + * silc_idcache_find_by_id_one to find exact match for Client ID (full + * ID is compared and not only the hash). + * + * Comparing only the hash portion of Client ID allows searching of + * Client ID's by nickname, because the hash is based on the nickname. + * As nicknames are not unique, multiple entries may be found. + * + ***/ +SilcBool silc_idcache_find_by_id(SilcIDCache cache, void *id, + SilcList *ret_list); + +/****f* silccore/SilcIDCacheAPI/silc_idcache_find_by_id_one + * + * SYNOPSIS + * + * SilcBool silc_idcache_find_by_id_one(SilcIDCache cache, void *id, + * SilcIDCacheEntry *ret); + * + * DESCRIPTION + * + * Find ID Cache entry by ID. Returns only one entry from the cache + * and the found entry is considered to be exact match. Returns TRUE + * if the entry was found. + * + ***/ +SilcBool silc_idcache_find_by_id_one(SilcIDCache cache, void *id, + SilcIDCacheEntry *ret); + +/****f* silccore/SilcIDCacheAPI/silc_idcache_find_by_context + * + * SYNOPSIS + * + * SilcBool silc_idcache_find_by_context(SilcIDCache cache, void *context, + * SilcIDCacheEntry *ret); + * + * DESCRIPTION + * + * Find cache entry by user specified context. Returns TRUE if the + * entry was found. + * + ***/ +SilcBool silc_idcache_find_by_context(SilcIDCache cache, void *context, + SilcIDCacheEntry *ret); + +/****f* silccore/SilcIDCacheAPI/silc_idcache_find_by_name + * + * SYNOPSIS + * + * SilcBool silc_idcache_find_by_name(SilcIDCache cache, char *name, + * SilcList *ret_list); + * + * DESCRIPTION + * + * Find cache entries by the name associated with the ID. This may + * return multiple entries to the `ret_list' SilcList context. Returns + * TRUE if the entry was found. + * + ***/ +SilcBool silc_idcache_find_by_name(SilcIDCache cache, char *name, + SilcList *ret_list); + +/****f* silccore/SilcIDCacheAPI/silc_idcache_find_by_name_one + * + * SYNOPSIS + * + * SilcBool silc_idcache_find_by_name_one(SilcIDCache cache, char *name, + * SilcIDCacheEntry *ret); + * + * DESCRIPTION + * + * Find cache entry by the name associated with the ID. This returns + * one entry and the found entry is considered to be exact match. + * Returns TRUE if the entry was found. + * + ***/ +SilcBool silc_idcache_find_by_name_one(SilcIDCache cache, char *name, + SilcIDCacheEntry *ret); + +#endif /* SILCIDCACHE_H */ diff --git a/lib/silcutil/silcnet.h b/lib/silcutil/silcnet.h index 41a357e9..005ff82b 100644 --- a/lib/silcutil/silcnet.h +++ b/lib/silcutil/silcnet.h @@ -87,19 +87,17 @@ typedef enum { * * DESCRIPTION * - * A callback of this type is returned by silc_net_tcp_create_listener, - * silc_net_udp_create_listener, silc_net_tcp_connect and - * silc_net_udp_connect functions. For silc_net_tcp_create_listener - * and silc_net_udp_create_listener this callback means that new incoming - * connection was accepted, and the `stream' is the socket stream - * representing the socket connection. - * - * For silc_net_tcp_connect and silc_net_udp_connect this means that we - * have connected to the remote host and the `stream' is the socket - * stream for the socket connection. The SILC Stream API (such as - * silc_stream_read, etc.) can be used to read and write to the stream. - * The created stream is socket stream so various SilcSocketStream API - * functions can be used with the `stream'. + * A callback of this type is returned by silc_net_tcp_create_listener + * and silc_net_tcp_connect functions. For silc_net_tcp_create_listener + * this callback means that new incoming connection was accepted, and the + * `stream' is the socket stream representing the socket connection. + * + * For silc_net_tcp_connect this means that we have connected to the + * remote host and the `stream' is the socket stream for the socket + * connection. The SILC Stream API (such as silc_stream_read, etc.) can + * be used to read and write to the stream. The created stream is socket + * stream so various SilcSocketStream API functions can be used with + * the `stream'. * ***/ typedef void (*SilcNetCallback)(SilcNetStatus status, @@ -196,10 +194,11 @@ SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr, * DESCRIPTION * * This function creates UDP stream. The UDP stream is bound to the - * `local_ip_addr' if it is specified. The `local_port' must always be - * specified. If the `remote_ip_addr' and `remote_port' is also provided, - * packets may be sent to that address using silc_stream_write function - * and packets may be received using silc_stream_read function. + * `local_ip_addr' if it is specified. If `local_port' is non-zero the + * stream is bound to that port. If the `remote_ip_addr' and `remote_port' + * is also provided, packets may be sent to that address using + * silc_stream_write function and packets may be received using + * silc_stream_read function. * * If the remote address is not provided then packets may only be received * by using silc_net_udp_receive and sent only by using the function @@ -224,10 +223,9 @@ SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr, * silc_stream_write(udpstream, data, data_len); * ***/ -SilcStream -silc_net_udp_connect(const char *local_ip_addr, int local_port, - const char *remote_ip_addr, int remote_port, - SilcSchedule schedule); +SilcStream silc_net_udp_connect(const char *local_ip_addr, int local_port, + const char *remote_ip_addr, int remote_port, + SilcSchedule schedule); /****f* silcutil/SilcNetAPI/silc_net_udp_receive * diff --git a/lib/silcutil/unix/silcunixnet.c b/lib/silcutil/unix/silcunixnet.c index c6a020d7..7bb5b6c5 100644 --- a/lib/silcutil/unix/silcunixnet.c +++ b/lib/silcutil/unix/silcunixnet.c @@ -252,7 +252,7 @@ silc_net_udp_connect(const char *local_ip_addr, int local_port, SILC_LOG_DEBUG(("Creating UDP stream")); - if (local_port < 1 || !schedule) + if (!schedule) goto err; /* Bind to local addresses */