static void *SWITCH_THREAD_FUNC limit_remote_thread(switch_thread_t *thread, void *obj) { limit_remote_t *remote = (limit_remote_t*)obj; while (remote->state > REMOTE_OFF) { if (remote->state != REMOTE_UP) { if (esl_connect_timeout(&remote->handle, remote->host, remote->port, remote->username, remote->password, 5000) == ESL_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected to remote FreeSWITCH (%s) at %s:%d\n", remote->name, remote->host, remote->port); remote->state = REMOTE_UP; } else { esl_disconnect(&remote->handle); memset(&remote->handle, 0, sizeof(remote->handle)); } } else { if (esl_send_recv_timed(&remote->handle, "api hash_dump limit", 5000) != ESL_SUCCESS) { esl_disconnect(&remote->handle); memset(&remote->handle, 0, sizeof(remote->handle)); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Disconnected from remote FreeSWITCH (%s) at %s:%d\n", remote->name, remote->host, remote->port); memset(&remote->handle, 0, sizeof(remote->handle)); remote->state = REMOTE_DOWN; /* Delete all remote tracking entries */ switch_thread_rwlock_wrlock(remote->rwlock); switch_core_hash_delete_multi(remote->index, limit_hash_remote_cleanup_callback, NULL); switch_thread_rwlock_unlock(remote->rwlock); } else { if (!zstr(remote->handle.last_sr_event->body)) { char *data = strdup(remote->handle.last_sr_event->body); char *p = data, *p2; switch_time_t now = switch_epoch_time_now(NULL); while (p && *p) { /* We are getting the limit data as: L/key/usage/rate/interval/last_checked */ if ((p2 = strchr(p, '\n'))) { *p2++ = '\0'; } /* Now p points at the beginning of the current line, p2 at the start of the next one */ if (*p == 'L') { /* Limit data */ char *argv[5]; int argc = switch_split(p+2, '/', argv); if (argc < 5) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "[%s] Protocol error: missing argument in line: %s\n", remote->name, p); } else { limit_hash_item_t *item; switch_thread_rwlock_wrlock(remote->rwlock); if (!(item = switch_core_hash_find(remote->index, argv[0]))) { item = malloc(sizeof(*item)); switch_core_hash_insert(remote->index, argv[0], item); } item->total_usage = atoi(argv[1]); item->rate_usage = atoi(argv[2]); item->interval = atoi(argv[3]); item->last_check = atoi(argv[4]); item->last_update = now; switch_thread_rwlock_unlock(remote->rwlock); } } p = p2; } free(data); /* Now free up anything that wasn't in this update since it means their usage is 0 */ switch_thread_rwlock_wrlock(remote->rwlock); switch_core_hash_delete_multi(remote->index, limit_hash_remote_cleanup_callback, (void*)(intptr_t)now); switch_thread_rwlock_unlock(remote->rwlock); } } } switch_yield(remote->interval * 1000); } remote->thread = NULL; return NULL; }
static switch_status_t handle_msg_atom(listener_t *listener, erlang_msg * msg, ei_x_buff * buf, ei_x_buff * rbuf) { char atom[MAXATOMLEN]; switch_status_t ret = SWITCH_STATUS_SUCCESS; if (ei_decode_atom(buf->buff, &buf->index, atom)) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); } else if (!strncmp(atom, "nolog", MAXATOMLEN)) { if (switch_test_flag(listener, LFLAG_LOG)) { void *pop; /*purge the log queue */ while (switch_queue_trypop(listener->log_queue, &pop) == SWITCH_STATUS_SUCCESS); switch_clear_flag_locked(listener, LFLAG_LOG); } ei_x_encode_atom(rbuf, "ok"); } else if (!strncmp(atom, "register_log_handler", MAXATOMLEN)) { ei_link(listener, ei_self(listener->ec), &msg->from); listener->log_process.type = ERLANG_PID; memcpy(&listener->log_process.pid, &msg->from, sizeof(erlang_pid)); listener->level = SWITCH_LOG_DEBUG; switch_set_flag(listener, LFLAG_LOG); ei_x_encode_atom(rbuf, "ok"); } else if (!strncmp(atom, "register_event_handler", MAXATOMLEN)) { ei_link(listener, ei_self(listener->ec), &msg->from); listener->event_process.type = ERLANG_PID; memcpy(&listener->event_process.pid, &msg->from, sizeof(erlang_pid)); if (!switch_test_flag(listener, LFLAG_EVENTS)) { switch_set_flag_locked(listener, LFLAG_EVENTS); } ei_x_encode_atom(rbuf, "ok"); } else if (!strncmp(atom, "noevents", MAXATOMLEN)) { void *pop; /*purge the event queue */ while (switch_queue_trypop(listener->event_queue, &pop) == SWITCH_STATUS_SUCCESS); if (switch_test_flag(listener, LFLAG_EVENTS)) { uint8_t x = 0; switch_clear_flag_locked(listener, LFLAG_EVENTS); switch_thread_rwlock_wrlock(listener->event_rwlock); for (x = 0; x <= SWITCH_EVENT_ALL; x++) { listener->event_list[x] = 0; } switch_core_hash_delete_multi(listener->event_hash, NULL, NULL); switch_thread_rwlock_unlock(listener->event_rwlock); ei_x_encode_atom(rbuf, "ok"); } else { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "notlistening"); } } else if (!strncmp(atom, "session_noevents", MAXATOMLEN)) { session_elem_t *session; if ((session = find_session_elem_by_pid(listener, &msg->from))) { void *pop; uint8_t x = 0; /*purge the event queue */ while (switch_queue_trypop(session->event_queue, &pop) == SWITCH_STATUS_SUCCESS); switch_thread_rwlock_wrlock(session->event_rwlock); for (x = 0; x <= SWITCH_EVENT_ALL; x++) { session->event_list[x] = 0; } /* wipe the hash */ switch_core_hash_delete_multi(session->event_hash, NULL, NULL); switch_thread_rwlock_unlock(session->event_rwlock); ei_x_encode_atom(rbuf, "ok"); } else { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "notlistening"); } } else if (!strncmp(atom, "exit", MAXATOMLEN)) { ei_x_encode_atom(rbuf, "ok"); ret = SWITCH_STATUS_TERM; } else if (!strncmp(atom, "getpid", MAXATOMLEN)) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "ok"); ei_x_encode_pid(rbuf, ei_self(listener->ec)); } else if (!strncmp(atom, "link", MAXATOMLEN)) { /* debugging */ ei_link(listener, ei_self(listener->ec), &msg->from); ret = SWITCH_STATUS_FALSE; } else { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "undef"); } return ret; }