static evi_subs_p evi_get_subscriber(evi_event_p event, str sock_str) { evi_export_t * trans_mod; evi_subs_p subscriber = NULL; evi_reply_sock * sock; /* transport module name */ trans_mod = get_trans_mod(&sock_str); if (!trans_mod) { LM_DBG("couldn't find a protocol to support %.*s\n", sock_str.len, sock_str.s); return NULL; } sock_str.s += trans_mod->proto.len + 1; sock_str.len -= (trans_mod->proto.len + 1); /* parse reply socket */ sock = trans_mod->parse(sock_str); if (!sock) return NULL; /* tries to match other socket */ if (trans_mod->match) { lock_get(event->lock); for (subscriber = event->subscribers; subscriber; subscriber = subscriber->next) { if (subscriber->trans_mod != trans_mod) continue; if (trans_mod->match(sock, subscriber->reply_sock)) { if (trans_mod->free) trans_mod->free(sock); else shm_free(sock); break; } } lock_release(event->lock); } return subscriber; }
struct mi_root * mi_event_subscribe(struct mi_root *root, void *param ) { struct mi_node *node; evi_subs_t *subscriber = NULL; evi_event_p event; evi_export_t *trans_mod = NULL; evi_reply_sock *sock; str sock_str; unsigned int expire = 0; /* event name */ node = root->node.kids; if (!node) { LM_ERR("no parameters received\n"); goto missing_param; } event = evi_get_event(&node->value); if (!event) { LM_ERR("invalid event name <%.*s>\n", node->value.len, node->value.s); goto bad_param; } /* transport module name */ node = node->next; if (!node) { LM_ERR("no transport type\n"); goto missing_param; } trans_mod = get_trans_mod(&node->value); if (!trans_mod) { LM_ERR("couldn't find a protocol to support %.*s\n", node->value.len,node->value.s); goto bad_param; } sock_str.s = node->value.s + trans_mod->proto.len + 1; sock_str.len = node->value.len - trans_mod->proto.len - 1; /* check expire */ node = node->next; if (node) { /* expiration period is set */ if (str2int(&node->value, &expire) < 0) { LM_ERR("invalid expire value %.*s", node->value.len, node->value.s); goto bad_param; } } else expire = DEFAULT_EXPIRE; /* parse reply socket */ sock = trans_mod->parse(sock_str); if (!sock) goto bad_param; /* tries to match other socket */ if (trans_mod->match) { lock_get(event->lock); for (subscriber = event->subscribers; subscriber; subscriber = subscriber->next) { if (subscriber->trans_mod != trans_mod) continue; if (trans_mod->match(sock, subscriber->reply_sock)) { /* update subscription time */ subscriber->reply_sock->subscription_time = time(0); /* update expire if required */ if (EVI_EXPIRE & sock->flags) subscriber->reply_sock->expire = expire; if (trans_mod->free) trans_mod->free(sock); else shm_free(sock); break; } } lock_release(event->lock); } /* if no socket matches - create a new one */ if (!subscriber) { subscriber = shm_malloc(sizeof(evi_subs_t)); if (!subscriber) { LM_ERR("no more shm memory\n"); goto internal_error; } sock->subscription_time = time(0); subscriber->trans_mod = trans_mod; subscriber->reply_sock = sock; if (EVI_EXPIRE & sock->flags) subscriber->reply_sock->expire = expire; subscriber->reply_sock->flags |= trans_mod->flags; /* guard subscribers list */ lock_get(event->lock); subscriber->next = event->subscribers; event->subscribers = subscriber; lock_release(event->lock); LM_DBG("added new subscriber for event %d\n", event->id); } return init_mi_tree(200, MI_SSTR(MI_OK)); internal_error: if (trans_mod && sock) { /* if the module has it's own free function */ if (trans_mod->free) trans_mod->free(sock); else shm_free(sock); } return init_mi_tree(500, MI_SSTR(MI_INTERNAL_ERR)); missing_param: return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM)); bad_param: return init_mi_tree( 400, MI_SSTR(MI_BAD_PARM)); }
/* * Subscribes an event * Returns: * 1 - success * 0 - internal error * -1 - param error */ int evi_event_subscribe(str event_name, str sock_str, unsigned expire, unsigned unsubscribe) { evi_subs_t *subscriber = NULL; evi_event_p event; evi_export_t *trans_mod = NULL; evi_reply_sock *sock; event = evi_get_event(&event_name); if (!event) { LM_ERR("invalid event name <%.*s>\n", event_name.len, event_name.s); goto bad_param; } /* transport module name */ trans_mod = get_trans_mod(&sock_str); if (!trans_mod) { LM_ERR("couldn't find a protocol to support %.*s\n", sock_str.len, sock_str.s); goto bad_param; } sock_str.s += trans_mod->proto.len + 1; sock_str.len -= (trans_mod->proto.len + 1); /* parse reply socket */ sock = trans_mod->parse(sock_str); if (!sock) goto bad_param; /* reset unrequired flags */ if (!expire && !unsubscribe) sock->flags &= ~EVI_EXPIRE; /* tries to match other socket */ if (trans_mod->match) { lock_get(event->lock); for (subscriber = event->subscribers; subscriber; subscriber = subscriber->next) { if (subscriber->trans_mod != trans_mod) continue; if (trans_mod->match(sock, subscriber->reply_sock)) { /* update subscription time */ subscriber->reply_sock->subscription_time = time(0); /* update expire if required */ if (EVI_EXPIRE & sock->flags) { subscriber->reply_sock->expire = expire; subscriber->reply_sock->flags = sock->flags; } if (trans_mod->free) trans_mod->free(sock); else shm_free(sock); break; } } lock_release(event->lock); } /* if no socket matches - create a new one */ if (!subscriber) { subscriber = shm_malloc(sizeof(evi_subs_t)); if (!subscriber) { LM_ERR("no more shm memory\n"); if (trans_mod && sock) { /* if the module has it's own free function */ if (trans_mod->free) trans_mod->free(sock); else shm_free(sock); } return 0; } sock->subscription_time = time(0); subscriber->trans_mod = trans_mod; subscriber->reply_sock = sock; if (EVI_EXPIRE & sock->flags) subscriber->reply_sock->expire = expire; subscriber->reply_sock->flags |= trans_mod->flags; /* guard subscribers list */ lock_get(event->lock); subscriber->next = event->subscribers; event->subscribers = subscriber; lock_release(event->lock); LM_DBG("added new subscriber for event %d\n", event->id); } return 1; bad_param: return -1; }