Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
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) {
Ejemplo n.º 11
0
/*
 * 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;
}
Ejemplo n.º 12
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);
}