Main Page | Data Structures | File List | Data Fields | Globals | Related Pages

connlist.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Copyright 2005 Daniel Ferullo                                             *
00003  *                                                                           *
00004  * Licensed under the Apache License, Version 2.0 (the "License");           *
00005  * you may not use this file except in compliance with the License.          *
00006  * You may obtain a copy of the License at                                   *
00007  *                                                                           *
00008  *    http://www.apache.org/licenses/LICENSE-2.0                             *
00009  *                                                                           *
00010  * Unless required by applicable law or agreed to in writing, software       *
00011  * distributed under the License is distributed on an "AS IS" BASIS,         *
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
00013  * See the License for the specific language governing permissions and       *
00014  * limitations under the License.                                            *
00015  *                                                                           *
00016  *****************************************************************************/
00017 
00018 /**
00019  * @file connlist.c
00020  * @author Daniel Ferullo (ferullo@cmu.edu)
00021  *
00022  * @brief Functions to help search and maintain the connection list.  These
00023  * functions are thread-safe.
00024  */
00025 
00026 #include "connlist.h"
00027 #include <pthread.h>
00028 #include "debug.h"
00029 
00030 #include <unistd.h>
00031 
00032 errorcode connlist_init(connlist_t *list) {
00033 
00034         CHECK_NOT_NULL(list,ERROR_NULL_ARG_1);
00035 
00036         CHECK_FAILED(list_init(&list->list),ERROR_INIT);
00037 
00038         /**
00039          * man page says return value is always 0, but I don't trust it, since the
00040          * man page for pthreads also says some functions/macros exist that
00041          * in fact do not.
00042          **/
00043         if (pthread_mutex_init(&(list->mutex),NULL)<0)
00044                 return ERROR_2;
00045 
00046         return SUCCESS;
00047 }
00048 
00049 errorcode connlist_add(connlist_t *list, connlist_item_t *item) {
00050 
00051         CHECK_NOT_NULL(list,ERROR_NULL_ARG_1);
00052         CHECK_NOT_NULL(item,ERROR_NULL_ARG_2);
00053 
00054         /* lock the mutex */
00055         DEBUG(DBG_THREAD,"THREAD:LOCKING MUTEX\n");
00056         if (pthread_mutex_lock(&(list->mutex))<0)
00057                 return ERROR_MUTEX_LOCK;
00058         DEBUG(DBG_THREAD,"THREAD:LOCKED MUTEX\n");
00059         /* the thread adding the item is a watcher by default */
00060         item->watchers = 1;
00061 
00062         /* add the item to the list */
00063         if (FAILED(list_add(&list->list,item))) {
00064                 if(pthread_mutex_unlock(&(list->mutex))<0)
00065                         return ERROR_MUTEX_UNLOCK_1;
00066                 DEBUG(DBG_THREAD,"THREAD:UNLOCKED MUTEX\n");
00067                 return ERROR_LIST_ADD;
00068         }
00069 
00070         /* unlock the mutex */
00071         DEBUG(DBG_THREAD,"THREAD:UNLOCKING MUTEX\n");
00072         if (pthread_mutex_unlock(&(list->mutex))<0)
00073                 return ERROR_MUTEX_UNLOCK_2;
00074         DEBUG(DBG_THREAD,"THREAD:UNLOCKED MUTEX\n");
00075 
00076         return SUCCESS;
00077 }
00078 
00079 errorcode connlist_find(connlist_t *list, int (*func)(void*,void*), void *arg,
00080                         connlist_item_t **found_item){
00081 
00082         /* declare local variables */
00083         connlist_item_t *cast_item;
00084 
00085         /* error check arguments */
00086         CHECK_NOT_NULL(list,ERROR_NULL_ARG_1);
00087         CHECK_NOT_NULL(func,ERROR_NULL_ARG_2);
00088         CHECK_NOT_NULL(found_item,ERROR_NULL_ARG_4);
00089 
00090         /* do function */
00091 
00092         /* lock the mutex */
00093         DEBUG(DBG_THREAD,"THREAD:LOCKING MUTEX\n");
00094         if (pthread_mutex_lock(&(list->mutex))<0)
00095                 return ERROR_MUTEX_LOCK;
00096         DEBUG(DBG_THREAD,"THREAD:LOCKED MUTEX %p\n",&(list->mutex));
00097 
00098         /* find the item in the list */
00099         if (FAILED(list_find(&list->list,func,arg,(void**)&cast_item))) {
00100                 if(pthread_mutex_unlock(&(list->mutex))<0)
00101                         return ERROR_MUTEX_UNLOCK_1;
00102                 DEBUG(DBG_THREAD,"THREAD:UNLOCKED MUTEX\n");
00103                 return ERROR_LIST_FIND;
00104         }
00105 
00106         *found_item = cast_item;
00107 
00108         /* the thread finding this item is a new watcher */
00109         cast_item->watchers += 1;
00110 
00111         /* unlock the mutex */
00112         DEBUG(DBG_THREAD,"THREAD:UNLOCKING MUTEX\n");
00113         if (pthread_mutex_unlock(&(list->mutex))<0)
00114                 return ERROR_MUTEX_UNLOCK_2;
00115         DEBUG(DBG_THREAD,"THREAD:UNLOCKED MUTEX\n");
00116 
00117         DEBUG(DBG_PORT_PRED,"PORT_PRED:found item\n");
00118         return SUCCESS;
00119 }
00120 
00121 int connlist_find_pred_port(void *this_item, void *find_item) {
00122 
00123         /* declare variables */
00124         connlist_item_t *cast_item;
00125         observed_data_t *cast_data;
00126 
00127         /* error check arguments */
00128         CHECK_NOT_NULL(find_item,LIST_FATAL);
00129         CHECK_NOT_NULL(this_item,LIST_FATAL);
00130 
00131         /* do function */
00132         cast_item = (connlist_item_t*) this_item;
00133         cast_data = (observed_data_t*) find_item;
00134 
00135         DEBUG(DBG_PORT_PRED,"PORT_PRED:item %s:%u\n",
00136                 DBG_IP(cast_item->obs_data.ip),
00137                 DBG_PORT(cast_item->obs_data.port));
00138         DEBUG(DBG_PORT_PRED,"PORT_PRED:data %s:%u\n",
00139                 DBG_IP(cast_data->ip),DBG_PORT(cast_data->port));
00140 
00141         /* check if the observed data is what is expected */
00142         if ( (cast_item->obs_data.ip == cast_data->ip) &&
00143                 (cast_item->obs_data.port == cast_data->port) )   {
00144                 DEBUG(DBG_PORT_PRED,"PORT_PRED:matched item\n");
00145                 return LIST_FOUND;
00146         }
00147 
00148         return LIST_NOT_FOUND;
00149 }
00150 
00151 int connlist_find_buddy(void *this_item, void *find_item) {
00152 
00153         /* declare local variables */
00154         connlist_item_t *cast_item;
00155         buddy_info_t    *cast_buddy;
00156 
00157         /* error check arguments */
00158         CHECK_NOT_NULL(find_item,LIST_FATAL);
00159         CHECK_NOT_NULL(this_item,LIST_FATAL);
00160 
00161         /* do function */
00162         cast_item   = (connlist_item_t*) this_item;
00163         cast_buddy  = (buddy_info_t*)    find_item;
00164 
00165         /*
00166         DEBUG(DBG_LIST,"LIST:match item\n");
00167         DEBUG(DBG_LIST," cast_buddy:\n");
00168         DEBUG(DBG_LIST,"  ext_ip...%s\n",DBG_IP(cast_buddy->ext_ip));
00169         DEBUG(DBG_LIST,"  int_ip...%s\n",DBG_IP(cast_buddy->int_ip));
00170         DEBUG(DBG_LIST,"  int_port.%u\n",DBG_PORT(cast_buddy->int_port));
00171         DEBUG(DBG_LIST," cast_item:\n");
00172         DEBUG(DBG_LIST,"  ext_ip...%s\n",DBG_IP(cast_item->obs_data.ip));
00173         DEBUG(DBG_LIST,"  int_ip...%s\n",DBG_IP(cast_item->info.peer.ip));
00174         DEBUG(DBG_LIST,"  int_port.%u\n",DBG_PORT(cast_item->info.peer.port));
00175         DEBUG(DBG_LIST,"\n");
00176         */
00177 
00178         if ( (cast_buddy->int_port==cast_item->info.peer.port) &&
00179              (cast_buddy->int_ip==cast_item->info.peer.ip)     &&
00180              (cast_buddy->ext_ip==cast_item->obs_data.ip) )     {
00181                 return LIST_FOUND;
00182         }
00183 
00184         return LIST_NOT_FOUND;
00185 }
00186 
00187 errorcode connlist_forget(connlist_t *list,
00188                           int (*func)(void*,void*), connlist_item_t *item) {
00189 
00190         /* declare variables */
00191 
00192         /* error check arguments */
00193         CHECK_NOT_NULL(list,ERROR_NULL_ARG_1);
00194         CHECK_NOT_NULL(item,ERROR_NULL_ARG_2);
00195 
00196         /* lock the mutex */
00197         DEBUG(DBG_THREAD,"THREAD:LOCKING MUTEX\n");
00198         if (pthread_mutex_lock(&(list->mutex))<0)
00199                 return ERROR_MUTEX_LOCK;
00200         DEBUG(DBG_THREAD,"THREAD:LOCKED MUTEX\n");
00201 
00202         /* decrement the number of watchers*/
00203         item->watchers -= 1;
00204 
00205         if (item->watchers == 0) {
00206                 /* remove the item to the list */
00207                 if (FAILED(list_remove(&list->list,func,item))) {
00208                         if(pthread_mutex_unlock(&(list->mutex))<0)
00209                                 return ERROR_MUTEX_UNLOCK_1;
00210                         DEBUG(DBG_THREAD,"THREAD:UNLOCKED MUTEX\n");
00211                         return ERROR_LIST_ADD;
00212                 }
00213         }
00214 
00215         /* unlock the mutex */
00216         DEBUG(DBG_THREAD,"THREAD:UNLOCKING MUTEX\n");
00217         if (pthread_mutex_unlock(&(list->mutex))<0)
00218                 return ERROR_MUTEX_UNLOCK_2;
00219         DEBUG(DBG_THREAD,"THREAD:UNLOCKED MUTEX\n");
00220         return SUCCESS;
00221 }
00222 
00223 int connlist_item_match(void *this_item, void *find_item) {
00224 
00225         /* declare variables */
00226 
00227         /* error check arguments */
00228         CHECK_NOT_NULL(this_item,LIST_FATAL);
00229         CHECK_NOT_NULL(find_item,LIST_FATAL);
00230 
00231         /* just match pointers, that is all that is necessary */
00232         if (this_item == find_item)
00233                 return LIST_FOUND;
00234 
00235         return LIST_NOT_FOUND;
00236 }
00237 
00238 int connlist_count(connlist_t *list) {
00239 
00240         /* declare variables */
00241         int count;
00242 
00243         /* error check arguments */
00244         CHECK_NOT_NULL(list,-2);
00245 
00246         /* do function */
00247         /* lock the mutex */
00248         DEBUG(DBG_THREAD,"THREAD:LOCKING MUTEX\n");
00249         if (pthread_mutex_lock(&(list->mutex))<0)
00250                 return -3;
00251         DEBUG(DBG_THREAD,"THREAD:LOCKED MUTEX\n");
00252 
00253         count = list_count(&list->list);
00254 
00255         /* unlock the mutex */
00256         DEBUG(DBG_THREAD,"THREAD:UNLOCKING MUTEX\n");
00257         if (pthread_mutex_unlock(&(list->mutex))<0)
00258                 return -4;
00259         DEBUG(DBG_THREAD,"THREAD:UNLOCKED MUTEX\n");
00260 
00261         return count;
00262 }

Generated on Wed Mar 30 23:20:47 2005 for NATBLASTER by  doxygen 1.3.9.1