示例#1
0
char *__netsock_stringify_fmt(const struct sockaddr_storage *sockAddrStorage, int format)
{
	const struct sockaddr_storage *sockAddrStorage_tmp;
	char host[NI_MAXHOST] = "";
	char port[NI_MAXSERV] = "";
	struct ast_str *str;
	int e;
	static const size_t size = sizeof(host) - 1 + sizeof(port) - 1 + 4;

	if (!sockAddrStorage) {
		return "(null)";
	}

	if (!(str = ast_str_thread_get(&sccp_netsock_stringify_buf, size))) {
		return "";
	}
	//if (sccp_netsock_ipv4_mapped(sockAddrStorage, &sockAddrStorage_tmp_ipv4)) {
	//	struct sockaddr_storage sockAddrStorage_tmp_ipv4;
	//	sockAddrStorage_tmp = &sockAddrStorage_tmp_ipv4;
	//#if DEBUG
	//	sccp_log(0)("SCCP: ipv4 mapped in ipv6 address\n");
	//#endif
	//} else {
	sockAddrStorage_tmp = sockAddrStorage;
	//}

	if ((e = getnameinfo((struct sockaddr *) sockAddrStorage_tmp, sccp_netsock_sizeof(sockAddrStorage_tmp), format & SCCP_SOCKADDR_STR_ADDR ? host : NULL, format & SCCP_SOCKADDR_STR_ADDR ? sizeof(host) : 0, format & SCCP_SOCKADDR_STR_PORT ? port : 0, format & SCCP_SOCKADDR_STR_PORT ? sizeof(port) : 0, NI_NUMERICHOST | NI_NUMERICSERV))) {
		sccp_log(DEBUGCAT_SOCKET) (VERBOSE_PREFIX_3 "SCCP: getnameinfo(): %s \n", gai_strerror(e));
		return "";
	}

	if ((format & SCCP_SOCKADDR_STR_REMOTE) == SCCP_SOCKADDR_STR_REMOTE) {
		char *p;

		if (sccp_netsock_is_ipv6_link_local(sockAddrStorage_tmp) && (p = strchr(host, '%'))) {
			*p = '\0';
		}
	}
	switch ((format & SCCP_SOCKADDR_STR_FORMAT_MASK)) {
		case SCCP_SOCKADDR_STR_DEFAULT:
			ast_str_set(&str, 0, sockAddrStorage_tmp->ss_family == AF_INET6 ? "[%s]:%s" : "%s:%s", host, port);
			break;
		case SCCP_SOCKADDR_STR_ADDR:
			ast_str_set(&str, 0, "%s", host);
			break;
		case SCCP_SOCKADDR_STR_HOST:
			ast_str_set(&str, 0, sockAddrStorage_tmp->ss_family == AF_INET6 ? "[%s]" : "%s", host);
			break;
		case SCCP_SOCKADDR_STR_PORT:
			ast_str_set(&str, 0, "%s", port);
			break;
		default:
			pbx_log(LOG_ERROR, "Invalid format\n");
			return "";
	}

	return ast_str_buffer(str);
}
示例#2
0
/*!
 * \brief Fire an Event
 * \param event SCCP Event
 * \note event will be freed after event is fired
 * 
 * \warning
 *      - sccp_event_listeners->subscriber is not always locked
 */
void sccp_event_fire(const sccp_event_t * event)
{
	if (event == NULL || SCCP_REF_RUNNING != sccp_refcount_isRunning() || !sccp_event_running) {
		if (event) {
			sccp_event_destroy((sccp_event_t *) event);
		}
		return;
	}

	AUTO_RELEASE sccp_event_t *e = (sccp_event_t *) sccp_refcount_object_alloc(sizeof(sccp_event_t), SCCP_REF_EVENT, sccp_event_type2str(event->type), sccp_event_destroy);

	if (!e) {
		pbx_log(LOG_ERROR, "%p: Memory Allocation Error while creating sccp_event e. Exiting\n", event);
		sccp_event_destroy((sccp_event_t *) event);
		return;
	}
	// memcpy(e, event, sizeof(sccp_event_t));
	e->type = event->type;

	sccp_log((DEBUGCAT_EVENT)) (VERBOSE_PREFIX_3 "Handling Event %p of Type %s\n", event, sccp_event_type2str(e->type));
	/* update refcount */
	switch (e->type) {
		case SCCP_EVENT_DEVICE_REGISTERED:
		case SCCP_EVENT_DEVICE_UNREGISTERED:
		case SCCP_EVENT_DEVICE_PREREGISTERED:
			e->event.deviceRegistered.device = event->event.deviceRegistered.device;
			break;

		case SCCP_EVENT_LINE_CREATED:
			e->event.lineCreated.line = event->event.lineCreated.line;
			break;

		case SCCP_EVENT_DEVICE_ATTACHED:
		case SCCP_EVENT_DEVICE_DETACHED:
			e->event.deviceAttached.linedevice = event->event.deviceAttached.linedevice;
			break;

		case SCCP_EVENT_FEATURE_CHANGED:
			e->event.featureChanged.device = event->event.featureChanged.device;
			e->event.featureChanged.optional_linedevice = event->event.featureChanged.optional_linedevice;
			e->event.featureChanged.featureType = event->event.featureChanged.featureType;
			break;

		case SCCP_EVENT_LINESTATUS_CHANGED:
			e->event.lineStatusChanged.line = event->event.lineStatusChanged.line;
			e->event.lineStatusChanged.optional_device = event->event.lineStatusChanged.optional_device;
			e->event.lineStatusChanged.state = event->event.lineStatusChanged.state;
			break;

		case SCCP_EVENT_LINE_CHANGED:
		case SCCP_EVENT_LINE_DELETED:
			break;
		case SCCP_EVENT_TYPE_SENTINEL:
			break;
	}

	/* search for position in array */
	int i, n;
	sccp_event_type_t eventType = event->type;

	for (i = 0, n = 1 << i; i < NUMBER_OF_EVENT_TYPES; i++, n = 1 << i) {
		if (eventType & n) {
			break;
		}
	}

	// pthread_attr_t tattr;
	// pthread_t tid;

	/* start async thread if nessesary */
	if (GLOB(module_running)) {
		if (subscriptions[i].aSyncSize > 0 && sccp_event_running) {
			/* create thread for async subscribers */
			struct sccp_event_aSyncEventProcessorThreadArg *arg = sccp_malloc(sizeof(struct sccp_event_aSyncEventProcessorThreadArg));

			if (!arg) {
				pbx_log(LOG_ERROR, "%p: Memory Allocation Error while creating sccp_event_aSyncEventProcessorThreadArg. Skipping\n", event);
			} else {
				arg->subscribers = &subscriptions[i];
				arg->event = sccp_event_retain(e);

				/* initialized with default attributes */
				if (arg->event != NULL) {
					sccp_log((DEBUGCAT_EVENT)) (VERBOSE_PREFIX_3 "Adding work to threadpool for event: %p, type: %s\n", event, sccp_event_type2str(event->type));
					if (!sccp_threadpool_add_work(GLOB(general_threadpool), (void *) sccp_event_processor, (void *) arg)) {
						pbx_log(LOG_ERROR, "Could not add work to threadpool for event: %p, type: %s for processing\n", event, sccp_event_type2str(event->type));
						arg->event = sccp_event_release(arg->event);
						sccp_free(arg);
					}
				} else {
					pbx_log(LOG_ERROR, "Could not retain e: %p, type: %s for processing\n", e, sccp_event_type2str(event->type));
					sccp_free(arg);
				}
			}
		}

		/* execute sync subscribers */
		AUTO_RELEASE sccp_event_t *tmp_e = NULL;

		if ((tmp_e = sccp_event_retain(e))) {
			for (n = 0; n < subscriptions[i].syncSize && sccp_event_running; n++) {
				if (subscriptions[i].sync[n].callback_function != NULL) {
					subscriptions[i].sync[n].callback_function((const sccp_event_t *) e);
				}
			}
		} else {
			pbx_log(LOG_ERROR, "Could not retain e: %p, type: %s for processing\n", e, sccp_event_type2str(event->type));
		}
	} else {
		// we are unloading. switching to synchonous mode for everything
		sccp_log((DEBUGCAT_EVENT)) (VERBOSE_PREFIX_3 "Handling Event %p of Type %s in Forced Synchronous Mode\n", event, sccp_event_type2str(e->type));
		AUTO_RELEASE sccp_event_t *tmp_e = NULL;

		if ((tmp_e = sccp_event_retain(e))) {
			for (n = 0; n < subscriptions[i].syncSize && sccp_event_running; n++) {
				if (subscriptions[i].sync[n].callback_function != NULL) {
					subscriptions[i].sync[n].callback_function((const sccp_event_t *) e);
				}
			}
			for (n = 0; n < subscriptions[i].aSyncSize && sccp_event_running; n++) {
				if (subscriptions[i].async[n].callback_function != NULL) {
					subscriptions[i].async[n].callback_function((const sccp_event_t *) e);
				}
			}
		} else {
			pbx_log(LOG_ERROR, "Could not retain e: %p, type: %s for processing\n", e, sccp_event_type2str(event->type));
		}
	}
}
示例#3
0
/*!
 * \brief
 * Splits a string into its host and port components
 *
 * \param str       [in] The string to parse. May be modified by writing a NUL at the end of
 *                  the host part.
 * \param host      [out] Pointer to the host component within \a str.
 * \param port      [out] Pointer to the port component within \a str.
 * \param flags     If set to zero, a port MAY be present. If set to PARSE_PORT_IGNORE, a
 *                  port MAY be present but will be ignored. If set to PARSE_PORT_REQUIRE,
 *                  a port MUST be present. If set to PARSE_PORT_FORBID, a port MUST NOT
 *                  be present.
 *
 * \retval 1 Success
 * \retval 0 Failure
 */
int sccp_netsock_split_hostport(char *str, char **host, char **port, int flags)
{
	char *s = str;
	char *orig_str = str;											/* Original string in case the port presence is incorrect. */
	char *host_end = NULL;											/* Delay terminating the host in case the port presence is incorrect. */

	sccp_log(DEBUGCAT_HIGH) (VERBOSE_PREFIX_4 "Splitting '%s' into...\n", str);
	*host = NULL;
	*port = NULL;
	if (*s == '[') {
		*host = ++s;
		for (; *s && *s != ']'; ++s) {
		}
		if (*s == ']') {
			host_end = s;
			++s;
		}
		if (*s == ':') {
			*port = s + 1;
		}
	} else {
		*host = s;
		for (; *s; ++s) {
			if (*s == ':') {
				if (*port) {
					*port = NULL;
					break;
				} else {
					*port = s;
				}
			}
		}
		if (*port) {
			host_end = *port;
			++*port;
		}
	}

	switch (flags & PARSE_PORT_MASK) {
		case PARSE_PORT_IGNORE:
			*port = NULL;
			break;
		case PARSE_PORT_REQUIRE:
			if (*port == NULL) {
				pbx_log(LOG_WARNING, "Port missing in %s\n", orig_str);
				return 0;
			}
			break;
		case PARSE_PORT_FORBID:
			if (*port != NULL) {
				pbx_log(LOG_WARNING, "Port disallowed in %s\n", orig_str);
				return 0;
			}
			break;
	}
	/* Can terminate the host string now if needed. */
	if (host_end) {
		*host_end = '\0';
	}
	sccp_log(DEBUGCAT_HIGH) (VERBOSE_PREFIX_4 "...host '%s' and port '%s'.\n", *host, *port ? *port : "");
	return 1;
}