static int io_grow(struct io_context *ioc) { /* * Grow the size of our arrays. Return 0 on success or * -1 on failure */ void *tmp; DEBUG(ast_log(LOG_DEBUG, "io_grow()\n")); ioc->maxfdcnt += GROW_SHRINK_SIZE; if ((tmp = ast_realloc(ioc->ior, (ioc->maxfdcnt + 1) * sizeof(*ioc->ior)))) { ioc->ior = tmp; if ((tmp = ast_realloc(ioc->fds, (ioc->maxfdcnt + 1) * sizeof(*ioc->fds)))) { ioc->fds = tmp; } else { /* * Failed to allocate enough memory for the pollfd. Not * really any need to shrink back the iorec's as we'll * probably want to grow them again soon when more memory * is available, and then they'll already be the right size */ ioc->maxfdcnt -= GROW_SHRINK_SIZE; return -1; } } else { /* * Memory allocation failure. We return to the old size, and * return a failure */ ioc->maxfdcnt -= GROW_SHRINK_SIZE; return -1; } return 0; }
/*! \brief Callback from ENUM lookup function */ static int enum_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer) { struct enum_context *c = context; void *p = NULL; int res; res = parse_naptr((unsigned char *)c->dst, c->dstlen, c->tech, c->techlen, answer, len, (unsigned char *)c->naptrinput); if (res < 0) { ast_log(LOG_WARNING, "Failed to parse naptr\n"); return -1; } else if ((res == 0) && !ast_strlen_zero(c->dst)) { /* ok, we got needed NAPTR */ if (c->options & ENUMLOOKUP_OPTIONS_COUNT) { /* counting RRs */ c->count++; snprintf(c->dst, c->dstlen, "%d", c->count); } else { if ((p = ast_realloc(c->naptr_rrs, sizeof(*c->naptr_rrs) * (c->naptr_rrs_count + 1)))) { c->naptr_rrs = p; memcpy(&c->naptr_rrs[c->naptr_rrs_count].naptr, answer, sizeof(c->naptr_rrs->naptr)); c->naptr_rrs[c->naptr_rrs_count].result = ast_strdup(c->dst); c->naptr_rrs[c->naptr_rrs_count].tech = ast_strdup(c->tech); c->naptr_rrs[c->naptr_rrs_count].sort_pos = c->naptr_rrs_count; c->naptr_rrs_count++; } c->dst[0] = 0; } return 0; } return 0; }
static void *myrealloc(void *ptr, size_t size) { /* There might be a realloc() out there that doesn't like reallocing NULL pointers, so we take care of it here */ if (ptr) return ast_realloc(ptr, size); else return ast_malloc(size); }
static char *socket_receive_file_to_buff(int fd,int *size) { /* Receive file (probably a waveform file) from socket using */ /* Festival key stuff technique, but long winded I know, sorry */ /* but will receive any file without closeing the stream or */ /* using OOB data */ static char *file_stuff_key = "ft_StUfF_key"; /* must == Festival's key */ char *buff; int bufflen; int n,k,i; char c; bufflen = 1024; if (!(buff = ast_malloc(bufflen))) { /* TODO: Handle memory allocation failure */ } *size=0; for (k=0; file_stuff_key[k] != '\0';) { n = read(fd,&c,1); if (n==0) break; /* hit stream eof before end of file */ if ((*size)+k+1 >= bufflen) { /* +1 so you can add a NULL if you want */ bufflen += bufflen/4; if (!(buff = ast_realloc(buff, bufflen))) { /* TODO: Handle memory allocation failure */ } } if (file_stuff_key[k] == c) k++; else if ((c == 'X') && (file_stuff_key[k+1] == '\0')) { /* It looked like the key but wasn't */ for (i=0; i < k; i++,(*size)++) buff[*size] = file_stuff_key[i]; k=0; /* omit the stuffed 'X' */ } else { for (i=0; i < k; i++,(*size)++) buff[*size] = file_stuff_key[i]; k=0; buff[*size] = c; (*size)++; } } return buff; }
static void CB_ADD(char **comment_buffer, int *comment_buffer_size, char *str) { int rem = *comment_buffer_size - strlen(*comment_buffer) - 1; int siz = strlen(str); if (rem < siz+1) { *comment_buffer = ast_realloc(*comment_buffer, *comment_buffer_size + CB_INCR + siz + 1); if (!(*comment_buffer)) return; *comment_buffer_size += CB_INCR+siz+1; } strcat(*comment_buffer,str); }
static void CB_ADD_LEN(char **comment_buffer, int *comment_buffer_size, char *str, int len) { int cbl = strlen(*comment_buffer) + 1; int rem = *comment_buffer_size - cbl; if (rem < len+1) { *comment_buffer = ast_realloc(*comment_buffer, *comment_buffer_size + CB_INCR + len + 1); if (!(*comment_buffer)) return; *comment_buffer_size += CB_INCR+len+1; } strncat(*comment_buffer,str,len); (*comment_buffer)[cbl+len-1] = 0; }
/*! * \brief Add a row of additional storage for the heap. */ static int grow_heap(struct ast_heap *h #ifdef MALLOC_DEBUG , const char *file, int lineno, const char *func #endif ) { h->avail_len = h->avail_len * 2 + 1; if (!(h->heap = #ifdef MALLOC_DEBUG __ast_realloc(h->heap, h->avail_len * sizeof(void *), file, lineno, func) #else ast_realloc(h->heap, h->avail_len * sizeof(void *)) #endif )) { h->cur_len = h->avail_len = 0; return -1; } return 0; }
/*! * \brief Add a row of additional storage for the heap. */ static int grow_heap(struct ast_heap *h #ifdef MALLOC_DEBUG , const char *file, int lineno, const char *func #endif ) { void **new_heap; size_t new_len = h->avail_len * 2 + 1; #ifdef MALLOC_DEBUG new_heap = __ast_realloc(h->heap, new_len * sizeof(void *), file, lineno, func); #else new_heap = ast_realloc(h->heap, new_len * sizeof(void *)); #endif if (!new_heap) { return -1; } h->heap = new_heap; h->avail_len = new_len; return 0; }
static int dialgroup_refreshdb(struct ast_channel *chan, const char *cdialgroup) { int len = 500, res = 0; char *buf = NULL; char *dialgroup = ast_strdupa(cdialgroup); do { len *= 2; buf = ast_realloc(buf, len); if ((res = dialgroup_read(chan, "", dialgroup, buf, len)) < 0) { ast_free(buf); return -1; } } while (res == 1); if (ast_strlen_zero(buf)) { ast_db_del("dialgroup", cdialgroup); } else { ast_db_put("dialgroup", cdialgroup, buf); } ast_free(buf); return 0; }
int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, char **payload, uint64_t *payload_len, enum ast_websocket_opcode *opcode, int *fragmented) { char buf[MAXIMUM_FRAME_SIZE] = ""; size_t frame_size, expected = 2; *payload = NULL; *payload_len = 0; *fragmented = 0; /* We try to read in 14 bytes, which is the largest possible WebSocket header */ if ((frame_size = fread(&buf, 1, 14, session->f)) < 1) { return -1; } /* The minimum size for a WebSocket frame is 2 bytes */ if (frame_size < expected) { return -1; } *opcode = buf[0] & 0xf; if (*opcode == AST_WEBSOCKET_OPCODE_TEXT || *opcode == AST_WEBSOCKET_OPCODE_BINARY || *opcode == AST_WEBSOCKET_OPCODE_CONTINUATION || *opcode == AST_WEBSOCKET_OPCODE_PING || *opcode == AST_WEBSOCKET_OPCODE_PONG) { int fin = (buf[0] >> 7) & 1; int mask_present = (buf[1] >> 7) & 1; char *mask = NULL, *new_payload; size_t remaining; if (mask_present) { /* The mask should take up 4 bytes */ expected += 4; if (frame_size < expected) { /* Per the RFC 1009 means we received a message that was too large for us to process */ ast_websocket_close(session, 1009); return 0; } } /* Assume no extended length and no masking at the beginning */ *payload_len = buf[1] & 0x7f; *payload = &buf[2]; /* Determine if extended length is being used */ if (*payload_len == 126) { /* Use the next 2 bytes to get a uint16_t */ expected += 2; *payload += 2; if (frame_size < expected) { ast_websocket_close(session, 1009); return 0; } *payload_len = ntohs(get_unaligned_uint16(&buf[2])); } else if (*payload_len == 127) { /* Use the next 8 bytes to get a uint64_t */ expected += 8; *payload += 8; if (frame_size < expected) { ast_websocket_close(session, 1009); return 0; } *payload_len = ntohl(get_unaligned_uint64(&buf[2])); } /* If masking is present the payload currently points to the mask, so move it over 4 bytes to the actual payload */ if (mask_present) { mask = *payload; *payload += 4; } /* Determine how much payload we need to read in as we may have already read some in */ remaining = *payload_len - (frame_size - expected); /* If how much payload they want us to read in exceeds what we are capable of close the session, things * will fail no matter what most likely */ if (remaining > (MAXIMUM_FRAME_SIZE - frame_size)) { ast_websocket_close(session, 1009); return 0; } new_payload = *payload + (frame_size - expected); /* Read in the remaining payload */ while (remaining > 0) { size_t payload_read; /* Wait for data to come in */ if (ast_wait_for_input(session->fd, -1) <= 0) { *opcode = AST_WEBSOCKET_OPCODE_CLOSE; *payload = NULL; session->closing = 1; return 0; } /* If some sort of failure occurs notify the caller */ if ((payload_read = fread(new_payload, 1, remaining, session->f)) < 1) { return -1; } remaining -= payload_read; new_payload += payload_read; } /* If a mask is present unmask the payload */ if (mask_present) { unsigned int pos; for (pos = 0; pos < *payload_len; pos++) { (*payload)[pos] ^= mask[pos % 4]; } } if (!(new_payload = ast_realloc(session->payload, session->payload_len + *payload_len))) { *payload_len = 0; ast_websocket_close(session, 1009); return 0; } /* Per the RFC for PING we need to send back an opcode with the application data as received */ if (*opcode == AST_WEBSOCKET_OPCODE_PING) { ast_websocket_write(session, AST_WEBSOCKET_OPCODE_PONG, *payload, *payload_len); } session->payload = new_payload; memcpy(session->payload + session->payload_len, *payload, *payload_len); session->payload_len += *payload_len; if (!fin && session->reconstruct && (session->payload_len < session->reconstruct)) { /* If this is not a final message we need to defer returning it until later */ if (*opcode != AST_WEBSOCKET_OPCODE_CONTINUATION) { session->opcode = *opcode; } *opcode = AST_WEBSOCKET_OPCODE_CONTINUATION; *payload_len = 0; *payload = NULL; } else { if (*opcode == AST_WEBSOCKET_OPCODE_CONTINUATION) { if (!fin) { /* If this was not actually the final message tell the user it is fragmented so they can deal with it accordingly */ *fragmented = 1; } else { /* Final frame in multi-frame so push up the actual opcode */ *opcode = session->opcode; } } *payload_len = session->payload_len; *payload = session->payload; session->payload_len = 0; } } else if (*opcode == AST_WEBSOCKET_OPCODE_CLOSE) {
/* * Load module stuff */ static int ind_load_module(void) { struct ast_config *cfg; struct ast_variable *v; char *cxt; char *c; struct ind_tone_zone *tones; const char *country = NULL; /* that the following cast is needed, is yuk! */ /* yup, checked it out. It is NOT written to. */ cfg = ast_config_load((char *)config); if (!cfg) return -1; /* Use existing config to populate the Indication table */ cxt = ast_category_browse(cfg, NULL); while(cxt) { /* All categories but "general" are considered countries */ if (!strcasecmp(cxt, "general")) { cxt = ast_category_browse(cfg, cxt); continue; } if (!(tones = ast_calloc(1, sizeof(*tones)))) { ast_config_destroy(cfg); return -1; } ast_copy_string(tones->country,cxt,sizeof(tones->country)); v = ast_variable_browse(cfg, cxt); while(v) { if (!strcasecmp(v->name, "description")) { ast_copy_string(tones->description, v->value, sizeof(tones->description)); } else if ((!strcasecmp(v->name,"ringcadence"))||(!strcasecmp(v->name,"ringcadance"))) { char *ring,*rings = ast_strdupa(v->value); c = rings; ring = strsep(&c,","); while (ring) { int *tmp, val; if (!isdigit(ring[0]) || (val=atoi(ring))==-1) { ast_log(LOG_WARNING,"Invalid ringcadence given '%s' at line %d.\n",ring,v->lineno); ring = strsep(&c,","); continue; } if (!(tmp = ast_realloc(tones->ringcadence, (tones->nrringcadence + 1) * sizeof(int)))) { ast_config_destroy(cfg); return -1; } tones->ringcadence = tmp; tmp[tones->nrringcadence] = val; tones->nrringcadence++; /* next item */ ring = strsep(&c,","); } } else if (!strcasecmp(v->name,"alias")) { char *countries = ast_strdupa(v->value); c = countries; country = strsep(&c,","); while (country) { struct ind_tone_zone* azone; if (!(azone = ast_calloc(1, sizeof(*azone)))) { ast_config_destroy(cfg); return -1; } ast_copy_string(azone->country, country, sizeof(azone->country)); ast_copy_string(azone->alias, cxt, sizeof(azone->alias)); if (ast_register_indication_country(azone)) { ast_log(LOG_WARNING, "Unable to register indication alias at line %d.\n",v->lineno); free(tones); } /* next item */ country = strsep(&c,","); } } else { /* add tone to country */ struct ind_tone_zone_sound *ps,*ts; for (ps=NULL,ts=tones->tones; ts; ps=ts, ts=ts->next) { if (strcasecmp(v->name,ts->name)==0) { /* already there */ ast_log(LOG_NOTICE,"Duplicate entry '%s', skipped.\n",v->name); goto out; } } /* not there, add it to the back */ if (!(ts = ast_malloc(sizeof(*ts)))) { ast_config_destroy(cfg); return -1; } ts->next = NULL; ts->name = strdup(v->name); ts->data = strdup(v->value); if (ps) ps->next = ts; else tones->tones = ts; } out: v = v->next; } if (tones->description[0] || tones->alias[0] || tones->tones) { if (ast_register_indication_country(tones)) { ast_log(LOG_WARNING, "Unable to register indication at line %d.\n",v->lineno); free(tones); } } else free(tones); cxt = ast_category_browse(cfg, cxt); } /* determine which country is the default */ country = ast_variable_retrieve(cfg,"general","country"); if (!country || !*country || ast_set_indication_country(country)) ast_log(LOG_WARNING,"Unable to set the default country (for indication tones)\n"); ast_config_destroy(cfg); return 0; }
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); }