Пример #1
0
static switch_status_t rtmp_tcp_read(rtmp_session_t *rsession, 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_STATUS_SUCCESS;
#ifdef RTMP_DEBUG_IO
	switch_size_t olen = *len;
#endif	
	switch_assert(*len > 0 && *len < 1024000);

	do {
		status = switch_socket_recv(io_pvt->socket, (char*)buf, len);	
	} while(status != SWITCH_STATUS_SUCCESS && SWITCH_STATUS_IS_BREAK(status));
	
#ifdef RTMP_DEBUG_IO
	{
		int i;

		fprintf(rsession->io_debug_in, "recv %p max=%"SWITCH_SIZE_T_FMT" got=%"SWITCH_SIZE_T_FMT"\n< ", (void*)buf, olen, *len);
			
		for (i = 0; i < *len; i++) {
			
			fprintf(rsession->io_debug_in, "%02X ", (uint8_t)buf[i]);

			if (i != 0 && i % 32 == 0) {
				fprintf(rsession->io_debug_in, "\n> ");
			}
		}
		fprintf(rsession->io_debug_in, "\n\n");
		fflush(rsession->io_debug_in);
	}
#endif

	return status;
}
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_STATUS_SUCCESS;
	switch_size_t orig_len = *len;
	switch_size_t remaining = *len;
	int sanity = 100;

#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

	while (remaining > 0) {
		if (rsession->state >= RS_DESTROY) {
			return SWITCH_STATUS_FALSE;
		}

again:
		status = switch_socket_send_nonblock(io_pvt->socket, (char*)buf, len);

		if ((status == 32 || SWITCH_STATUS_IS_BREAK(status)) && sanity-- > 0) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "sending too fast, retrying %d\n", sanity);
			goto again;
		}

		if (status != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "send error %d\n", status);
			break;
		}

		if (*len != orig_len) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "sent %ld of %ld\n", *len, orig_len);
		buf += *len;
		remaining -= *len;
		*len = remaining;
	}

	*len = orig_len;

	return status;
}
Пример #3
0
SWITCH_DECLARE(switch_status_t) switch_ivr_menu_execute(switch_core_session_t *session, switch_ivr_menu_t *stack, char *name, void *obj)
{
	int reps = 0, errs = 0, timeouts = 0, match = 0, running = 1;
	char *greeting_sound = NULL, *aptr = NULL;
	char arg[512];
	switch_ivr_action_t todo = SWITCH_IVR_ACTION_DIE;
	switch_ivr_menu_action_t *ap;
	switch_ivr_menu_t *menu;
	switch_channel_t *channel;
	switch_status_t status = SWITCH_STATUS_SUCCESS;

	if (++stack->stack_count > 12) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Too many levels of recursion.\n");
		switch_goto_status(SWITCH_STATUS_FALSE, end);
	}

	if (!session || !stack || zstr(name)) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid menu context\n");
		switch_goto_status(SWITCH_STATUS_FALSE, end);
	}

	channel = switch_core_session_get_channel(session);

	if (!(menu = switch_ivr_menu_find(stack, name))) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Menu!\n");
		switch_goto_status(SWITCH_STATUS_FALSE, end);
	}

	if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) {
		switch_channel_set_variable(channel, "tts_engine", menu->tts_engine);
		switch_channel_set_variable(channel, "tts_voice", menu->tts_voice);
	}

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Executing IVR menu %s\n", menu->name);
	switch_channel_set_variable(channel, "ivr_menu_status", "success");

	for (reps = 0; running && status == SWITCH_STATUS_SUCCESS; reps++) {
		if (!switch_channel_ready(channel)) {
			break;
		}
		if (errs == menu->max_failures) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum failures\n");
			switch_channel_set_variable(channel, "ivr_menu_status", "failure");
			break;
		}
		if (timeouts == menu->max_timeouts) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum timeouts\n");
			switch_channel_set_variable(channel, "ivr_menu_status", "timeout");
			break;
		}

		if (reps > 0 && menu->short_greeting_sound) {
			greeting_sound = menu->short_greeting_sound;
		} else {
			greeting_sound = menu->greeting_sound;
		}

		match = 0;
		aptr = NULL;

		memset(arg, 0, sizeof(arg));

		memset(menu->buf, 0, menu->inlen + 1);

		if (play_and_collect(session, menu, greeting_sound, menu->inlen) == SWITCH_STATUS_TIMEOUT && *menu->buf == '\0') {
			timeouts++;
			continue;
		}

		if (*menu->buf != '\0') {

			for (ap = menu->actions; ap; ap = ap->next) {
				int ok = 0;
				char substituted[1024];
				char *use_arg = ap->arg;

				if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) {
					switch_channel_set_variable(channel, "tts_engine", menu->tts_engine);
					switch_channel_set_variable(channel, "tts_voice", menu->tts_voice);
				}

				if (ap->re) {
					switch_regex_t *re = NULL;
					int ovector[30];

					if ((ok = switch_regex_perform(menu->buf, ap->bind, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
						switch_perform_substitution(re, ok, ap->arg, menu->buf, substituted, sizeof(substituted), ovector);
						use_arg = substituted;
					}
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "action regex [%s] [%s] [%d]\n", menu->buf, ap->bind, ok);

					switch_regex_safe_free(re);
				} else {
					ok = !strcmp(menu->buf, ap->bind);
				}

				if (ok) {
					match++;
					errs = 0;
					if (ap->function) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
										  "IVR function on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, use_arg);
						todo = ap->function(menu, use_arg, arg, sizeof(arg), obj);
						aptr = arg;
					} else {
						todo = ap->ivr_action;
						aptr = use_arg;
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
										  "IVR action on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, aptr);
					}

					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "switch_ivr_menu_execute todo=[%d]\n", todo);

					switch (todo) {
					case SWITCH_IVR_ACTION_DIE:
						status = SWITCH_STATUS_FALSE;
						break;
					case SWITCH_IVR_ACTION_PLAYSOUND:
						status = switch_ivr_play_file(session, NULL, aptr, NULL);
						break;
					case SWITCH_IVR_ACTION_EXECMENU:
						if (!strcmp(aptr, menu->name)) {
							status = SWITCH_STATUS_SUCCESS;
						} else {
							reps = -1;
							status = switch_ivr_menu_execute(session, stack, aptr, obj);
						}
						break;
					case SWITCH_IVR_ACTION_EXECAPP:
						{
							switch_application_interface_t *application_interface;
							char *app_name;
							char *app_arg = NULL;

							status = SWITCH_STATUS_FALSE;

							if (!zstr(aptr)) {
								app_name = switch_core_session_strdup(session, aptr);
								if ((app_arg = strchr(app_name, ' '))) {
									*app_arg++ = '\0';
								}

								if ((application_interface = switch_loadable_module_get_application_interface(app_name))) {
									switch_core_session_exec(session, application_interface, app_arg);
									UNPROTECT_INTERFACE(application_interface);
									status = SWITCH_STATUS_SUCCESS;
								}
							}
						}
						break;
					case SWITCH_IVR_ACTION_BACK:
						running = 0;
						status = SWITCH_STATUS_SUCCESS;
						break;
					case SWITCH_IVR_ACTION_TOMAIN:
						switch_set_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN);
						status = SWITCH_STATUS_BREAK;
						break;
					case SWITCH_IVR_ACTION_NOOP:
						status = SWITCH_STATUS_SUCCESS;
						break;
					default:
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid TODO!\n");
						break;
					}
				}
			}

			if (switch_test_flag(menu, SWITCH_IVR_MENU_FLAG_STACK)) {	/* top level */
				if (switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN)) {	/* catch the fallback and recover */
					switch_clear_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN);
					status = SWITCH_STATUS_SUCCESS;
					running = 1;
					continue;
				}
			}
		}
		if (!match) {
			if (*menu->buf) {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' caught invalid input '%s'\n", menu->name,
								  menu->buf);
				if (menu->invalid_sound) {
					play_and_collect(session, menu, menu->invalid_sound, 0);
				}
			} else {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' no input detected\n", menu->name);
			}
			errs++;

			/* breaks are ok too */
			if (SWITCH_STATUS_IS_BREAK(status)) {
				status = SWITCH_STATUS_SUCCESS;
			}
		}
	}

	if (stack->stack_count == 1) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "exit-sound '%s'\n", menu->exit_sound);
		if (!zstr(menu->exit_sound)) {
			status = play_and_collect(session, menu, menu->exit_sound, 0);
		}
	}

  end:

	stack->stack_count--;

	return status;
}
Пример #4
0
switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
{
	skinny_message_t *request;
	switch_size_t mlen, bytes = 0;
	char mbuf[SKINNY_MESSAGE_MAXSIZE] = "";
	char *ptr;
	switch_status_t status = SWITCH_STATUS_SUCCESS;

	request = calloc(1,SKINNY_MESSAGE_MAXSIZE);

	if (!request) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to allocate memory.\n");
		return SWITCH_STATUS_MEMERR;
	}

	ptr = mbuf;

	while (listener_is_ready(listener)) {
		uint8_t do_sleep = 1;
		if (listener->expire_time && listener->expire_time < switch_epoch_time_now(NULL)) {
			switch_safe_free(request);
			return SWITCH_STATUS_TIMEOUT;
		}
		if(bytes < SKINNY_MESSAGE_FIELD_SIZE) {
			/* We have nothing yet, get length header field */
			mlen = SKINNY_MESSAGE_FIELD_SIZE - bytes;
		} else {
			/* We now know the message size */
			mlen = request->length + 2*SKINNY_MESSAGE_FIELD_SIZE - bytes;
		}

		status = switch_socket_recv(listener->sock, ptr, &mlen);

		if (listener->expire_time && listener->expire_time < switch_epoch_time_now(NULL)) {
			switch_safe_free(request);
			return SWITCH_STATUS_TIMEOUT;
		}

		if (!listener_is_ready(listener)) {
			switch_safe_free(request);
			break;
		}
		if (!switch_status_is_timeup(status) && !SWITCH_STATUS_IS_BREAK(status) && (status != SWITCH_STATUS_SUCCESS)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Socket break with status=%d.\n", status);
			switch_safe_free(request);
			return SWITCH_STATUS_FALSE;
		}

		if(mlen) {
			bytes += mlen;

			if(bytes >= SKINNY_MESSAGE_FIELD_SIZE) {
				do_sleep = 0;
				ptr += mlen;
				memcpy(request, mbuf, bytes);
#ifdef SKINNY_MEGA_DEBUG
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
						"Got request: length=%d,version=%x,type=%x\n",
						request->length,request->version,request->type);
#endif
				if(request->length < SKINNY_MESSAGE_FIELD_SIZE) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
							"Skinny client sent invalid data. Length should be greater than 4 but got %d.\n",
							request->length);
					switch_safe_free(request);
					return SWITCH_STATUS_FALSE;
				}
				if(request->length + 2*SKINNY_MESSAGE_FIELD_SIZE > SKINNY_MESSAGE_MAXSIZE) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
							"Skinny client sent too huge data. Got %d which is above threshold %d.\n",
							request->length, SKINNY_MESSAGE_MAXSIZE - 2*SKINNY_MESSAGE_FIELD_SIZE);
					switch_safe_free(request);
					return SWITCH_STATUS_FALSE;
				}
				if(bytes >= request->length + 2*SKINNY_MESSAGE_FIELD_SIZE) {
					/* Message body */
					*req = request;
					/* Do not free here, caller needs to do it */
					return  SWITCH_STATUS_SUCCESS;
				}
			}
		}

		if (listener->digit_timeout_time && listener->digit_timeout_time < switch_mono_micro_time_now()) {
			switch_safe_free(request);
			return SWITCH_STATUS_TIMEOUT;
		}

		if (do_sleep) {
			switch_cond_next();
		}
	}

	switch_safe_free(request);
	return SWITCH_STATUS_SUCCESS;
}
void AsyncIOServer::OnRecvEvent(Socket* socket) {
	Client* client = (Client *)(socket->data);
	if( client != NULL ) {
//		switch_log_printf(
//				SWITCH_CHANNEL_LOG,
//				SWITCH_LOG_DEBUG,
//				"AsyncIOServer::OnRecvEvent( client : %p, socket : %p ) \n",
//				client,
//				socket
//				);

		// 尝试读取数据
		char buf[READ_BUFFER_SIZE];
		switch_size_t len = sizeof(buf);
		switch_status_t status = SWITCH_STATUS_SUCCESS;
		bool disconnect = false;

		// 有足够的缓存空间
		if( client->CheckBufferEnough() ) {
			while (true) {
				status = mTcpServer.Read(socket, (char *)buf, &len);
//				status = switch_socket_recv(socket->socket, (char *)buf, &len);
				if( status == SWITCH_STATUS_SUCCESS ) {
					// 读取数据成功, 缓存到客户端
//					switch_log_printf(
//							SWITCH_CHANNEL_LOG,
//							SWITCH_LOG_DEBUG,
//							"AsyncIOServer::OnRecvEvent( client : %p, socket : %p, read ok ) \n",
//							client,
//							socket
//							);

					if( client->Write(buf, len) ) {
						// 放到处理队列
//						switch_log_printf(
//								SWITCH_CHANNEL_LOG,
//								SWITCH_LOG_DEBUG,
//								"AsyncIOServer::OnRecvEvent( client : %p, socket : %p, client write buffer ok ) \n",
//								client,
//								socket
//								);

						RecvHandle(client);

					} else {
						// 没有足够的缓存空间
						switch_log_printf(
								SWITCH_CHANNEL_LOG,
								SWITCH_LOG_INFO,
								"AsyncIOServer::OnRecvEvent( client : %p, socket : %p, write error ) \n",
								client,
								socket
								);
						disconnect = true;
						break;
					}
				} else if( SWITCH_STATUS_IS_BREAK(status) /*|| (status == SWITCH_STATUS_INTR)*/ ) {
					// 没有数据可读超时返回, 不处理
//					switch_log_printf(
//							SWITCH_CHANNEL_LOG,
//							SWITCH_LOG_DEBUG,
//							"AsyncIOServer::OnRecvEvent( client : %p, socket : %p, nothing to read ) \n",
//							client,
//							socket
//							);
					break;
				} else {
					// 读取数据出错, 断开
					switch_log_printf(
							SWITCH_CHANNEL_LOG,
							SWITCH_LOG_INFO,
							"AsyncIOServer::OnRecvEvent( client : %p, socket : %p, read error : %d ) \n",
							client,
							socket,
							status
							);
					disconnect = true;
					break;
				}
			}
		} else {
			// 缓存数据过大, 断开
			switch_log_printf(
					SWITCH_CHANNEL_LOG,
					SWITCH_LOG_INFO,
					"AsyncIOServer::OnRecvEvent( client : %p, socket : %p, buffer not enough error ) \n",
					client,
					socket
					);
			disconnect = true;
		}

		if( disconnect ) {
			Disconnect(client);
		}

		bool bFlag = false;
		switch_mutex_lock(client->clientMutex);
		bFlag = ClientCloseIfNeed(client);
		switch_mutex_unlock(client->clientMutex);

		if( bFlag ) {
			// 回调
			if( mpAsyncIOServerCallback ) {
				mpAsyncIOServerCallback->OnDisconnect(client);
			}

			// 关闭Socket
			mTcpServer.Close(client->socket);

			// 销毁客户端
			Client::Destroy(client);
		}
	}
}
Пример #6
0
static void *SWITCH_THREAD_FUNC switch_nat_multicast_runtime(switch_thread_t * thread, void *obj)
{
	char *buf = NULL;
	char newip[16] = "";
	char *pos;
	switch_event_t *event = NULL;

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NAT thread started\n");

	buf = (char *) malloc(MULTICAST_BUFFSIZE);
	switch_assert(buf);
	nat_globals_perm.running = 1;

	while (nat_globals_perm.running == 1) {
		size_t len = MULTICAST_BUFFSIZE;
		switch_status_t status;
		switch_bool_t do_repub = SWITCH_FALSE;
		memset(buf, 0, len);

		status = switch_socket_recvfrom(nat_globals_perm.maddress, nat_globals_perm.msocket, 0, buf, &len);

		if (!len) {
			if (SWITCH_STATUS_IS_BREAK(status)) {
				switch_yield(5000000);
				continue;
			}

			break;
		}

		if (nat_globals.nat_type == SWITCH_NAT_TYPE_UPNP) {
			/* look for our desc URL and servicetype in the packet */
			if (strstr(buf, nat_globals.descURL) && (buf == NULL || strstr(buf, nat_globals.data.servicetype))) {
				if ((pos = strstr(buf, "NTS:"))) {
					pos = pos + 4;
					while (*pos && *pos == ' ') {
						pos++;
					}
					if (!strncmp(pos, "ssdp:alive", 10)) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "got UPnP keep alive packet: \n%s\n", buf);
						/* did pub ip change */
						newip[0] = '\0';
						if (get_upnp_pubaddr(newip) != SWITCH_STATUS_SUCCESS) {
							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
											  "Unable to get current pubaddr after receiving UPnP keep alive packet.\n");
						}
					} else if (!strncmp(pos, "ssdp:byebye", 11)) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
										  "got UPnP signoff packet.  Your NAT gateway is probably going offline.\n");
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "got UPnP signoff packet: \n%s\n", buf);
					} else {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "got UNKNOWN UPnP keep alive packet: \n%s\n", buf);
					}
				}
			}
		} else {
			/* got some data in NAT-PMP mode, treat any data as a republish event */
			if (get_pmp_pubaddr(newip) < 0) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to get current pubaddr after receiving UPnP keep alive packet.\n");
			}
		}

		if ((strlen(newip) > 0) && strcmp(newip, "0.0.0.0") && strcmp(newip, nat_globals.pub_addr)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Public IP changed from '%s' to '%s'.\n", nat_globals.pub_addr, newip);
			do_repub = SWITCH_TRUE;

			switch_event_create(&event, SWITCH_EVENT_TRAP);
			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "network-address-change");
			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v4", nat_globals.pub_addr);
			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v4", newip);
			switch_event_fire(&event);

			switch_set_string(nat_globals.pub_addr, newip);
			switch_nat_reinit();
		}

		if (do_repub) {
			switch_nat_republish();
		}
	}

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NAT thread ending\n");
	nat_globals_perm.running = 0;

	switch_safe_free(buf);

	return NULL;
}