Changeset 1098:f38d77f9cfd3 in freeDiameter for libfdcore
- Timestamp:
- May 9, 2013, 12:59:34 PM (11 years ago)
- Branch:
- default
- Phase:
- public
- Location:
- libfdcore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
libfdcore/cnxctx.c
r1084 r1098 736 736 } 737 737 738 // fd_msg_log(....) 739 738 740 /* We have received a complete message, pass it to the daemon */ 739 741 CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, length, newmsg), /* continue or destroy everything? */); -
libfdcore/core.c
r1085 r1098 187 187 188 188 /* Initialize some modules */ 189 CHECK_FCT( fd_hooks_init() ); 189 190 CHECK_FCT( fd_queues_init() ); 190 191 CHECK_FCT( fd_msg_init() ); -
libfdcore/fdcore-internal.h
r1085 r1098 363 363 #define FD_CNX_ORDERED (1 << 0) /* All messages sent with this flag set will be delivered in the same order. No guarantee on other messages */ 364 364 365 /* Internal calls of the hook mechanism */ 366 void fd_hook_call(enum fd_hook_type type, struct msg * msg, struct fd_peer * peer, void * other, struct fd_msg_pmdl * pmdl); 367 void fd_hook_associate(struct msg * msg, struct fd_msg_pmdl * pmdl); 368 int fd_hooks_init(void); 365 369 #endif /* _FDCORE_INTERNAL_H */ -
libfdcore/hooks.c
r1077 r1098 36 36 #include "fdcore-internal.h" 37 37 38 struct fd_hook_hdl; 39 struct fd_hook_data_hdl; 40 38 /* Structures for the fd_hook_data_hdl management */ 39 static struct fd_hook_data_hdl { 40 size_t pmd_size; 41 void (*pmd_init_cb)(struct fd_hook_permsgdata *); 42 void (*pmd_fini_cb)(struct fd_hook_permsgdata *); 43 } HDH_array[FD_HOOK_HANDLE_LIMIT]; 44 static int max_index = 0; 45 static pthread_mutex_t HDH_lock = PTHREAD_MUTEX_INITIALIZER; 46 47 /* The structure linked from the msg structure list */ 48 struct pmd_list_item { 49 struct fd_list chain; /* this list is ordered by hdl */ 50 struct fd_hook_data_hdl * hdl; 51 struct fd_hook_permsgdata { } pmd; /* this data belongs to the extension; we only know the size of it */ 52 }; 53 54 #define sizeof_pmd(hdl) (((size_t)&((struct pmd_list_item *)0)->pmd) + hdl->pmd_size) 55 56 /* Now a hook registered by an extension */ 57 struct fd_hook_hdl { 58 struct fd_list chain[HOOK_PEER_LAST+1]; 59 void (*fd_hook_cb)(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata); 60 void *regdata; 61 struct fd_hook_data_hdl *data_hdl; 62 }; 63 64 /* Array of those hooks */ 65 struct { 66 struct fd_list sentinel; 67 pthread_rwlock_t rwlock; 68 } HS_array[HOOK_PEER_LAST+1]; 69 70 /* Initialize the array of sentinels for the hooks */ 71 int fd_hooks_init(void) 72 { 73 int i; 74 for (i=0; i <= HOOK_PEER_LAST; i++) { 75 fd_list_init(&HS_array[i].sentinel, NULL); 76 CHECK_POSIX( pthread_rwlock_init(&HS_array[i].rwlock, NULL) ); 77 } 78 return 0; 79 } 80 81 /* Get a slot in the array */ 41 82 int fd_hook_data_register( 42 struct fd_hook_permsgdata * (*permsgdata_new_cb) (void), 43 void (*permsgdata_destroy_cb) (struct fd_hook_permsgdata *), 44 struct fd_hook_data_hdl ** new_handle 45 ) 46 { 47 return ENOTSUP; 48 } 49 50 int fd_hook_register ( enum fd_hook_type type, 51 void (*fd_hook_cb)(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, void * regdata), 52 void * regdata, 83 size_t permsgdata_size, 84 void (*permsgdata_init_cb) (struct fd_hook_permsgdata *), 85 void (*permsgdata_fini_cb) (struct fd_hook_permsgdata *), 86 struct fd_hook_data_hdl **new_handle) 87 { 88 int ret = ENOSPC, idx; 89 TRACE_ENTRY("%zd %p %p %p", permsgdata_size, permsgdata_init_cb, permsgdata_fini_cb, new_handle); 90 91 CHECK_PARAMS( permsgdata_size && new_handle ); 92 93 CHECK_POSIX( pthread_mutex_lock(&HDH_lock) ); 94 if (max_index < FD_HOOK_HANDLE_LIMIT) { 95 idx = max_index++; 96 ret = 0; 97 } 98 CHECK_POSIX( pthread_mutex_unlock(&HDH_lock) ); 99 100 if (ret == 0) { 101 HDH_array[idx].pmd_size = permsgdata_size; 102 HDH_array[idx].pmd_init_cb = permsgdata_init_cb; 103 HDH_array[idx].pmd_fini_cb = permsgdata_fini_cb; 104 *new_handle = &HDH_array[idx]; 105 } 106 107 return ret; 108 } 109 110 /* Register a new hook callback */ 111 int fd_hook_register ( uint32_t type_mask, 112 void (*fd_hook_cb)(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata), 113 void *regdata, 53 114 struct fd_hook_data_hdl *data_hdl, 54 115 struct fd_hook_hdl ** handler ) 55 116 { 56 return ENOTSUP; 57 } 58 59 117 struct fd_hook_hdl * newhdl = NULL; 118 int i; 119 120 TRACE_ENTRY("%x %p %p %p %p", type_mask, fd_hook_cb, regdata, data_hdl, handler); 121 122 CHECK_PARAMS( fd_hook_cb && handler ); 123 124 CHECK_MALLOC( newhdl = malloc(sizeof(struct fd_hook_hdl)) ); 125 memset(newhdl, 0, sizeof(struct fd_hook_hdl)); 126 127 newhdl->fd_hook_cb = fd_hook_cb; 128 newhdl->regdata = regdata; 129 newhdl->data_hdl = data_hdl; 130 131 for (i=0; i <= HOOK_PEER_LAST; i++) { 132 fd_list_init(&newhdl->chain[i], newhdl); 133 if (type_mask & (1<<i)) { 134 CHECK_POSIX( pthread_rwlock_wrlock(&HS_array[i].rwlock) ); 135 fd_list_insert_before( &HS_array[i].sentinel, &newhdl->chain[i]); 136 CHECK_POSIX( pthread_rwlock_unlock(&HS_array[i].rwlock) ); 137 } 138 } 139 140 *handler = newhdl; 141 return 0; 142 } 143 144 /* free this hook callback */ 60 145 int fd_hook_unregister( struct fd_hook_hdl * handler ) 61 146 { 62 return ENOTSUP; 63 } 64 147 int i; 148 TRACE_ENTRY("%p", handler); 149 CHECK_PARAMS( handler ); 150 151 for (i=0; i <= HOOK_PEER_LAST; i++) { 152 if ( ! FD_IS_LIST_EMPTY(&handler->chain[i])) { 153 CHECK_POSIX( pthread_rwlock_wrlock(&HS_array[i].rwlock) ); 154 fd_list_unlink(&handler->chain[i]); 155 CHECK_POSIX( pthread_rwlock_unlock(&HS_array[i].rwlock) ); 156 } 157 } 158 159 free(handler); 160 161 return 0; 162 } 163 164 /* callback for the libfdproto to free the data associated with a message */ 165 static void pmdl_free(struct fd_msg_pmdl *pmdl) 166 { 167 /* destroy all the items in the list */ 168 while (!FD_IS_LIST_EMPTY(&pmdl->sentinel)) { 169 struct pmd_list_item * li = (struct pmd_list_item *)(pmdl->sentinel.next); 170 if (li->hdl->pmd_fini_cb) { 171 (*li->hdl->pmd_fini_cb)(&li->pmd); 172 } 173 fd_list_unlink(&li->chain); 174 free(li); 175 } 176 CHECK_POSIX_DO( pthread_mutex_destroy(&pmdl->lock), ); 177 pmdl->sentinel.o = NULL; 178 } 179 180 /* Save the list of pmd into the message structure, as well as the callback to free this list */ 181 void fd_hook_associate(struct msg * msg, struct fd_msg_pmdl * pmdl) 182 { 183 struct fd_msg_pmdl * in_msg; 184 185 CHECK_PARAMS_DO( msg && pmdl, return ); 186 in_msg = fd_msg_pmdl_get(msg); 187 ASSERT(in_msg && (in_msg->sentinel.o == NULL)); /* error / already initialized ??? */ 188 fd_list_init(&in_msg->sentinel, pmdl_free); 189 CHECK_POSIX_DO( pthread_mutex_init(&in_msg->lock, NULL), ); 190 /* Now move all items from the pmdl pointer into the initialized list */ 191 CHECK_POSIX_DO( pthread_mutex_lock(&pmdl->lock), ); 192 fd_list_move_end(&in_msg->sentinel, &pmdl->sentinel); 193 CHECK_POSIX_DO( pthread_mutex_unlock(&pmdl->lock), ); 194 pmdl_free(pmdl); 195 /* We're done */ 196 } 197 198 /* Return the location of the permsgdata area corresponding to this handle, after eventually having created it. Return NULL in case of failure */ 199 static struct fd_hook_permsgdata * get_or_create_pmd(struct fd_msg_pmdl *pmdl, struct fd_hook_hdl * h) 200 { 201 struct fd_hook_permsgdata * ret = NULL; 202 struct fd_list * li; 203 CHECK_POSIX_DO( pthread_mutex_lock(&pmdl->lock), ); 204 205 /* Search in the list for an item with the same handle. The list is ordered by this handle */ 206 for (li=pmdl->sentinel.next; li != &pmdl->sentinel; li = li->next) { 207 struct pmd_list_item * pli = (struct pmd_list_item *) li; 208 if (pli->hdl == h->data_hdl) 209 ret = &pli->pmd; 210 if (pli->hdl >= h->data_hdl) 211 break; 212 } 213 if (!ret) { 214 /* we need to create a new one and insert before li */ 215 struct pmd_list_item * pli; 216 CHECK_MALLOC_DO( pli = malloc(sizeof_pmd(h->data_hdl)), ); 217 if (pli) { 218 memset(pli, 0, sizeof_pmd(h->data_hdl)); 219 fd_list_init(&pli->chain, pli); 220 pli->hdl = h->data_hdl; 221 ret = &pli->pmd; 222 if (h->data_hdl->pmd_init_cb) { 223 (*h->data_hdl->pmd_init_cb)(ret); 224 } 225 fd_list_insert_before(li, &pli->chain); 226 } 227 } 228 229 CHECK_POSIX_DO( pthread_mutex_unlock(&pmdl->lock), ); 230 return ret; 231 } 232 233 234 /* The function that does the work of calling the extension's callbacks and also managing the permessagedata structures */ 235 void fd_hook_call(enum fd_hook_type type, struct msg * msg, struct fd_peer * peer, void * other, struct fd_msg_pmdl * pmdl) 236 { 237 struct fd_list * li; 238 ASSERT(type <= HOOK_PEER_LAST); 239 240 /* lock the list of hooks for this type */ 241 CHECK_POSIX_DO( pthread_rwlock_rdlock(&HS_array[type].rwlock), ); 242 243 /* for each registered hook */ 244 for (li = HS_array[type].sentinel.next; li != &HS_array[type].sentinel; li = li->next) { 245 struct fd_hook_hdl * h = (struct fd_hook_hdl *)li->o; 246 struct fd_hook_permsgdata * pmd = NULL; 247 248 /* do we need to handle pmd ? */ 249 if (h->data_hdl && pmdl) { 250 pmd = get_or_create_pmd(pmdl, h); 251 } 252 253 /* Now, call this callback */ 254 (*h->fd_hook_cb)(type, msg, &peer->p_hdr, other, pmd, h->regdata); 255 } 256 257 /* done */ 258 CHECK_POSIX_DO( pthread_rwlock_unlock(&HS_array[type].rwlock), ); 259 }
Note: See TracChangeset
for help on using the changeset viewer.