struct csel * csel_create (const char *strategy, const char *params, occupy_func occupy, free_func free) { struct csel *cs; int i = 0; if (strategy && *strategy) { for (; i < (sizeof(strategies) / sizeof(struct strategy)); ++i) { if (!strcasecmp(strategies[i].name, strategy)) break; } if (i == (sizeof(strategies) / sizeof(struct strategy))) { ast_log(LOG_WARNING, "csel: unknown strategy: %s, falling back to: %s\n", strategy, strategies[0].name); i = 0; } } cs = calloc(1, sizeof(struct csel)); cs->occupy = occupy; cs->m = &strategies[i]; if (cs->m->init(cs, params)) { free(cs); return NULL; } ast_mutex_init(&cs->lock); ast_module_ref(ast_module_info->self); return cs; }
int ooh323c_start_call_thread(ooCallData *call) { char c = 'c'; struct callthread *cur = callThreads; ast_mutex_lock(&callThreadsLock); while (cur != NULL && (cur->inUse || ast_mutex_trylock(&cur->lock))) { cur = cur->next; } ast_mutex_unlock(&callThreadsLock); if (cur != NULL) { if (cur->inUse || write(cur->thePipe[1], &c, 1) < 0) { ast_mutex_unlock(&cur->lock); cur = NULL; } } /* make new thread */ if (cur == NULL) { if (!(cur = ast_calloc(1, sizeof(struct callthread)))) { ast_log(LOG_ERROR, "Unable to allocate thread structure for call %s\n", call->callToken); return -1; } ast_module_ref(myself); if ((socketpair(PF_LOCAL, SOCK_STREAM, 0, cur->thePipe)) == -1) { ast_log(LOG_ERROR, "Can't create thread pipe for call %s\n", call->callToken); ast_free(cur); return -1; } cur->inUse = TRUE; cur->call = call; ast_mutex_init(&cur->lock); if (gH323Debug) ast_debug(1,"new call thread created for call %s\n", call->callToken); if(ast_pthread_create_detached_background(&call->callThread, NULL, ooh323c_call_thread, cur) < 0) { ast_log(LOG_ERROR, "Unable to start ooh323c call thread for call %s\n", call->callToken); ast_mutex_destroy(&cur->lock); close(cur->thePipe[0]); close(cur->thePipe[1]); ast_free(cur); return -1; } } else { if (gH323Debug) ast_debug(1,"using existing call thread for call %s\n", call->callToken); cur->inUse = TRUE; cur->call = call; ast_mutex_unlock(&cur->lock); } return 0; }
static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel *chan) { struct ast_datastore *datastore = NULL; struct mixmonitor_ds *mixmonitor_ds; if (!(mixmonitor_ds = ast_calloc(1, sizeof(*mixmonitor_ds)))) { return -1; } ast_mutex_init(&mixmonitor_ds->lock); ast_cond_init(&mixmonitor_ds->destruction_condition, NULL); if (!(datastore = ast_datastore_alloc(&mixmonitor_ds_info, NULL))) { ast_mutex_destroy(&mixmonitor_ds->lock); ast_cond_destroy(&mixmonitor_ds->destruction_condition); ast_free(mixmonitor_ds); return -1; } /* No need to lock mixmonitor_ds since this is still operating in the channel's thread */ mixmonitor_ds->chan = chan; mixmonitor_ds->audiohook = &mixmonitor->audiohook; datastore->data = mixmonitor_ds; ast_channel_lock(chan); ast_channel_datastore_add(chan, datastore); ast_channel_unlock(chan); mixmonitor->mixmonitor_ds = mixmonitor_ds; return 0; }
/*! \brief Called when we want to place a call somewhere, but not actually call it... yet */ static struct ast_channel *bridge_request(const char *type, int format, void *data, int *cause) { struct bridge_pvt *p = NULL; /* Try to allocate memory for our very minimal pvt structure */ if (!(p = ast_calloc(1, sizeof(*p)))) { return NULL; } /* Try to grab two Asterisk channels to use as input and output channels */ if (!(p->input = ast_channel_alloc(1, AST_STATE_UP, 0, 0, "", "", "", 0, "Bridge/%p-input", p))) { ast_free(p); return NULL; } if (!(p->output = ast_channel_alloc(1, AST_STATE_UP, 0, 0, "", "", "", 0, "Bridge/%p-output", p))) { ast_channel_free(p->input); ast_free(p); return NULL; } /* Setup the lock on the pvt structure, we will need that */ ast_mutex_init(&p->lock); /* Setup parameters on both new channels */ p->input->tech = p->output->tech = &bridge_tech; p->input->tech_pvt = p->output->tech_pvt = p; p->input->nativeformats = p->output->nativeformats = AST_FORMAT_SLINEAR; p->input->readformat = p->output->readformat = AST_FORMAT_SLINEAR; p->input->rawreadformat = p->output->rawreadformat = AST_FORMAT_SLINEAR; p->input->writeformat = p->output->writeformat = AST_FORMAT_SLINEAR; p->input->rawwriteformat = p->output->rawwriteformat = AST_FORMAT_SLINEAR; return p->input; }
static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel *chan, char **datastore_id) { struct ast_datastore *datastore = NULL; struct mixmonitor_ds *mixmonitor_ds; if (!(mixmonitor_ds = ast_calloc(1, sizeof(*mixmonitor_ds)))) { return -1; } if (ast_asprintf(datastore_id, "%p", mixmonitor_ds) == -1) { ast_log(LOG_ERROR, "Failed to allocate memory for MixMonitor ID.\n"); } ast_mutex_init(&mixmonitor_ds->lock); ast_cond_init(&mixmonitor_ds->destruction_condition, NULL); if (!(datastore = ast_datastore_alloc(&mixmonitor_ds_info, *datastore_id))) { ast_mutex_destroy(&mixmonitor_ds->lock); ast_cond_destroy(&mixmonitor_ds->destruction_condition); ast_free(mixmonitor_ds); return -1; } mixmonitor_ds->samp_rate = 8000; mixmonitor_ds->audiohook = &mixmonitor->audiohook; datastore->data = mixmonitor_ds; ast_channel_lock(chan); ast_channel_datastore_add(chan, datastore); ast_channel_unlock(chan); mixmonitor->mixmonitor_ds = mixmonitor_ds; return 0; }
struct ast_tcptls_session_instance *ast_tcptls_client_create(struct ast_tcptls_session_args *desc) { int x = 1; struct ast_tcptls_session_instance *tcptls_session = NULL; /* Do nothing if nothing has changed */ if (!ast_sockaddr_cmp(&desc->old_address, &desc->remote_address)) { ast_debug(1, "Nothing changed in %s\n", desc->name); return NULL; } /* If we return early, there is no connection */ ast_sockaddr_setnull(&desc->old_address); if (desc->accept_fd != -1) close(desc->accept_fd); desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->remote_address) ? AF_INET6 : AF_INET, SOCK_STREAM, IPPROTO_TCP); if (desc->accept_fd < 0) { ast_log(LOG_WARNING, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno)); return NULL; } /* if a local address was specified, bind to it so the connection will originate from the desired address */ if (!ast_sockaddr_isnull(&desc->local_address)) { setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); if (ast_bind(desc->accept_fd, &desc->local_address)) { ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n", desc->name, ast_sockaddr_stringify(&desc->local_address), strerror(errno)); goto error; } } if (!(tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor))) goto error; ast_mutex_init(&tcptls_session->lock); tcptls_session->client = 1; tcptls_session->fd = desc->accept_fd; tcptls_session->parent = desc; tcptls_session->parent->worker_fn = NULL; ast_sockaddr_copy(&tcptls_session->remote_address, &desc->remote_address); /* Set current info */ ast_sockaddr_copy(&desc->old_address, &desc->remote_address); return tcptls_session; error: close(desc->accept_fd); desc->accept_fd = -1; if (tcptls_session) ao2_ref(tcptls_session, -1); return NULL; }
/*! * \brief Initialize global mock resolver data. * * This must be called at the beginning of tests that use the mock resolver */ static void resolver_data_init(void) { test_resolver_data.resolve_called = 0; test_resolver_data.canceled = 0; test_resolver_data.resolution_complete = 0; ast_mutex_init(&test_resolver_data.lock); ast_cond_init(&test_resolver_data.cancel_cond, NULL); }
void *ast_json_malloc(size_t size) { struct json_mem *mem = ast_malloc(size + sizeof(*mem)); if (!mem) { return NULL; } mem->magic = JSON_MAGIC; ast_mutex_init(&mem->mutex); return mem->data; }
struct ast_tcptls_session_instance *ast_tcptls_client_create(struct ast_tcptls_session_args *desc) { int x = 1; struct ast_tcptls_session_instance *tcptls_session = NULL; /* Do nothing if nothing has changed */ if (!memcmp(&desc->old_address, &desc->remote_address, sizeof(desc->old_address))) { ast_debug(1, "Nothing changed in %s\n", desc->name); return NULL; } desc->old_address = desc->remote_address; if (desc->accept_fd != -1) close(desc->accept_fd); desc->accept_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (desc->accept_fd < 0) { ast_log(LOG_WARNING, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno)); return NULL; } /* if a local address was specified, bind to it so the connection will originate from the desired address */ if (desc->local_address.sin_family != 0) { setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); if (bind(desc->accept_fd, (struct sockaddr *) &desc->local_address, sizeof(desc->local_address))) { ast_log(LOG_ERROR, "Unable to bind %s to %s:%d: %s\n", desc->name, ast_inet_ntoa(desc->local_address.sin_addr), ntohs(desc->local_address.sin_port), strerror(errno)); goto error; } } if (!(tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor))) goto error; ast_mutex_init(&tcptls_session->lock); tcptls_session->client = 1; tcptls_session->fd = desc->accept_fd; tcptls_session->parent = desc; tcptls_session->parent->worker_fn = NULL; memcpy(&tcptls_session->remote_address, &desc->remote_address, sizeof(tcptls_session->remote_address)); return tcptls_session; error: close(desc->accept_fd); desc->accept_fd = -1; if (tcptls_session) ao2_ref(tcptls_session, -1); return NULL; }
static int load_module(void) { ast_mutex_init(&args.lock); args.stun_sock = -1; if (__reload(1)) { ast_mutex_destroy(&args.lock); return AST_MODULE_LOAD_DECLINE; } return AST_MODULE_LOAD_SUCCESS; }
static int init_timing_thread(void) { ast_mutex_init(&timing_thread.lock); ast_cond_init(&timing_thread.cond, NULL); if (ast_pthread_create_background(&timing_thread.thread, NULL, do_timing, NULL)) { ast_log(LOG_ERROR, "Unable to start timing thread.\n"); return -1; } return 0; }
int initContext (OOCTXT* pctxt) { memset (pctxt, 0, sizeof(OOCTXT)); memHeapCreate (&pctxt->pTypeMemHeap); pctxt->pMsgMemHeap = pctxt->pTypeMemHeap; memHeapAddRef (&pctxt->pMsgMemHeap); ast_mutex_init(&pctxt->pLock); return ASN_OK; }
static struct recurring_data *recurring_data_alloc(void) { struct recurring_data *rdata; rdata = ao2_alloc(sizeof(*rdata), recurring_data_destructor); if (!rdata) { return NULL; } ast_mutex_init(&rdata->lock); ast_cond_init(&rdata->cond, NULL); return rdata; }
void *ast_tcptls_server_root(void *data) { struct ast_tcptls_session_args *desc = data; int fd; struct ast_sockaddr addr; struct ast_tcptls_session_instance *tcptls_session; pthread_t launched; for (;;) { int i, flags; if (desc->periodic_fn) desc->periodic_fn(desc); i = ast_wait_for_input(desc->accept_fd, desc->poll_timeout); if (i <= 0) continue; fd = ast_accept(desc->accept_fd, &addr); if (fd < 0) { if ((errno != EAGAIN) && (errno != EINTR)) ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno)); continue; } tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor); if (!tcptls_session) { ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno)); if (close(fd)) { ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno)); } continue; } ast_mutex_init(&tcptls_session->lock); flags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); tcptls_session->fd = fd; tcptls_session->parent = desc; ast_sockaddr_copy(&tcptls_session->remote_address, &addr); tcptls_session->client = 0; /* This thread is now the only place that controls the single ref to tcptls_session */ if (ast_pthread_create_detached_background(&launched, NULL, handle_tcptls_connection, tcptls_session)) { ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno)); ast_tcptls_close_session_file(tcptls_session); ao2_ref(tcptls_session, -1); } } return NULL; }
/*! * \brief Allocate and initialize a new worker thread * * This will create, initialize, and start the thread. * * \param pool The threadpool to which the worker will be added * \retval NULL Failed to allocate or start the worker thread * \retval non-NULL The newly-created worker thread */ static struct worker_thread *worker_thread_alloc(struct ast_threadpool *pool) { struct worker_thread *worker = ao2_alloc(sizeof(*worker), worker_thread_destroy); if (!worker) { return NULL; } worker->id = ast_atomic_fetchadd_int(&worker_id_counter, 1); ast_mutex_init(&worker->lock); ast_cond_init(&worker->cond, NULL); worker->pool = pool; worker->thread = AST_PTHREADT_NULL; worker->state = ALIVE; worker->options = pool->options; return worker; }
static struct shutdown_data *shutdown_data_create(int dont_wait) { RAII_VAR(struct shutdown_data *, shutdown_data, NULL, ao2_cleanup); shutdown_data = ao2_alloc(sizeof(*shutdown_data), shutdown_data_dtor); if (!shutdown_data) { return NULL; } ast_mutex_init(&shutdown_data->lock); ast_cond_init(&shutdown_data->in, NULL); ast_cond_init(&shutdown_data->out, NULL); shutdown_data->task_stop_waiting = dont_wait; ao2_ref(shutdown_data, +1); return shutdown_data; }
int ooCreateCmdConnection() { int ret = 0; int thePipe[2]; if ((ret = pipe(thePipe)) == -1) { return OO_FAILED; } ast_mutex_init(&gCmdChanLock); gH323ep.cmdSock = dup(thePipe[0]); close(thePipe[0]); gCmdChan = dup(thePipe[1]); close(thePipe[1]); return OO_OK; }
/*! \brief Create a task_data object */ static struct task_data *task_data_create(void) { struct task_data *task_data = ao2_alloc(sizeof(*task_data), task_data_dtor); if (!task_data) { return NULL; } ast_cond_init(&task_data->cond, NULL); ast_mutex_init(&task_data->lock); task_data->task_complete = 0; task_data->wait_time = 0; return task_data; }
/*! * \internal \brief Dispatch a message to a subscriber * \param sub The subscriber to dispatch to * \param message The message to send * \param synchronous If non-zero, synchronize on the subscriber receiving * the message */ static void dispatch_message(struct stasis_subscription *sub, struct stasis_message *message, int synchronous) { if (!sub->mailbox) { /* Dispatch directly */ subscription_invoke(sub, message); return; } /* Bump the message for the taskprocessor push. This will get de-ref'd * by the task processor callback. */ ao2_bump(message); if (!synchronous) { if (ast_taskprocessor_push_local(sub->mailbox, dispatch_exec_async, message)) { /* Push failed; ugh. */ ast_log(LOG_ERROR, "Dropping async dispatch\n"); ao2_cleanup(message); } } else { struct sync_task_data std; ast_mutex_init(&std.lock); ast_cond_init(&std.cond, NULL); std.complete = 0; std.task_data = message; if (ast_taskprocessor_push_local(sub->mailbox, dispatch_exec_sync, &std)) { /* Push failed; ugh. */ ast_log(LOG_ERROR, "Dropping sync dispatch\n"); ao2_cleanup(message); ast_mutex_destroy(&std.lock); ast_cond_destroy(&std.cond); return; } ast_mutex_lock(&std.lock); while (!std.complete) { ast_cond_wait(&std.cond, &std.lock); } ast_mutex_unlock(&std.lock); ast_mutex_destroy(&std.lock); ast_cond_destroy(&std.cond); } }
struct sched_context *sched_context_create(void) { struct sched_context *tmp; tmp = malloc(sizeof(struct sched_context)); if (tmp) { memset(tmp, 0, sizeof(struct sched_context)); ast_mutex_init(&tmp->lock); tmp->eventcnt = 1; tmp->schedcnt = 0; tmp->schedq = NULL; #ifdef SCHED_MAX_CACHE tmp->schedc = NULL; tmp->schedccnt = 0; #endif } return tmp; }
static struct stasis_message *caching_guarantee_create(void) { RAII_VAR(struct caching_guarantee *, guarantee, NULL, ao2_cleanup); RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); if (!(guarantee = ao2_alloc(sizeof(*guarantee), caching_guarantee_dtor))) { return NULL; } ast_mutex_init(&guarantee->lock); ast_cond_init(&guarantee->cond, NULL); if (!(msg = stasis_message_create(cache_guarantee_type(), guarantee))) { return NULL; } ao2_ref(msg, +1); return msg; }
int ast_sem_init(struct ast_sem *sem, int pshared, unsigned int value) { if (pshared) { /* Don't need it... yet */ errno = ENOSYS; return -1; } /* Since value is unsigned, this will also catch attempts to init with * a negative value */ if (value > AST_SEM_VALUE_MAX) { errno = EINVAL; return -1; } sem->count = value; sem->waiters = 0; ast_mutex_init(&sem->mutex); ast_cond_init(&sem->cond, NULL); return 0; }
static int load_module(void) { ast_mutex_init(&root_handler_lock); /* root_handler may have been built during a declined load */ if (!root_handler) { root_handler = root_handler_create(); } if (!root_handler) { return AST_MODULE_LOAD_FAILURE; } /* oom_json may have been built during a declined load */ if (!oom_json) { oom_json = ast_json_pack( "{s: s}", "error", "Allocation failed"); } if (!oom_json) { /* Ironic */ return AST_MODULE_LOAD_FAILURE; } if (ast_ari_config_init() != 0) { return AST_MODULE_LOAD_DECLINE; } if (is_enabled()) { ast_debug(3, "ARI enabled\n"); ast_http_uri_link(&http_uri); } else { ast_debug(3, "ARI disabled\n"); } if (ast_ari_cli_register() != 0) { return AST_MODULE_LOAD_FAILURE; } return AST_MODULE_LOAD_SUCCESS; }
int ooCreateCallCmdConnection(OOH323CallData* call) { int ret = 0; int thePipe[2]; OOTRACEINFO2("INFO: create cmd connect for call: %lx\n", call); call->CmdChanLock = malloc(sizeof(ast_mutex_t)); ast_mutex_init(call->CmdChanLock); if ((ret = socketpair(PF_LOCAL, SOCK_STREAM, 0, thePipe)) == -1) { ast_mutex_destroy(call->CmdChanLock); free(call->CmdChanLock); call->CmdChanLock = NULL; return OO_FAILED; } ast_mutex_lock(call->CmdChanLock); call->cmdSock = thePipe[0]; call->CmdChan = thePipe[1]; ast_mutex_unlock(call->CmdChanLock); return OO_OK; }
int ooH323EpInitialize (enum OOCallMode callMode, const char* tracefile) { memset(&gH323ep, 0, sizeof(ooEndPoint)); initContext(&(gH323ep.ctxt)); initContext(&(gH323ep.msgctxt)); if(tracefile) { if(strlen(tracefile)>= MAXFILENAME) { printf("Error:File name longer than allowed maximum %d\n", MAXFILENAME-1); return OO_FAILED; } strcpy(gH323ep.traceFile, tracefile); } else{ strcpy(gH323ep.traceFile, DEFAULT_TRACEFILE); } gH323ep.fptraceFile = fopen(gH323ep.traceFile, "a"); if(gH323ep.fptraceFile == NULL) { printf("Error:Failed to open trace file %s for write.\n", gH323ep.traceFile); return OO_FAILED; } /* Initialize default port ranges that will be used by stack. Apps can override these by explicitely setting port ranges */ gH323ep.tcpPorts.start = TCPPORTSSTART; gH323ep.tcpPorts.max = TCPPORTSEND; gH323ep.tcpPorts.current=TCPPORTSSTART; gH323ep.udpPorts.start = UDPPORTSSTART; gH323ep.udpPorts.max = UDPPORTSEND; gH323ep.udpPorts.current = UDPPORTSSTART; gH323ep.rtpPorts.start = RTPPORTSSTART; gH323ep.rtpPorts.max = RTPPORTSEND; gH323ep.rtpPorts.current = RTPPORTSSTART; OO_SETFLAG(gH323ep.flags, OO_M_FASTSTART); OO_SETFLAG(gH323ep.flags, OO_M_TUNNELING); OO_SETFLAG(gH323ep.flags, OO_M_AUTOANSWER); OO_CLRFLAG(gH323ep.flags, OO_M_GKROUTED); gH323ep.aliases = NULL; gH323ep.termType = DEFAULT_TERMTYPE; gH323ep.t35CountryCode = DEFAULT_T35COUNTRYCODE; gH323ep.t35Extension = DEFAULT_T35EXTENSION; gH323ep.manufacturerCode = DEFAULT_MANUFACTURERCODE; gH323ep.productID = DEFAULT_PRODUCTID; gH323ep.versionID = OOH323C_VERSION; gH323ep.callType = T_H225CallType_pointToPoint; ooGetLocalIPAddress(gH323ep.signallingIP); gH323ep.listenPort = DEFAULT_H323PORT; gH323ep.listener = NULL; ooH323EpSetCallerID(DEFAULT_CALLERID); gH323ep.myCaps = NULL; gH323ep.noOfCaps = 0; gH323ep.callList = NULL; ast_mutex_init(&monitorLock); ast_mutex_init(&callListLock); ast_mutex_init(&newCallLock); ast_mutex_init(&bindPortLock); gH323ep.dtmfmode = 0; gH323ep.callingPartyNumber[0]='\0'; gH323ep.callMode = callMode; gH323ep.isGateway = FALSE; dListInit(&g_TimerList);/* This is for test application chansetup only*/ gH323ep.callEstablishmentTimeout = DEFAULT_CALLESTB_TIMEOUT; gH323ep.msdTimeout = DEFAULT_MSD_TIMEOUT; gH323ep.tcsTimeout = DEFAULT_TCS_TIMEOUT; gH323ep.logicalChannelTimeout = DEFAULT_LOGICALCHAN_TIMEOUT; gH323ep.sessionTimeout = DEFAULT_ENDSESSION_TIMEOUT; gH323ep.ifList = NULL; ooSetTraceThreshold(OOTRCLVLINFO); OO_SETFLAG(gH323ep.flags, OO_M_ENDPOINTCREATED); gH323ep.cmdSock = 0; return OO_OK; }
static struct timespec make_deadline(int timeout_millis) { struct timeval start = ast_tvnow(); struct timeval delta = { .tv_sec = timeout_millis / 1000, .tv_usec = (timeout_millis % 1000) * 1000, }; struct timeval deadline_tv = ast_tvadd(start, delta); struct timespec deadline = { .tv_sec = deadline_tv.tv_sec, .tv_nsec = 1000 * deadline_tv.tv_usec, }; return deadline; } struct stasis_message_sink *stasis_message_sink_create(void) { RAII_VAR(struct stasis_message_sink *, sink, NULL, ao2_cleanup); sink = ao2_alloc(sizeof(*sink), stasis_message_sink_dtor); if (!sink) { return NULL; } ast_mutex_init(&sink->lock); ast_cond_init(&sink->cond, NULL); sink->max_messages = 4; sink->messages = ast_malloc(sizeof(*sink->messages) * sink->max_messages); if (!sink->messages) { return NULL; } ao2_ref(sink, +1); return sink; } /*! * \brief Implementation of the stasis_message_sink_cb() callback. * * Why the roundabout way of exposing this via stasis_message_sink_cb()? Well, * it has to do with how we load modules. * * Modules have their own metadata compiled into them in the module info block * at the end of the file. This includes dependency information in the * \c nonoptreq field. * * Asterisk loads the module, inspects the field, then loads any needed * dependencies. This works because Asterisk passes \c RTLD_LAZY to the initial * dlopen(), which defers binding function references until they are called. * * But when you take the address of a function, that function needs to be * available at load time. So if some module used the address of * message_sink_cb() directly, and \c res_stasis_test.so wasn't loaded yet, then * that module would fail to load. * * The stasis_message_sink_cb() function gives us a layer of indirection so that * the initial lazy binding will still work as expected. */ static void message_sink_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message) { struct stasis_message_sink *sink = data; SCOPED_MUTEX(lock, &sink->lock); if (stasis_subscription_final_message(sub, message)) { sink->is_done = 1; ast_cond_signal(&sink->cond); return; } if (stasis_subscription_change_type() == stasis_message_type(message)) { /* Ignore subscription changes */ return; } if (sink->num_messages == sink->max_messages) { size_t new_max_messages = sink->max_messages * 2; struct stasis_message **new_messages = ast_realloc( sink->messages, sizeof(*new_messages) * new_max_messages); if (!new_messages) { return; } sink->max_messages = new_max_messages; sink->messages = new_messages; } ao2_ref(message, +1); sink->messages[sink->num_messages++] = message; ast_cond_signal(&sink->cond); } stasis_subscription_cb stasis_message_sink_cb(void) { return message_sink_cb; } int stasis_message_sink_wait_for_count(struct stasis_message_sink *sink, int num_messages, int timeout_millis) { struct timespec deadline = make_deadline(timeout_millis); SCOPED_MUTEX(lock, &sink->lock); while (sink->num_messages < num_messages) { int r = ast_cond_timedwait(&sink->cond, &sink->lock, &deadline); if (r == ETIMEDOUT) { break; } if (r != 0) { ast_log(LOG_ERROR, "Unexpected condition error: %s\n", strerror(r)); break; } } return sink->num_messages; } int stasis_message_sink_should_stay(struct stasis_message_sink *sink, int num_messages, int timeout_millis) { struct timespec deadline = make_deadline(timeout_millis); SCOPED_MUTEX(lock, &sink->lock); while (sink->num_messages == num_messages) { int r = ast_cond_timedwait(&sink->cond, &sink->lock, &deadline); if (r == ETIMEDOUT) { break; } if (r != 0) { ast_log(LOG_ERROR, "Unexpected condition error: %s\n", strerror(r)); break; } } return sink->num_messages; } int stasis_message_sink_wait_for(struct stasis_message_sink *sink, int start, stasis_wait_cb cmp_cb, const void *data, int timeout_millis) { struct timespec deadline = make_deadline(timeout_millis); SCOPED_MUTEX(lock, &sink->lock); /* wait for the start */ while (sink->num_messages < start + 1) { int r = ast_cond_timedwait(&sink->cond, &sink->lock, &deadline); if (r == ETIMEDOUT) { /* Timed out waiting for the start */ return -1; } if (r != 0) { ast_log(LOG_ERROR, "Unexpected condition error: %s\n", strerror(r)); return -2; } } while (!cmp_cb(sink->messages[start], data)) { ++start; while (sink->num_messages < start + 1) { int r = ast_cond_timedwait(&sink->cond, &sink->lock, &deadline); if (r == ETIMEDOUT) { return -1; } if (r != 0) { ast_log(LOG_ERROR, "Unexpected condition error: %s\n", strerror(r)); return -2; } } } return start; } struct stasis_message *stasis_test_message_create(void) { RAII_VAR(void *, data, NULL, ao2_cleanup); if (!stasis_test_message_type()) { return NULL; } /* We just need the unique pointer; don't care what's in it */ data = ao2_alloc(1, NULL); if (!data) { return NULL; } return stasis_message_create(stasis_test_message_type(), data); }
/* * Helper thread to periodically poll the video source and enqueue the * generated frames to the channel's queue. * Using a separate thread also helps because the encoding can be * computationally expensive so we don't want to starve the main thread. */ static void *video_thread(void *arg) { struct video_desc *env = arg; int count = 0; char save_display[128] = ""; /* if sdl_videodriver is set, override the environment. Also, * if it contains 'console' override DISPLAY around the call to SDL_Init * so we use the console as opposed to the x11 version of aalib */ if (!ast_strlen_zero(env->sdl_videodriver)) { /* override */ const char *s = getenv("DISPLAY"); setenv("SDL_VIDEODRIVER", env->sdl_videodriver, 1); if (s && !strcasecmp(env->sdl_videodriver, "aalib-console")) { ast_copy_string(save_display, s, sizeof(save_display)); unsetenv("DISPLAY"); } } sdl_setup(env); if (!ast_strlen_zero(save_display)) setenv("DISPLAY", save_display, 1); /* initialize grab coordinates */ env->out.loc_src_geometry.x = 0; env->out.loc_src_geometry.y = 0; ast_mutex_init(&env->dec_lock); /* used to sync decoder and renderer */ if (grabber_open(&env->out)) { ast_log(LOG_WARNING, "cannot open local video source\n"); } else { #if 0 /* In principle, try to register the fd. * In practice, many webcam drivers do not support select/poll, * so don't bother and instead read periodically from the * video thread. */ if (env->out.fd >= 0) ast_channel_set_fd(env->owner, 1, env->out.fd); #endif video_out_init(env); } for (;;) { struct timeval t = { 0, 50000 }; /* XXX 20 times/sec */ struct ast_frame *p, *f; struct ast_channel *chan; int fd; char *caption = NULL, buf[160]; /* determine if video format changed */ if (count++ % 10 == 0) { if (env->out.sendvideo) sprintf(buf, "%s %s %dx%d @@ %dfps %dkbps", env->out.videodevice, env->codec_name, env->enc_in.w, env->enc_in.h, env->out.fps, env->out.bitrate/1000); else sprintf(buf, "hold"); caption = buf; } /* manage keypad events */ /* XXX here we should always check for events, * otherwise the drag will not work */ if (env->gui) eventhandler(env, caption); /* sleep for a while */ ast_select(0, NULL, NULL, NULL, &t); if (env->in) { struct video_dec_desc *v = env->in; /* * While there is something to display, call the decoder and free * the buffer, possibly enabling the receiver to store new data. */ while (v->dec_in_dpy) { struct fbuf_t *tmp = v->dec_in_dpy; /* store current pointer */ if (v->d_callbacks->dec_run(v, tmp)) show_frame(env, WIN_REMOTE); tmp->used = 0; /* mark buffer as free */ tmp->ebit = 0; ast_mutex_lock(&env->dec_lock); if (++v->dec_in_dpy == &v->dec_in[N_DEC_IN]) /* advance to next, circular */ v->dec_in_dpy = &v->dec_in[0]; if (v->dec_in_cur == NULL) /* receiver was idle, enable it... */ v->dec_in_cur = tmp; /* using the slot just freed */ else if (v->dec_in_dpy == v->dec_in_cur) /* this was the last slot */ v->dec_in_dpy = NULL; /* nothing more to display */ ast_mutex_unlock(&env->dec_lock); } } if (env->shutdown) break; f = get_video_frames(env, &p); /* read and display */ if (!f) continue; chan = env->owner; if (chan == NULL) continue; fd = chan->alertpipe[1]; ast_channel_lock(chan); /* AST_LIST_INSERT_TAIL is only good for one frame, cannot use here */ if (chan->readq.first == NULL) { chan->readq.first = f; } else { chan->readq.last->frame_list.next = f; } chan->readq.last = p; /* * more or less same as ast_queue_frame, but extra * write on the alertpipe to signal frames. */ if (fd > -1) { int blah = 1, l = sizeof(blah); for (p = f; p; p = AST_LIST_NEXT(p, frame_list)) { if (write(fd, &blah, l) != l) ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d: %s!\n", chan->name, f->frametype, f->subclass, strerror(errno)); } } ast_channel_unlock(chan); } /* thread terminating, here could call the uninit */ /* uninitialize the local and remote video environments */ env->in = dec_uninit(env->in); video_out_uninit(env); if (env->gui) env->gui = cleanup_sdl(env->gui); ast_mutex_destroy(&env->dec_lock); env->shutdown = 0; return NULL; }
static int scheduler(struct ast_test *test, int serialized) { RAII_VAR(struct ast_taskprocessor *, tp1, NULL, ast_taskprocessor_unreference); RAII_VAR(struct test_data *, test_data1, ao2_alloc(sizeof(*test_data1), data_cleanup), ao2_cleanup); RAII_VAR(struct test_data *, test_data2, ao2_alloc(sizeof(*test_data2), data_cleanup), ao2_cleanup); RAII_VAR(struct ast_sip_sched_task *, task1, NULL, ao2_cleanup); RAII_VAR(struct ast_sip_sched_task *, task2, NULL, ao2_cleanup); int duration; int delay; struct timeval task1_start; ast_test_validate(test, test_data1 != NULL); ast_test_validate(test, test_data2 != NULL); test_data1->test = test; test_data1->test_start = ast_tvnow(); test_data1->interval = 2000; test_data1->sleep = 1000; ast_mutex_init(&test_data1->lock); ast_cond_init(&test_data1->cond, NULL); test_data2->test = test; test_data2->test_start = ast_tvnow(); test_data2->interval = 2000; test_data2->sleep = 1000; ast_mutex_init(&test_data2->lock); ast_cond_init(&test_data2->cond, NULL); if (serialized) { ast_test_status_update(test, "This test will take about %3.1f seconds\n", (test_data1->interval + test_data1->sleep + (MAX(test_data1->interval - test_data2->interval, 0)) + test_data2->sleep) / 1000.0); tp1 = ast_sip_create_serializer("test-scheduler-serializer"); ast_test_validate(test, (tp1 != NULL)); } else { ast_test_status_update(test, "This test will take about %3.1f seconds\n", ((MAX(test_data1->interval, test_data2->interval) + MAX(test_data1->sleep, test_data2->sleep)) / 1000.0)); } task1 = ast_sip_schedule_task(tp1, test_data1->interval, task_1, NULL, test_data1, AST_SIP_SCHED_TASK_FIXED); ast_test_validate(test, task1 != NULL); task2 = ast_sip_schedule_task(tp1, test_data2->interval, task_1, NULL, test_data2, AST_SIP_SCHED_TASK_FIXED); ast_test_validate(test, task2 != NULL); waitfor(test_data1); ast_sip_sched_task_cancel(task1); ast_test_validate(test, test_data1->is_servant); duration = ast_tvdiff_ms(test_data1->task_end, test_data1->test_start); ast_test_validate(test, (duration > ((test_data1->interval + test_data1->sleep) * 0.9)) && (duration < ((test_data1->interval + test_data1->sleep) * 1.1))); ast_sip_sched_task_get_times(task1, NULL, &task1_start, NULL); delay = ast_tvdiff_ms(task1_start, test_data1->test_start); ast_test_validate(test, (delay > (test_data1->interval * 0.9) && (delay < (test_data1->interval * 1.1)))); waitfor(test_data2); ast_sip_sched_task_cancel(task2); ast_test_validate(test, test_data2->is_servant); if (serialized) { ast_test_validate(test, test_data1->tid == test_data2->tid); ast_test_validate(test, ast_tvdiff_ms(test_data2->task_start, test_data1->task_end) >= 0); } else { ast_test_validate(test, test_data1->tid != test_data2->tid); } return AST_TEST_PASS; }
/* * Helper thread to periodically poll the video sources and enqueue the * generated frames directed to the remote party to the channel's queue. * Using a separate thread also helps because the encoding can be * computationally expensive so we don't want to starve the main thread. */ static void *video_thread(void *arg) { struct video_desc *env = arg; int count = 0; char save_display[128] = ""; int i; /* integer variable used as iterator */ /* if sdl_videodriver is set, override the environment. Also, * if it contains 'console' override DISPLAY around the call to SDL_Init * so we use the console as opposed to the x11 version of aalib */ if (!ast_strlen_zero(env->sdl_videodriver)) { /* override */ const char *s = getenv("DISPLAY"); setenv("SDL_VIDEODRIVER", env->sdl_videodriver, 1); if (s && !strcasecmp(env->sdl_videodriver, "aalib-console")) { ast_copy_string(save_display, s, sizeof(save_display)); unsetenv("DISPLAY"); } } sdl_setup(env); if (!ast_strlen_zero(save_display)) { setenv("DISPLAY", save_display, 1); } ast_mutex_init(&env->dec_lock); /* used to sync decoder and renderer */ if (grabber_open(&env->out)) { ast_log(LOG_WARNING, "cannot open local video source\n"); } if (env->out.device_num) { env->out.devices[env->out.device_primary].status_index |= IS_PRIMARY | IS_SECONDARY; } /* even if no device is connected, we must call video_out_init, * as some of the data structures it initializes are * used in get_video_frames() */ video_out_init(env); /* Writes intial status of the sources. */ if (env->gui) { for (i = 0; i < env->out.device_num; i++) { print_message(env->gui->thumb_bd_array[i].board, src_msgs[env->out.devices[i].status_index]); } } for (;;) { struct timespec t = { 0, 50000000 }; /* XXX 20 times/sec */ struct ast_frame *p, *f; struct ast_channel *chan; int fd; char *caption = NULL, buf[160]; /* determine if video format changed */ if (count++ % 10 == 0) { if (env->out.sendvideo && env->out.devices) { snprintf(buf, sizeof(buf), "%s %s %dx%d @@ %dfps %dkbps", env->out.devices[env->out.device_primary].name, env->codec_name, env->enc_in.w, env->enc_in.h, env->out.fps, env->out.bitrate / 1000); } else { sprintf(buf, "hold"); } caption = buf; } /* manage keypad events */ /* XXX here we should always check for events, * otherwise the drag will not work */ if (env->gui) eventhandler(env, caption); /* sleep for a while */ nanosleep(&t, NULL); if (env->in) { struct video_dec_desc *v = env->in; /* * While there is something to display, call the decoder and free * the buffer, possibly enabling the receiver to store new data. */ while (v->dec_in_dpy) { struct fbuf_t *tmp = v->dec_in_dpy; /* store current pointer */ /* decode the frame, but show it only if not frozen */ if (v->d_callbacks->dec_run(v, tmp) && !env->frame_freeze) show_frame(env, WIN_REMOTE); tmp->used = 0; /* mark buffer as free */ tmp->ebit = 0; ast_mutex_lock(&env->dec_lock); if (++v->dec_in_dpy == &v->dec_in[N_DEC_IN]) /* advance to next, circular */ v->dec_in_dpy = &v->dec_in[0]; if (v->dec_in_cur == NULL) /* receiver was idle, enable it... */ v->dec_in_cur = tmp; /* using the slot just freed */ else if (v->dec_in_dpy == v->dec_in_cur) /* this was the last slot */ v->dec_in_dpy = NULL; /* nothing more to display */ ast_mutex_unlock(&env->dec_lock); } } if (env->shutdown) break; f = get_video_frames(env, &p); /* read and display */ if (!f) continue; chan = env->owner; if (chan == NULL) { /* drop the chain of frames, nobody uses them */ while (f) { struct ast_frame *g = AST_LIST_NEXT(f, frame_list); ast_frfree(f); f = g; } continue; } fd = chan->alertpipe[1]; ast_channel_lock(chan); /* AST_LIST_INSERT_TAIL is only good for one frame, cannot use here */ if (chan->readq.first == NULL) { chan->readq.first = f; } else { chan->readq.last->frame_list.next = f; } chan->readq.last = p; /* * more or less same as ast_queue_frame, but extra * write on the alertpipe to signal frames. */ if (fd > -1) { int blah = 1, l = sizeof(blah); for (p = f; p; p = AST_LIST_NEXT(p, frame_list)) { if (write(fd, &blah, l) != l) ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d: %s!\n", chan->name, f->frametype, f->subclass, strerror(errno)); } } ast_channel_unlock(chan); } /* thread terminating, here could call the uninit */ /* uninitialize the local and remote video environments */ env->in = dec_uninit(env->in); video_out_uninit(env); if (env->gui) env->gui = cleanup_sdl(env->gui, env->out.device_num); ast_mutex_destroy(&env->dec_lock); env->shutdown = 0; return NULL; }
OOH323CallData* ooCreateCall(char* type, char*callToken) { OOH323CallData *call=NULL; OOCTXT *pctxt=NULL; OOCTXT *msgctxt=NULL; pctxt = newContext(); if(!pctxt) { OOTRACEERR1("ERROR:Failed to create OOCTXT for new call\n"); return NULL; } msgctxt = newContext(); if(!msgctxt) { OOTRACEERR1("ERROR:Failed to create OOCTXT for new call\n"); return NULL; } ast_mutex_lock(&newCallLock); /* call = (OOH323CallData*)memAlloc(&gH323ep.ctxt, sizeof(OOH323CallData)); */ call = (OOH323CallData*)memAlloc(pctxt, sizeof(OOH323CallData)); ast_mutex_unlock(&newCallLock); if(!call) { OOTRACEERR1("ERROR:Memory - ooCreateCall - call\n"); return NULL; } memset(call, 0, sizeof(OOH323CallData)); ast_cond_init(&call->gkWait, NULL); ast_mutex_init(&call->GkLock); ast_mutex_init(&call->Lock); call->pctxt = pctxt; call->msgctxt = msgctxt; call->callMode = gH323ep.callMode; sprintf(call->callToken, "%s", callToken); sprintf(call->callType, "%s", type); call->callReference = 0; if(gH323ep.callerid) { strncpy(call->ourCallerId, gH323ep.callerid, sizeof(call->ourCallerId)-1); call->ourCallerId[sizeof(call->ourCallerId)-1] = '\0'; } else { call->ourCallerId[0] = '\0'; } memset(&call->callIdentifier, 0, sizeof(H225CallIdentifier)); memset(&call->confIdentifier, 0, sizeof(H225ConferenceIdentifier)); call->flags = 0; if (OO_TESTFLAG(gH323ep.flags, OO_M_TUNNELING)) OO_SETFLAG (call->flags, OO_M_TUNNELING); if(gH323ep.gkClient) { if(OO_TESTFLAG(gH323ep.flags, OO_M_GKROUTED)) { OO_SETFLAG(call->flags, OO_M_GKROUTED); } } if (OO_TESTFLAG(gH323ep.flags, OO_M_FASTSTART)) OO_SETFLAG (call->flags, OO_M_FASTSTART); if (OO_TESTFLAG(gH323ep.flags, OO_M_MEDIAWAITFORCONN)) OO_SETFLAG (call->flags, OO_M_MEDIAWAITFORCONN); call->fsSent = FALSE; // May 20090713. Fix it for Video session OO_SETFLAG(call->flags, OO_M_AUDIOSESSION); call->callState = OO_CALL_CREATED; call->callEndReason = OO_REASON_UNKNOWN; call->pCallFwdData = NULL; if(!strcmp(call->callType, "incoming")) { call->callingPartyNumber = NULL; } else{ if(ooUtilsIsStrEmpty(gH323ep.callingPartyNumber)) { call->callingPartyNumber = NULL; } else{ call->callingPartyNumber = (char*) memAlloc(call->pctxt, strlen(gH323ep.callingPartyNumber)+1); if(call->callingPartyNumber) { strcpy(call->callingPartyNumber, gH323ep.callingPartyNumber); } else{ OOTRACEERR3("Error:Memory - ooCreateCall - callingPartyNumber" ".(%s, %s)\n", call->callType, call->callToken); freeContext(pctxt); return NULL; } } } call->calledPartyNumber = NULL; call->h245ConnectionAttempts = 0; call->h245SessionState = OO_H245SESSION_IDLE; call->dtmfmode = gH323ep.dtmfmode; call->mediaInfo = NULL; strcpy(call->localIP, gH323ep.signallingIP); call->pH225Channel = NULL; call->pH245Channel = NULL; call->h245listener = NULL; call->h245listenport = NULL; call->remoteIP[0] = '\0'; call->remotePort = 0; call->remoteH245Port = 0; call->remoteDisplayName = NULL; call->remoteAliases = NULL; call->ourAliases = NULL; call->masterSlaveState = OO_MasterSlave_Idle; call->statusDeterminationNumber = 0; call->localTermCapState = OO_LocalTermCapExchange_Idle; call->remoteTermCapState = OO_RemoteTermCapExchange_Idle; call->ourCaps = NULL; call->remoteCaps = NULL; call->jointCaps = NULL; dListInit(&call->remoteFastStartOLCs); call->remoteTermCapSeqNo =0; call->localTermCapSeqNo = 0; memcpy(&call->capPrefs, &gH323ep.capPrefs, sizeof(OOCapPrefs)); call->logicalChans = NULL; call->noOfLogicalChannels = 0; call->logicalChanNoBase = 1001; call->logicalChanNoMax = 1100; call->logicalChanNoCur = 1001; call->nextSessionID = 4; /* 1,2,3 are reserved for audio, video and data */ dListInit(&call->timerList); call->msdRetries = 0; call->pFastStartRes = NULL; call->usrData = NULL; OOTRACEINFO3("Created a new call (%s, %s)\n", call->callType, call->callToken); /* Add new call to calllist */ ooAddCallToList (call); if(gH323ep.h323Callbacks.onNewCallCreated) gH323ep.h323Callbacks.onNewCallCreated(call); return call; }