示例#1
0
/**
 * Execute function for each subscriber
 */
static void subscriber_execute(const char *uuid, const char *signal_type, subscriber_execute_fn callback, void *user_data)
{
    switch_event_t *subscriber_list = NULL;
    switch_event_header_t *subscriber = NULL;

    /* fetch list of subscribers */
    char *key = switch_mprintf("%s:%s", uuid, signal_type);
    switch_event_create_subclass(&subscriber_list, SWITCH_EVENT_CLONE, NULL);
    switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Subscriber execute %s\n", signal_type);
    switch_mutex_lock(globals.subscribers_mutex);
    {
        switch_hash_index_t *hi = NULL;
        switch_hash_t *signal_subscribers = switch_core_hash_find(globals.subscribers, key);
        if (signal_subscribers) {
            for (hi = switch_core_hash_first(signal_subscribers); hi; hi = switch_core_hash_next(hi)) {
                const void *jid;
                void *dont_care;
                switch_core_hash_this(hi, &jid, NULL, &dont_care);
                switch_event_add_header_string(subscriber_list, SWITCH_STACK_BOTTOM, "execute", (const char *)jid);
            }
        } else {
            switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "No subscribers for %s\n", signal_type);
        }
    }
    switch_mutex_unlock(globals.subscribers_mutex);
    switch_safe_free(key);

    /* execute function for each subscriber */
    for (subscriber = subscriber_list->headers; subscriber; subscriber = subscriber->next) {
        callback(subscriber->value, user_data);
    }

    switch_event_destroy(&subscriber_list);
}
示例#2
0
/**
 * Process a tag
 */
static int tag_hook(void *user_data, char *name, char **atts, int type)
{
	int result = IKS_OK;
	struct nlsml_parser *parser = (struct nlsml_parser *)user_data;

	if (type == IKS_OPEN || type == IKS_SINGLE) {
		struct nlsml_node *child_node = malloc(sizeof(*child_node));
		child_node->name = name;
		child_node->tag_def = switch_core_hash_find(globals.tag_defs, name);
		if (!child_node->tag_def) {
			child_node->tag_def = switch_core_hash_find(globals.tag_defs, "ANY");
		}
		child_node->parent = parser->cur;
		parser->cur = child_node;
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser->uuid), SWITCH_LOG_DEBUG1, "<%s>\n", name);
		result = process_tag(parser, name, atts);
	}

	if (type == IKS_CLOSE || type == IKS_SINGLE) {
		struct nlsml_node *node = parser->cur;
		parser->cur = node->parent;
		free(node);
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser->uuid), SWITCH_LOG_DEBUG1, "</%s>\n", name);
	}

	return result;
}
示例#3
0
/**
 * Parse the result, looking for noinput/nomatch/match
 * @param result the NLSML result to parse
 * @param uuid optional UUID for logging
 * @return true if successful
 */
enum nlsml_match_type nlsml_parse(const char *result, const char *uuid)
{
	struct nlsml_parser parser = { 0 };
	parser.uuid = uuid;
	if (!zstr(result)) {
		iksparser *p = iks_sax_new(&parser, tag_hook, cdata_hook);
		if (iks_parse(p, result, 0, 1) == IKS_OK) {
			/* check result */
			if (parser.match) {
				return NMT_MATCH;
			}
			if (parser.nomatch) {
				return NMT_NOMATCH;
			}
			if (parser.noinput) {
				return NMT_NOINPUT;
			}
			switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser.uuid), SWITCH_LOG_INFO, "NLSML result does not have match/noinput/nomatch!\n");
		} else {
			switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser.uuid), SWITCH_LOG_INFO, "Failed to parse NLSML!\n");
		}
		iks_parser_delete(p);
	} else {
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser.uuid), SWITCH_LOG_INFO, "Missing NLSML result\n");
	}
	return NMT_BAD_XML;
}
bool WSClientParser::Login() {
	switch_log_printf(
			SWITCH_CHANNEL_UUID_LOG(this->uuid),
			SWITCH_LOG_INFO,
			"WSClientParser::Login( "
			"this : %p, "
			"user : '******', "
			"domain : '%s', "
			"site : '%s', "
			"custom : '%s' "
			") \n",
			this,
			mpUser,
			mpDomain,
			mpSite,
			mpCustom
			);

	bool bFlag = true;

	// 暂时不做PHP验证
	switch_event_t *locate_params;
	switch_xml_t xml = NULL;

	switch_event_create(&locate_params, SWITCH_EVENT_GENERAL);
	switch_assert(locate_params);
	switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "source", "mod_ws");
	switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "site", mpSite);
	switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "custom", mpCustom);

	/* Locate user */
	if (switch_xml_locate_user_merged("id", mpUser, mpDomain, NULL, &xml, locate_params) != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(
				SWITCH_CHANNEL_UUID_LOG(this->uuid),
				SWITCH_LOG_ERROR,
				"WSClientParser::Login( "
				"[Fail], "
				"this : %p, "
				"user : '******', "
				"domain : '%s' ",
				this,
				mpUser,
				mpDomain
				);
		bFlag = false;
	}

	switch_event_destroy(&locate_params);

	// 发送登录成功事件
	ws_login();

	return bFlag;
}
示例#5
0
/**
 * Forward CPA signal to client
 */
static void rayo_cpa_detector_event(const char *jid, void *user_data)
{
    struct rayo_actor *component = RAYO_LOCATE(jid);
    if (component) {
        if (CPA_COMPONENT(component)->ready) {
            switch_event_t *event = (switch_event_t *)user_data;
            const char *signal_type = switch_event_get_header(event, "signal-type");
            struct cpa_signal *cpa_signal = switch_core_hash_find(CPA_COMPONENT(component)->signals, signal_type);
            switch_log_printf(SWITCH_CHANNEL_UUID_LOG(RAYO_COMPONENT(component)->parent->id), SWITCH_LOG_DEBUG, "Handling CPA event\n");
            if (cpa_signal) {
                const char *value = switch_event_get_header(event, "value");
                const char *duration = switch_event_get_header(event, "duration");
                if (cpa_signal->terminate) {
                    iks *complete_event;
                    iks *signal_xml;

                    stop_cpa_detectors(CPA_COMPONENT(component));

                    /* send complete event to client */
                    complete_event = rayo_component_create_complete_event(RAYO_COMPONENT(component), "signal", RAYO_CPA_NS);
                    signal_xml = iks_find(complete_event, "complete");
                    signal_xml = iks_find(signal_xml, "signal");
                    iks_insert_attrib(signal_xml, "type", signal_type);
                    if (!zstr(value)) {
                        iks_insert_attrib(signal_xml, "value", value);
                    }
                    if (!zstr(duration)) {
                        iks_insert_attrib(signal_xml, "duration", duration);
                    }
                    rayo_component_send_complete_event(RAYO_COMPONENT(component), complete_event);
                } else {
                    /* send event to client */
                    iks *signal_event = iks_new_presence("signal", RAYO_CPA_NS, RAYO_JID(component), RAYO_COMPONENT(component)->client_jid);
                    iks *signal_xml = iks_find(signal_event, "signal");
                    iks_insert_attrib(signal_xml, "type", signal_type);
                    if (!zstr(value)) {
                        iks_insert_attrib(signal_xml, "value", value);
                    }
                    if (!zstr(duration)) {
                        iks_insert_attrib(signal_xml, "duration", duration);
                    }
                    RAYO_SEND_REPLY(component, RAYO_COMPONENT(component)->client_jid, signal_event);
                }
            }
        } else {
            switch_log_printf(SWITCH_CHANNEL_UUID_LOG(RAYO_COMPONENT(component)->parent->id), SWITCH_LOG_DEBUG, "Skipping CPA event\n");
        }
        RAYO_UNLOCK(component);
    }
}
WSChannel* WSClientParser::CreateChannel(switch_core_session_t *session) {
	WSChannel *wsChannel = NULL;

	// 创建channel
//	switch_memory_pool_t *pool = switch_core_session_get_pool(session);
	wsChannel = (WSChannel *)switch_core_alloc(mpPool, sizeof(WSChannel));
	wsChannel->session = session;
	wsChannel->parser = this;
	wsChannel->uuid_str = switch_core_strdup(mpPool, switch_core_session_get_uuid(session));

	switch_log_printf(
			SWITCH_CHANNEL_UUID_LOG(this->GetUUID()),
			SWITCH_LOG_INFO,
			"WSClientParser::CreateChannel( "
			"this : %p, "
			"wsChannel : %p "
			") \n",
			this,
			wsChannel
			);

	if( InitChannel(wsChannel) ) {
		mpChannel = wsChannel;
	} else {
		DestroyChannel(wsChannel);
	}

	return wsChannel;
}
bool WSClientParser::ws_disconnect() {
	switch_status_t status = SWITCH_STATUS_FALSE;
	switch_event_t *event;
	if ( (status = switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, WS_EVENT_MAINT)) == SWITCH_STATUS_SUCCESS) {
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "User", mpUser);
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Domain", mpDomain);
		status = switch_event_fire(&event);
	}

	if( status != SWITCH_STATUS_SUCCESS ) {
		switch_log_printf(
				SWITCH_CHANNEL_UUID_LOG(this->uuid),
				SWITCH_LOG_ERROR,
				"WSClientParser::ws_disconnect( "
				"[Send event Fail], "
				"this : %p, "
				"user : '******', "
				"domain : '%s' "
				") \n",
				this,
				mpUser,
				mpDomain
				);
	}

	return status == SWITCH_STATUS_SUCCESS;
}
示例#8
0
/**
 * Request signals
 */
static void subscribe(const char *uuid, const char *signal_type, const char *jid)
{
    char *key = switch_mprintf("%s:%s", uuid, signal_type);
    switch_mutex_lock(globals.subscribers_mutex);
    {
        switch_hash_t *signal_subscribers = switch_core_hash_find(globals.subscribers, key);
        switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Subscribe %s => %s\n", signal_type, jid);
        if (!signal_subscribers) {
            switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Create %s subscriber hash\n", signal_type);
            switch_core_hash_init(&signal_subscribers);
            switch_core_hash_insert(globals.subscribers, key, signal_subscribers);
        }
        switch_core_hash_insert(signal_subscribers, jid, "1");
    }
    switch_mutex_unlock(globals.subscribers_mutex);
    switch_safe_free(key);
}
/**
 * Seek file
 */
static switch_status_t fileman_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
{
	struct fileman_file_context *context = handle->private_info;

	if (!handle->seekable) {
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_WARNING, "File is not seekable\n");
		return SWITCH_STATUS_NOTIMPL;
	}
	return switch_core_file_seek(&context->fh, cur_sample, samples, whence);
}
示例#10
0
/**
 * Handle CDATA that is not allowed
 * @param parser the parser
 * @param data the CDATA
 * @param len the CDATA length
 * @return IKS_BADXML if any printable characters
 */
static int process_cdata_bad(struct nlsml_parser *parser, char *data, size_t len)
{
	int i;
	for (i = 0; i < len; i++) {
		if (isgraph(data[i])) {
			switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser->uuid), SWITCH_LOG_INFO, "Unexpected CDATA for <%s>\n", parser->cur->name);
			return IKS_BADXML;
		}
	}
	return IKS_OK;
}
示例#11
0
/**
 * Stop receiving signals
 */
static void unsubscribe(const char *uuid, const char *signal_type, const char *jid)
{
    char *key = switch_mprintf("%s:%s", uuid, signal_type);
    switch_mutex_lock(globals.subscribers_mutex);
    {
        switch_hash_t *signal_subscribers = switch_core_hash_find(globals.subscribers, key);
        if (signal_subscribers) {
            switch_core_hash_delete(signal_subscribers, jid);
            switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Unsubscribe %s => %s\n", signal_type, jid);

            /* clean up hash if empty */
            if (!switch_core_hash_first(signal_subscribers)) {
                switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Destroy %s subscriber hash\n", signal_type);
                switch_core_hash_destroy(&signal_subscribers);
                switch_core_hash_delete(globals.subscribers, key);
            }
        }
    }
    switch_mutex_unlock(globals.subscribers_mutex);
    switch_safe_free(key);
}
示例#12
0
/**
 * Handle tag attributes
 * @param parser the parser
 * @param name the tag name
 * @param atts the attributes
 * @return IKS_OK if OK IKS_BADXML on parse failure
 */
static int process_tag(struct nlsml_parser *parser, const char *name, char **atts)
{
	struct nlsml_node *cur = parser->cur;
	if (cur->tag_def->is_root && cur->parent == NULL) {
		/* no parent for ROOT tags */
		return cur->tag_def->attribs_fn(parser, atts);
	} else if (!cur->tag_def->is_root && cur->parent) {
		/* check if this child is allowed by parent node */
		struct tag_def *parent_def = cur->parent->tag_def;
		if (switch_core_hash_find(parent_def->children_tags, "ANY") ||
			switch_core_hash_find(parent_def->children_tags, name)) {
			return cur->tag_def->attribs_fn(parser, atts);
		} else {
			switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser->uuid), SWITCH_LOG_INFO, "<%s> cannot be a child of <%s>\n", name, cur->parent->name);
		}
	} else if (cur->tag_def->is_root && cur->parent != NULL) {
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser->uuid), SWITCH_LOG_INFO, "<%s> must be the root element\n", name);
	} else {
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser->uuid), SWITCH_LOG_INFO, "<%s> cannot be a root element\n", name);
	}
	return IKS_BADXML;
}
/**
 * Notify completion of record component
 */
static void complete_record(struct rayo_component *component, const char *reason, const char *reason_namespace)
{
	switch_core_session_t *session = NULL;
	const char *uuid = component->parent->id;
	char *uri = switch_mprintf("file://%s", RECORD_COMPONENT(component)->local_file_path);
	iks *recording;
	switch_size_t file_size = 0;
/* TODO this doesn't work with HTTP */
#if 0
	switch_file_t *file;

	if (switch_file_open(&file, RECORD_COMPONENT(component)->local_file_path, SWITCH_FOPEN_READ, SWITCH_FPROT_UREAD, RAYO_POOL(component)) == SWITCH_STATUS_SUCCESS) {
		file_size = switch_file_get_size(file);
		switch_file_close(file);
	} else {
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_INFO, "Failed to open %s.\n", RECORD_COMPONENT(component)->local_file_path);
	}
#endif

	switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Recording %s done.\n", RECORD_COMPONENT(component)->local_file_path);

	if (RECORD_COMPONENT(component)->stop_beep && (session = switch_core_session_locate(uuid))) {
		switch_ivr_displace_session(session, RECORD_BEEP, 0, "");
		switch_core_session_rwunlock(session);
	}

	/* send complete event to client */
	recording = iks_new("recording");
	iks_insert_attrib(recording, "xmlns", RAYO_RECORD_COMPLETE_NS);
	iks_insert_attrib(recording, "uri", uri);
	iks_insert_attrib_printf(recording, "duration", "%i", RECORD_COMPONENT(component)->duration_ms);
	iks_insert_attrib_printf(recording, "size", "%"SWITCH_SIZE_T_FMT, file_size);
	rayo_component_send_complete_with_metadata(component, reason, reason_namespace, recording, 1);
	iks_delete(recording);

	RAYO_UNLOCK(component);

	switch_safe_free(uri);
}
示例#14
0
static switch_status_t rtmp_tcp_write(rtmp_session_t *rsession, const unsigned char *buf, switch_size_t *len)
{
	//rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)rsession->profile->io;
	rtmp_tcp_io_private_t *io_pvt = rsession->io_private;
	switch_status_t status;
	switch_size_t orig_len = *len;	
	
#ifdef RTMP_DEBUG_IO
	{
		int i;
		fprintf(rsession->io_debug_out,
			"SEND %"SWITCH_SIZE_T_FMT" bytes\n> ", *len);

		for (i = 0; i < *len; i++) {
			fprintf(rsession->io_debug_out, "%02X ", (uint8_t)buf[i]);
				
			if (i != 0 && i % 32 == 0) {
				fprintf(rsession->io_debug_out, "\n> ");
			}
		}
		fprintf(rsession->io_debug_out, "\n\n ");
		
		fflush(rsession->io_debug_out);
	}
#endif
	
	if (io_pvt->sendq && switch_buffer_inuse(io_pvt->sendq) > 0) {
		/* We already have queued data, append it to the sendq */
		switch_buffer_write(io_pvt->sendq, buf, *len);
		return SWITCH_STATUS_SUCCESS;
	}
	
	status = switch_socket_send_nonblock(io_pvt->socket, (char*)buf, len);
	
	if (*len > 0 && *len < orig_len) {
		
		if (rsession->state >= RS_DESTROY) {
			return SWITCH_STATUS_FALSE;
		}
		
		/* We didnt send it all... add it to the sendq*/		
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_DEBUG, "%"SWITCH_SIZE_T_FMT" bytes added to sendq.\n", (orig_len - *len));
		
		switch_buffer_write(io_pvt->sendq, (buf + *len), orig_len - *len);

		/* Make sure we poll-write */
		rtmp_tcp_alter_pollfd(rsession, SWITCH_TRUE);
	}
	
	return status;
}
void WSClientParser::DestroyChannel(WSChannel* wsChannel) {
	switch_log_printf(
			SWITCH_CHANNEL_UUID_LOG(this->GetUUID()),
			SWITCH_LOG_INFO,
			"WSClientParser::DestroyChannel( "
			"this : %p, "
			"wsChannel : %p "
			") \n",
			this,
			mpChannel
			);

	if( wsChannel ) {
		// Audio
		if (switch_core_codec_ready(&wsChannel->read_codec)) {
			switch_core_codec_destroy(&wsChannel->read_codec);
		}

		if (switch_core_codec_ready(&wsChannel->write_codec)) {
			switch_core_codec_destroy(&wsChannel->write_codec);
		}

		// Video
		if (switch_core_codec_ready(&wsChannel->video_read_codec)) {
			switch_core_codec_destroy(&wsChannel->video_read_codec);
		}

		if (switch_core_codec_ready(&wsChannel->video_write_codec)) {
			switch_core_codec_destroy(&wsChannel->video_write_codec);
		}

		if( wsChannel->video_readbuf_mutex ) {
			switch_mutex_destroy(wsChannel->video_readbuf_mutex);
			wsChannel->video_readbuf_mutex = NULL;
		}

		if( wsChannel->session ) {
			switch_media_handle_destroy(wsChannel->session);
			wsChannel->session = NULL;
		}

		if( wsChannel->video_readbuf ) {
			switch_buffer_destroy(&wsChannel->video_readbuf);
			wsChannel->video_readbuf = NULL;
		}
	}
}
void WSClientParser::DestroyCall() {
	switch_log_printf(
			SWITCH_CHANNEL_UUID_LOG(this->GetUUID()),
			SWITCH_LOG_INFO,
			"WSClientParser::DestroyCall( "
			"this : %p, "
			"mpChannel : %p "
			") \n",
			this,
			mpChannel
			);

	if( mpChannel ) {
		DestroyChannel(mpChannel);
		mpChannel = NULL;
	}
}
示例#17
0
/**
 * Process cdata
 * @param user_data the parser
 * @param data the CDATA
 * @param len the CDATA length
 * @return IKS_OK
 */
static int cdata_hook(void *user_data, char *data, size_t len)
{
	struct nlsml_parser *parser = (struct nlsml_parser *)user_data;
	if (!parser) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing parser\n");
		return IKS_BADXML;
	}
	if (parser->cur) {
		struct tag_def *def = parser->cur->tag_def;
		if (def) {
			return def->cdata_fn(parser, data, len);
		}
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser->uuid), SWITCH_LOG_INFO, "Missing definition for <%s>\n", parser->cur->name);
		return IKS_BADXML;
	}
	return IKS_OK;
}
bool WSClientParser::GetHandShakeRespond(char** buffer, int& len) {
	if( mState == WSClientState_Handshake ) {
		mState = WSClientState_Data;

		char input[256] = "";
		unsigned char output[SHA1_HASH_SIZE] = "";
		char b64[256] = "";

		snprintf(input, sizeof(input), "%s%s", mWebSocketKey, WEBSOCKET_GUID);
		sha1_digest(output, input);
		b64encode((unsigned char *)output, SHA1_HASH_SIZE, (unsigned char *)b64, sizeof(b64));

		char* temp = switch_core_sprintf(
				mpPool,
				"HTTP/1.1 101 Switching Protocols\r\n"
				"Upgrade: websocket\r\n"
				"Connection: Upgrade\r\n"
				"Sec-WebSocket-Accept: %s\r\n"
				"\r\n",
				b64
				);

		*buffer = temp;
		len = strlen(temp);

		switch_log_printf(
				SWITCH_CHANNEL_UUID_LOG(this->uuid),
				SWITCH_LOG_INFO,
				"WSClientParser::GetHandShakeRespond( "
				"this : %p, "
				"len : %d, "
				"buffer : \n%s\n"
				") \n",
				this,
				len,
				*buffer
				);

		return true;
	}
	return false;
}
示例#19
0
static void rtmp_tcp_alter_pollfd(rtmp_session_t *rsession, switch_bool_t pollout)
{
	rtmp_tcp_io_private_t *io_pvt = rsession->io_private;
	rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)rsession->profile->io;
	
	if (pollout && (io_pvt->pollfd->reqevents & SWITCH_POLLOUT)) {
		return;
	} else if (!pollout && !(io_pvt->pollfd->reqevents & SWITCH_POLLOUT)) {
		return;
	}
	
	switch_pollset_remove(io->pollset, io_pvt->pollfd);
	io_pvt->pollfd->reqevents = SWITCH_POLLIN | SWITCH_POLLERR;
	if (pollout) {
		io_pvt->pollfd->reqevents |=  SWITCH_POLLOUT;
	}
	switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_NOTICE, "Pollout: %s\n", 
		pollout ? "true" : "false");
	
	switch_pollset_add(io->pollset, io_pvt->pollfd);
}
示例#20
0
/**
 * Wraps file with interface that can be controlled by fileman flags
 * @param handle
 * @param path the file to play
 * @return SWITCH_STATUS_SUCCESS if opened
 */
static switch_status_t fileman_file_open(switch_file_handle_t *handle, const char *path)
{
	int start_offset_ms = 0;
	switch_status_t status = SWITCH_STATUS_FALSE;
	struct fileman_file_context *context = switch_core_alloc(handle->memory_pool, sizeof(*context));
	handle->private_info = context;

	if (handle->params) {
		const char *id = switch_event_get_header(handle->params, "id");
		const char *uuid = switch_event_get_header(handle->params, "session");
		const char *start_offset_ms_str = switch_event_get_header(handle->params, "start_offset_ms");
		if (!zstr(id)) {
			context->id = switch_core_strdup(handle->memory_pool, id);
		}
		if (!zstr(uuid)) {
			context->uuid = switch_core_strdup(handle->memory_pool, uuid);
		}
		if (!zstr(start_offset_ms_str) && switch_is_number(start_offset_ms_str)) {
			start_offset_ms = atoi(start_offset_ms_str);
			if (start_offset_ms < 0) {
				start_offset_ms = 0;
			}
		}
	}

	switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Got path %s\n", path);

	if ((status = switch_core_file_open(&context->fh, path, handle->channels, handle->samplerate, handle->flags, NULL)) != SWITCH_STATUS_SUCCESS) {
		return status;
	}

	/* set up handle for external control */
	if (!context->id) {
		/* use filename as ID */
		context->id = switch_core_strdup(handle->memory_pool, path);
	}
	switch_mutex_lock(fileman_globals.mutex);
	if (!switch_core_hash_find(fileman_globals.hash, context->id)) {
		switch_core_hash_insert(fileman_globals.hash, context->id, handle);
	} else {
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_WARNING, "Duplicate fileman ID: %s\n", context->id);
		return SWITCH_STATUS_FALSE;
	}
	switch_mutex_unlock(fileman_globals.mutex);

	context->max_frame_len = (handle->samplerate / 1000 * SWITCH_MAX_INTERVAL);
	switch_zmalloc(context->abuf, FILE_STARTBYTES * sizeof(*context->abuf));

	if (!context->fh.audio_buffer) {
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Create audio buffer\n");
		switch_buffer_create_dynamic(&context->fh.audio_buffer, FILE_BLOCKSIZE, FILE_BUFSIZE, 0);
		switch_assert(context->fh.audio_buffer);
	}

	handle->samples = context->fh.samples;
	handle->format = context->fh.format;
	handle->sections = context->fh.sections;
	handle->seekable = context->fh.seekable;
	handle->speed = context->fh.speed;
	handle->vol = context->fh.vol;
	handle->offset_pos = context->fh.offset_pos;
	handle->interval = context->fh.interval;

	if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) {
		switch_set_flag(handle, SWITCH_FILE_NATIVE);
	} else {
		switch_clear_flag(handle, SWITCH_FILE_NATIVE);
	}

	if (handle->params && switch_true(switch_event_get_header(handle->params, "pause"))) {
		switch_set_flag(handle, SWITCH_FILE_PAUSE);
	}

	if (handle->seekable && start_offset_ms) {
		unsigned int pos = 0;
		int32_t target = start_offset_ms * (handle->samplerate / 1000);
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "seek to position %d\n", target);
		switch_core_file_seek(&context->fh, &pos, target, SEEK_SET);
	}

	return status;
}
WSChannel* WSClientParser::CreateCall(
		switch_core_session_t *session,
		const char *profileName,
		const char *profileContext,
		const char *profileDialplan,
		const char* ip
		) {
	WSChannel *wsChannel = NULL;

	switch_memory_pool_t *pool = NULL;
	switch_channel_t* channel = NULL;
	switch_caller_profile_t *caller_profile = NULL;

	char *user = mpUser;
	char *domain = mpDomain;
	const char *destNumber = mpDestNumber;
	const char *context = NULL;
	const char *dialplan = NULL;
	switch_status_t status = SWITCH_STATUS_SUCCESS;

	switch_log_printf(
			SWITCH_CHANNEL_UUID_LOG(this->GetUUID()),
			SWITCH_LOG_INFO,
			"WSClientParser::CreateCall( "
			"this : %p, "
			"profileName : '%s', "
			"profileContext : '%s', "
			"profileDialplan : '%s', "
			"ip : '%s' "
			") \n",
			this,
			profileName,
			profileContext,
			profileDialplan,
			ip
			);

	// 参数不能为空
	if ( !user || !domain || !destNumber ) {
		status = SWITCH_STATUS_FALSE;
	}

	// 不允许一个连接创建多个会话
	if( status == SWITCH_STATUS_SUCCESS && mpChannel ) {
		status = SWITCH_STATUS_FALSE;
	}

	if( status == SWITCH_STATUS_SUCCESS ) {
		pool = switch_core_session_get_pool(session);
		channel = switch_core_session_get_channel(session);
		switch_channel_set_name(
				channel,
				switch_core_session_sprintf(session, "ws/%s/%s/%s", profileName, user, destNumber)
				);
	}

//	if ( status == SWITCH_STATUS_SUCCESS && !zstr(user) && !zstr(domain)) {
//		// 拨号不做验证
//		const char *ivrUser = switch_core_session_sprintf(session, "%s@%s", user, domain);
//		status = switch_ivr_set_user(session, ivrUser);
//	}

	if( status == SWITCH_STATUS_SUCCESS ) {
		if (!(context = switch_channel_get_variable(channel, "user_context"))) {
			if (!(context = profileContext)) {
				context = "public";
			}
		}

		if (!(dialplan = switch_channel_get_variable(channel, "inbound_dialplan"))) {
			if (!(dialplan = profileDialplan)) {
				dialplan = "LUA";
			}
		}

		//	switch_log_printf(
		//			SWITCH_CHANNEL_SESSION_LOG(session),
		//			SWITCH_LOG_NOTICE,
		//			"WSClientParser::CreateCall( "
		//			"context : %s, "
		//			"dialplan : %s "
		//			") \n",
		//			context,
		//			dialplan
		//			);

		// 设置主叫
		caller_profile = switch_caller_profile_new(
				pool,
				switch_str_nil(user),
				dialplan,
				SWITCH_DEFAULT_CLID_NAME,
				!zstr(user) ? user : SWITCH_DEFAULT_CLID_NUMBER,
				ip /* net addr */,
				NULL /* ani   */,
				NULL /* anii  */,
				NULL /* rdnis */,
				"mod_ws",
				context,
				destNumber
				);
		switch_channel_set_caller_profile(channel, caller_profile);
		switch_core_session_add_stream(session, NULL);
		switch_channel_set_variable(channel, "caller", user);
		switch_channel_set_state(channel, CS_INIT);

		wsChannel = CreateChannel(session);
	}

	if( wsChannel ) {
		switch_log_printf(
				SWITCH_CHANNEL_UUID_LOG(this->GetUUID()),
				SWITCH_LOG_INFO,
				"WSClientParser::CreateCall( "
				"[Success], "
				"this : %p, "
				"wsChannel : %p, "
				"profileName : '%s', "
				"profileContext : '%s', "
				"profileDialplan : '%s', "
				"ip : '%s' "
				") \n",
				this,
				wsChannel,
				profileName,
				profileContext,
				profileDialplan,
				ip
				);
	} else {
		switch_log_printf(
				SWITCH_CHANNEL_UUID_LOG(this->GetUUID()),
				SWITCH_LOG_ERROR,
				"WSClientParser::CreateCall( "
				"[Fail], "
				"this : %p "
				") \n",
				this,
				profileName,
				profileContext,
				profileDialplan,
				ip
				);
	}

	return wsChannel;
}
示例#22
0
/**
 * Process fileman command
 */
static switch_status_t fileman_process_cmd(const char *cmd, switch_file_handle_t *fhp)
{
	if (zstr(cmd)) {
		return SWITCH_STATUS_SUCCESS;
	}

	if (fhp) {
		struct fileman_file_context *context = (struct fileman_file_context *)fhp->private_info;
		if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) {
			return SWITCH_STATUS_FALSE;
		}

		if (!strncasecmp(cmd, "speed", 5)) {
			char *p;

			if ((p = strchr(cmd, ':'))) {
				p++;
				if (*p == '+' || *p == '-') {
					int step;
					if (!(step = atoi(p))) {
						if (*p == '+') {
							step = 1;
						} else {
							step = -1;
						}
					}
					fhp->speed += step;
				} else {
					int speed = atoi(p);
					fhp->speed = speed;
				}
				return SWITCH_STATUS_SUCCESS;
			}

			return SWITCH_STATUS_FALSE;

		} else if (!strncasecmp(cmd, "volume", 6)) {
			char *p;

			if ((p = strchr(cmd, ':'))) {
				p++;
				if (*p == '+' || *p == '-') {
					int step;
					if (!(step = atoi(p))) {
						if (*p == '+') {
							step = 1;
						} else {
							step = -1;
						}
					}
					fhp->vol += step;
				} else {
					int vol = atoi(p);
					fhp->vol = vol;
				}
				return SWITCH_STATUS_SUCCESS;
			}

			if (fhp->vol) {
				switch_normalize_volume(fhp->vol);
			}

			return SWITCH_STATUS_FALSE;
		} else if (!strcasecmp(cmd, "pause")) {
			switch_set_flag(fhp, SWITCH_FILE_PAUSE);
			return SWITCH_STATUS_SUCCESS;
		} else if (!strcasecmp(cmd, "resume")) {
			switch_clear_flag(fhp, SWITCH_FILE_PAUSE);
			return SWITCH_STATUS_SUCCESS;
		} else if (!strcasecmp(cmd, "stop")) {
			switch_set_flag(fhp, SWITCH_FILE_DONE);
			return SWITCH_STATUS_FALSE;
		} else if (!strcasecmp(cmd, "truncate")) {
			switch_core_file_truncate(fhp, 0);
		} else if (!strcasecmp(cmd, "restart")) {
			unsigned int pos = 0;
			fhp->speed = 0;
			switch_core_file_seek(fhp, &pos, 0, SEEK_SET);
			return SWITCH_STATUS_SUCCESS;
		} else if (!strncasecmp(cmd, "seek", 4)) {
			unsigned int samps = 0;
			unsigned int pos = 0;
			char *p;

			if ((p = strchr(cmd, ':'))) {
				p++;
				if (*p == '+' || *p == '-') {
					int step;
					int32_t target;
					if (!(step = atoi(p))) {
						if (*p == '+') {
							step = 1000;
						} else {
							step = -1000;
						}
					}

					samps = step * (fhp->samplerate / 1000);
					target = (int32_t)fhp->pos + samps;

					if (target < 0) {
						target = 0;
					}

					switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "seek to position %d\n", target);
					switch_core_file_seek(fhp, &pos, target, SEEK_SET);

				} else {
					samps = switch_atoui(p) * (fhp->samplerate / 1000);
					switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "seek to position %d\n", samps);
					switch_core_file_seek(fhp, &pos, samps, SEEK_SET);
				}
			}

			return SWITCH_STATUS_SUCCESS;
		}
	}

	if (!strcmp(cmd, "true") || !strcmp(cmd, "undefined")) {
		return SWITCH_STATUS_SUCCESS;
	}

	return SWITCH_STATUS_FALSE;
}
bool WSClientParser::HangupCall() {
	switch_core_session_t* session = NULL;

	if( mpChannel ) {
		// 挂断会话
		char* uuid = mpChannel->uuid_str;

		switch_log_printf(
				SWITCH_CHANNEL_UUID_LOG(this->GetUUID()),
				SWITCH_LOG_INFO,
				"WSClientParser::HangupCall( "
				"[Start], "
				"this : %p, "
				"wsChannel : %p, "
				"session : '%s' "
				") \n",
				this,
				mpChannel,
				uuid
				);

		if( uuid ) {
			// 挂断会话
			session = switch_core_session_locate(uuid);
			if ( session != NULL )  {
				switch_channel_t* channel = switch_core_session_get_channel(session);
				if( channel ) {
					switch_log_printf(
							SWITCH_CHANNEL_UUID_LOG(this->GetUUID()),
							SWITCH_LOG_INFO,
							"WSClientParser::HangupCall( "
							"[Channel hang up], "
							"this : %p, "
							"wsChannel : %p, "
							"session : '%s' "
							") \n",
							this,
							mpChannel,
							switch_core_session_get_uuid(session)
							);
					switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
				} else {
					switch_log_printf(
							SWITCH_CHANNEL_UUID_LOG(this->GetUUID()),
							SWITCH_LOG_INFO,
							"WSClientParser::HangupCall( "
							"[No channel to hang up], "
							"this : %p, "
							"wsChannel : %p, "
							"session : '%s' "
							") \n",
							this,
							mpChannel,
							switch_core_session_get_uuid(session)
							);
				}
				switch_core_session_rwunlock(session);
			}
		}

		switch_log_printf(
				SWITCH_CHANNEL_UUID_LOG(this->GetUUID()),
				SWITCH_LOG_INFO,
				"WSClientParser::HangupCall( "
				"[Success], "
				"this : %p, "
				"wsChannel : %p, "
				"session : '%s' "
				") \n",
				this,
				mpChannel,
				uuid
				);
	}

	return (session != NULL);
}
bool WSClientParser::ParseFirstLine(char* line) {
	bool bFlag = false;

	// Get Param
	char* p = line;
	char* delim = " ";
	char decodeUrl[HTTP_URL_MAX_PATH] = {0};

	char *array[HTTP_URL_FIRSTLINE_PARAM_MAX_COUNT];
	if( switch_separate_string_string(p, delim, array, HTTP_URL_FIRSTLINE_PARAM_MAX_COUNT) >= HTTP_URL_FIRSTLINE_PARAM_COUNT ) {
		Arithmetic ac;
		ac.decode_url(array[1], strlen(array[1]), decodeUrl);

		switch_log_printf(
				SWITCH_CHANNEL_UUID_LOG(this->uuid),
				SWITCH_LOG_INFO,
				"WSClientParser::ParseFirstLine( "
				"this : %p, "
				"decodeUrl : '%s' "
				") \n",
				this,
				decodeUrl
				);

		if( strlen(decodeUrl) > 0 ) {
//			p = decodeUrl;
			p = switch_core_strdup(mpPool, decodeUrl);
			delim = "/";
			if( *p == *delim ) {
				p++;
			}

			char *array2[HTTP_URL_PATH_PARAM_MAX_COUNT];
			if( switch_separate_string_string(p, delim, array2, HTTP_URL_PATH_PARAM_MAX_COUNT) >= HTTP_URL_PATH_PARAM_COUNT ) {
				mpUser = switch_core_strdup(mpPool, array2[0]);
				mpDomain = switch_core_strdup(mpPool, array2[1]);
				mpDestNumber = switch_core_strdup(mpPool, array2[2]);
				// 暂时不做PHP验证
				mpSite = switch_core_strdup(mpPool, array2[3]);
				mpCustom = switch_core_strdup(mpPool, array2[4]);
//				mpSite = switch_core_strdup(mpPool, "");
//				mpCustom = switch_core_strdup(mpPool, "");

				switch_log_printf(
						SWITCH_CHANNEL_UUID_LOG(this->uuid),
						SWITCH_LOG_INFO,
						"WSClientParser::ParseFirstLine( "
						"this : %p, "
						"user : '******', "
						"domain : '%s', "
						"destnumber : '%s', "
						"site : '%s', "
						"custom : '%s' "
						") \n",
						this,
						mpUser,
						mpDomain,
						mpDestNumber,
						mpSite,
						mpCustom
						);

				bFlag = true;
			}
		}
	}

	if( !bFlag ) {
		switch_log_printf(
				SWITCH_CHANNEL_UUID_LOG(this->uuid),
				SWITCH_LOG_ERROR,
				"WSClientParser::ParseFirstLine( "
				"[Fail], "
				"this : %p, "
				"decodeUrl : '%s' "
				") \n",
				this,
				decodeUrl
				);
	}

	return bFlag;
}
示例#25
0
/**
 * Handle fax completion event from FreeSWITCH core
 * @param event received from FreeSWITCH core.  It will be destroyed by the core after this function returns.
 */
static void on_execute_complete_event(switch_event_t *event)
{
	const char *application = switch_event_get_header(event, "Application");
	
	if (!zstr(application) && (!strcmp(application, "rxfax") || !strcmp(application, "txfax"))) {
		int is_rxfax = !strcmp(application, "rxfax");
		const char *uuid = switch_event_get_header(event, "Unique-ID");
		const char *fax_jid = switch_event_get_header(event, "variable_rayo_fax_jid");
		struct rayo_actor *component;
		if (!zstr(fax_jid) && (component = RAYO_LOCATE(fax_jid))) {
			iks *result;
			iks *complete;
			iks *fax;
			int have_fax_document = 1;
			switch_core_session_t *session;
			switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Got result for %s\n", fax_jid);

			/* clean up channel */
			session = switch_core_session_locate(uuid);
			if (session) {
				switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_read_frame_interrupt", NULL);
				switch_core_session_rwunlock(session);
			}

			/* RX only: transfer HTTP document and delete local copy */
			if (is_rxfax && RECEIVEFAX_COMPONENT(component)->http_put_after_receive && switch_file_exists(RECEIVEFAX_COMPONENT(component)->local_filename, RAYO_POOL(component)) == SWITCH_STATUS_SUCCESS) {
				switch_stream_handle_t stream = { 0 };
				SWITCH_STANDARD_STREAM(stream);
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s PUT fax to %s\n", RAYO_JID(component), RECEIVEFAX_COMPONENT(component)->filename);
				switch_api_execute("http_put", RECEIVEFAX_COMPONENT(component)->filename, NULL, &stream);
				/* check if successful */
				if (!zstr(stream.data) && strncmp(stream.data, "+OK", 3)) {
					/* PUT failed */
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s PUT fax to %s failed: %s\n", RAYO_JID(component), RECEIVEFAX_COMPONENT(component)->filename, (char *)stream.data);
					have_fax_document = 0;
				}
				switch_safe_free(stream.data)
				switch_file_remove(RECEIVEFAX_COMPONENT(component)->local_filename, RAYO_POOL(component));
			}

			/* successful fax? */
			if (have_fax_document && switch_true(switch_event_get_header(event, "variable_fax_success"))) {
				result = rayo_component_create_complete_event(RAYO_COMPONENT(component), FAX_FINISH);
			} else if (have_fax_document && FAX_COMPONENT(component)->stop)  {
				result = rayo_component_create_complete_event(RAYO_COMPONENT(component), COMPONENT_COMPLETE_STOP);
			} else {
				result = rayo_component_create_complete_event(RAYO_COMPONENT(component), COMPONENT_COMPLETE_ERROR);
			}
			complete = iks_find(result, "complete");

			/* RX only: add fax document information */
			if (is_rxfax && have_fax_document) {
				const char *pages = switch_event_get_header(event, "variable_fax_document_transferred_pages");
				if (!zstr(pages) && switch_is_number(pages) && atoi(pages) > 0) {
					const char *resolution = switch_event_get_header(event, "variable_fax_file_image_resolution");
					const char *size = switch_event_get_header(event, "variable_fax_image_size");

					fax = iks_insert(complete, "fax");
					iks_insert_attrib(fax, "xmlns", RAYO_FAX_COMPLETE_NS);

					if (RECEIVEFAX_COMPONENT(component)->http_put_after_receive) {
						iks_insert_attrib(fax, "url", RECEIVEFAX_COMPONENT(component)->filename);
					} else {
						/* convert absolute path to file:// URI */
						iks_insert_attrib_printf(fax, "url", "file://%s", RECEIVEFAX_COMPONENT(component)->filename);
					}

					if (!zstr(resolution)) {
						iks_insert_attrib(fax, "resolution", resolution);
					}
					if (!zstr(size)) {
						iks_insert_attrib(fax, "size", size);
					}
					iks_insert_attrib(fax, "pages", pages);
				}
			}

			/* add metadata from event */
			insert_fax_metadata(event, "fax_success", complete);
			insert_fax_metadata(event, "fax_result_code", complete);
			insert_fax_metadata(event, "fax_result_text", complete);
			insert_fax_metadata(event, "fax_document_transferred_pages", complete);
			insert_fax_metadata(event, "fax_document_total_pages", complete);
			insert_fax_metadata(event, "fax_image_resolution", complete);
			insert_fax_metadata(event, "fax_image_size", complete);
			insert_fax_metadata(event, "fax_bad_rows", complete);
			insert_fax_metadata(event, "fax_transfer_rate", complete);
			insert_fax_metadata(event, "fax_ecm_used", complete);
			insert_fax_metadata(event, "fax_local_station_id", complete);
			insert_fax_metadata(event, "fax_remote_station_id", complete);

			/* flag faxing as done */
			rayo_call_set_faxing(RAYO_CALL(RAYO_COMPONENT(component)->parent), 0);

			rayo_component_send_complete_event(RAYO_COMPONENT(component), result);

			RAYO_UNLOCK(component);
		}
	}
}
示例#26
0
void *SWITCH_THREAD_FUNC rtmp_io_tcp_thread(switch_thread_t *thread, void *obj)
{
	rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)obj;
	io->base.running = 1;
	
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s: I/O Thread starting\n", io->base.profile->name);
	
	
	while(io->base.running) {
		const switch_pollfd_t *fds;
		int32_t numfds;
		int32_t i;
		switch_status_t status;
		
		switch_mutex_lock(io->mutex);
		status = switch_pollset_poll(io->pollset, 500000, &numfds, &fds);
		switch_mutex_unlock(io->mutex);
		
		if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_TIMEOUT) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "pollset_poll failed\n");
			continue;
		} else if (status == SWITCH_STATUS_TIMEOUT) {
			switch_cond_next();
		}
		
		for (i = 0; i < numfds; i++) {
			if (!fds[i].client_data) { 
				switch_socket_t *newsocket;
				if (switch_socket_accept(&newsocket, io->listen_socket, io->base.pool) != SWITCH_STATUS_SUCCESS) {
					if (io->base.running) {
						/* Don't spam the logs if we are shutting down */
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error [%s]\n", strerror(errno));	
					} else {
						return NULL;
					}
				} else {
					rtmp_session_t *rsession;
					
					if (switch_socket_opt_set(newsocket, SWITCH_SO_NONBLOCK, TRUE)) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't set socket as non-blocking\n");
					}

					if (switch_socket_opt_set(newsocket, SWITCH_SO_TCP_NODELAY, 1)) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't disable Nagle.\n");
					}
					
					if (rtmp_session_request(io->base.profile, &rsession) != SWITCH_STATUS_SUCCESS) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RTMP session request failed\n");
						switch_socket_close(newsocket);
					} else {
						switch_sockaddr_t *addr = NULL;
						char ipbuf[200];
						
						/* Create out private data and attach it to the rtmp session structure */
						rtmp_tcp_io_private_t *pvt = switch_core_alloc(rsession->pool, sizeof(*pvt));
						rsession->io_private = pvt;
						pvt->socket = newsocket;
						switch_socket_create_pollfd(&pvt->pollfd, newsocket, SWITCH_POLLIN | SWITCH_POLLERR, rsession, rsession->pool);
						switch_pollset_add(io->pollset, pvt->pollfd);
						switch_buffer_create_dynamic(&pvt->sendq, 512, 1024, 0);
						
						/* Get the remote address/port info */
						switch_socket_addr_get(&addr, SWITCH_TRUE, newsocket);
						switch_get_addr(ipbuf, sizeof(ipbuf), addr);
						rsession->remote_address = switch_core_strdup(rsession->pool, ipbuf);
						rsession->remote_port = switch_sockaddr_get_port(addr);
						switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_INFO, "Rtmp connection from %s:%i\n",
										  rsession->remote_address, rsession->remote_port);
					}
				}
			} else {
				rtmp_session_t *rsession = (rtmp_session_t*)fds[i].client_data;
				rtmp_tcp_io_private_t *io_pvt = (rtmp_tcp_io_private_t*)rsession->io_private;
				
				if (fds[i].rtnevents & SWITCH_POLLOUT && switch_buffer_inuse(io_pvt->sendq) > 0) {
					/* Send as much remaining data as possible */
					switch_size_t sendlen;
					const void *ptr;
					sendlen = switch_buffer_peek_zerocopy(io_pvt->sendq, &ptr);
					switch_socket_send_nonblock(io_pvt->socket, ptr, &sendlen);
					switch_buffer_toss(io_pvt->sendq, sendlen);
					if (switch_buffer_inuse(io_pvt->sendq) == 0) {
						/* Remove our fd from OUT polling */
						rtmp_tcp_alter_pollfd(rsession, SWITCH_FALSE);
					}
				} else 	if (fds[i].rtnevents & SWITCH_POLLIN && rtmp_handle_data(rsession) != SWITCH_STATUS_SUCCESS) {
					switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_DEBUG, "Closing socket\n");
					
					switch_mutex_lock(io->mutex);
					switch_pollset_remove(io->pollset, io_pvt->pollfd);
					switch_mutex_unlock(io->mutex);
					
					switch_socket_close(io_pvt->socket);
					io_pvt->socket = NULL;
					
					rtmp_session_destroy(&rsession);
				}
			}
		}
	}
	
	io->base.running = -1;
	switch_socket_close(io->listen_socket);
	
	return NULL;
}
int WSClientParser::ParseData(char* buffer, int len) {
	switch_log_printf(
			SWITCH_CHANNEL_UUID_LOG(this->uuid),
			SWITCH_LOG_DEBUG,
			"WSClientParser::ParseData( "
			"this : %p, "
			"len : %d "
//			"buffer : \n%s\n"
			") \n",
			this,
			len
//			buffer
			);

	int ret = 0;
//	DataParser::ParseData(NULL, len);

	Lock();
	switch( mState ) {
	case WSClientState_UnKnow:{
		int lineNumber = 0;

		char line[HTTP_URL_MAX_PATH];
		int lineLen = 0;

		const char* header = buffer;
		const char* sepHeader = strstr(buffer, HTTP_HEADER_SEP);
		const char* sep = NULL;
		if( sepHeader ) {
			switch_log_printf(
					SWITCH_CHANNEL_UUID_LOG(this->uuid),
					SWITCH_LOG_INFO,
					"WSClientParser::ParseData( "
					"[HandShake], "
					"this : %p, "
					"len : %d, "
					"buffer : \n%s\n"
					") \n",
					this,
					len,
					buffer
					);

			// Parse HTTP header separator
			ret = sepHeader - buffer + strlen(HTTP_HEADER_SEP);

			// Parse HTTP header line separator
			while( true ) {
				if( (sep = strstr(header, HTTP_LINE_SEP)) && sep != sepHeader ) {
					lineLen = sep - header;
					if( lineLen < sizeof(line) - 1 ) {
						memcpy(line, header, lineLen);
						line[lineLen] = '\0';

						if( lineNumber == 0 ) {
							// Get First Line
							if( !ParseFirstLine(line) ) {
								break;
							}
						} else {
							ParseHeader(line);
							if( CheckHandShake() ) {
								break;
							}
						}
					}

					header += lineLen + strlen(HTTP_LINE_SEP);

					lineNumber++;

				} else {
					break;
				}
			}
		}

		if( mState == WSClientState_Handshake ) {
			if( mpCallback ) {
				mpCallback->OnWSClientParserHandshake(this);
			}
		} else {
			if( mpCallback ) {
				mpCallback->OnWSClientDisconected(this);
			}
		}
	}break;
	case WSClientState_Handshake:{

	}
	case WSClientState_Data:{
//		char temp[4096] = {0};
//		char *p = temp;
//		unsigned char c;
//		for(int i = 0; i< len; i++) {
//			c = buffer[i];
//			sprintf(p, "%c%c,", hex[c >> 4], hex[c & (16 - 1)]);
//			p += 3;
//		}
//		switch_log_printf(
//				SWITCH_CHANNEL_UUID_LOG(this->uuid),
//				SWITCH_LOG_INFO,
//				"WSClientParser::ParseData( "
//				"parser : %p, "
//				"hex : \n%s\n"
//				") \n",
//				this,
//				temp
//				);

		WSPacket* packet = (WSPacket *)buffer;

//		switch_log_printf(
//				SWITCH_CHANNEL_UUID_LOG(this->uuid),
//				SWITCH_LOG_INFO,
//				"WSClientParser::ParseData( "
//				"parser : %p, "
//				"packet->Fin : %s, "
//				"packet->RSV : %u, "
//				"packet->Opcode : %u, "
//				"packet->Mask : %s, "
//				"packet->Playload Length : %u, "
//				"packet->Extend Playload Length : %llu, "
//				"packet->Mask Key : %s "
//				") \n",
//				this,
//				packet->baseHeader.IsFin()?"true":"false",
//				packet->baseHeader.GetRSVType(),
//				packet->baseHeader.GetOpcode(),
//				packet->baseHeader.IsMask()?"true":"false",
//				packet->baseHeader.GetPlayloadLength(),
//				packet->GetPlayloadLength(),
//				packet->GetMaskKey()
//				);

		const char* data = (const char*)packet->GetData();//buffer;//packet->GetData();
		int playloadLength = packet->GetPlayloadLength();//len;//packet->GetPlayloadLength();
		ret = packet->GetHeaderLength() + playloadLength;

		if( mpCallback) {
			mpCallback->OnWSClientParserData(this, data, playloadLength);
		}

	}break;
	case WSClientState_Disconnected:{
		ret = len;
	}break;
	default:{
		break;
	}
	}

	Unlock();

	return ret;
}