예제 #1
0
파일: os_net.c 프로젝트: Keemotion/GPAC4iOS
//binds the given socket to the specified port. If ReUse is true
//this will enable reuse of ports on a single machine
GF_EXPORT
GF_Err gf_sk_bind(GF_Socket *sock, const char *local_ip, u16 port, const char *peer_name, u16 peer_port, u32 options)
{
#ifdef GPAC_HAS_IPV6
	struct addrinfo *res, *aip;
	int af;
	u32 type;
#else
	u32 ip_add;
	size_t addrlen;
	struct sockaddr_in LocalAdd;
	struct hostent *Host;
#if 0
	char buf[GF_MAX_IP_NAME_LEN];
#endif

#endif
	s32 ret;
	s32 optval;

	if (!sock || sock->socket) return GF_BAD_PARAM;

#ifndef WIN32	
	if(!local_ip){
		if(!peer_name || !strcmp(peer_name,"localhost")){
			peer_name="127.0.0.1";	
		}
	}
#endif

#ifdef GPAC_HAS_IPV6
	type = (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM;
	af = (options & GF_SOCK_FORCE_IPV6) ? PF_INET6 : PF_UNSPEC;
	if (!gf_net_has_ipv6()) af = PF_INET;
	/*probe way to peer: is it V4 or V6? */
	if (peer_name && peer_port) {
		res = gf_sk_get_ipv6_addr(peer_name, peer_port, af, AI_PASSIVE, type);
		if (!res) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Socket] Cannot get IPV6 host name for %s:%d\n", peer_name, peer_port));
			return GF_IP_ADDRESS_NOT_FOUND;
		}
#ifdef WIN32
		/*win32 has troubles redirecting IPV4 datagrams to IPV6 sockets, so override
		local family type to avoid IPV4(S)->IPV6(C) UDP*/
		af = res->ai_family;
#endif
		memcpy(&sock->dest_addr, res->ai_addr, res->ai_addrlen);
		sock->dest_addr_len = (u32) res->ai_addrlen;
		freeaddrinfo(res);
	}

	/*turn on MobileIP*/
	if (local_ip && MobileIPAdd && !strcmp(MobileIPAdd, local_ip) ) {
		if (gf_net_mobileip_ctrl(1)==GF_OK) {
			sock->flags |= GF_SOCK_IS_MIP;
		} else {
			res = gf_sk_get_ipv6_addr(NULL, port, af, AI_PASSIVE, type);
			local_ip = NULL;
		}
	}
	res = gf_sk_get_ipv6_addr(local_ip, port, af, AI_PASSIVE, type);
	if (!res) {
		if (local_ip) {
			res = gf_sk_get_ipv6_addr(NULL, port, af, AI_PASSIVE, type);
			local_ip = NULL;
		}
		if (!res) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Socket] Cannot get IPV6 host name for %s:%d\n", local_ip, port));
			return GF_IP_ADDRESS_NOT_FOUND;
		}
	}

	/*for all interfaces*/
	for (aip=res; aip!=NULL; aip=aip->ai_next) {
		if (type != (u32) aip->ai_socktype) continue;

		if (aip->ai_next && (aip->ai_next->ai_family==PF_INET) && !gf_net_is_ipv6(peer_name)) continue;

		sock->socket = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
		if (sock->socket == INVALID_SOCKET) {
			sock->socket = NULL_SOCKET;
			continue;
		}
		if (options & GF_SOCK_REUSE_PORT) {
			optval = 1;
			setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
#ifdef SO_REUSEPORT
			optval = 1;
			setsockopt(sock->socket, SOL_SOCKET, SO_REUSEPORT, SSO_CAST &optval, sizeof(optval));
#endif
		}

		if (sock->flags & GF_SOCK_NON_BLOCKING) gf_sk_set_block_mode(sock, 1);

		if (peer_name && peer_port)
			sock->flags |= GF_SOCK_HAS_PEER;


		ret = bind(sock->socket, aip->ai_addr, (int) aip->ai_addrlen);
		if (ret == SOCKET_ERROR) {
			closesocket(sock->socket);
			sock->socket = NULL_SOCKET;
			continue;
		}

		if (aip->ai_family==PF_INET6) sock->flags |= GF_SOCK_IS_IPV6;
		else sock->flags &= ~GF_SOCK_IS_IPV6;

		freeaddrinfo(res);
		return GF_OK;
	}
	freeaddrinfo(res);
	GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Socket] Cannot bind to host %s port %d\n", local_ip, port));
	return GF_IP_CONNECTION_FAILURE;

#else

	sock->socket = socket(AF_INET, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
	if (sock->flags & GF_SOCK_NON_BLOCKING) gf_sk_set_block_mode(sock, 1);
	sock->flags &= ~GF_SOCK_IS_IPV6;

	memset((void *) &LocalAdd, 0, sizeof(LocalAdd));

	/*turn on MobileIP*/
	if (local_ip && MobileIPAdd && !strcmp(MobileIPAdd, local_ip) ) {
		if (gf_net_mobileip_ctrl(1)==GF_OK) {
			sock->flags |= GF_SOCK_IS_MIP;
		} else {
			local_ip = NULL;
		}
	}
	/*setup the address*/
	ip_add = 0;
	if (local_ip) ip_add = inet_addr(local_ip);

	if (!ip_add) {
#if 0
		buf[0] = 0;
		ret = gethostname(buf, GF_MAX_IP_NAME_LEN);
		/*get the IP address*/
		Host = gethostbyname(buf);
		if (Host != NULL) {
			memcpy((char *) &LocalAdd.sin_addr, Host->h_addr_list[0], sizeof(LocalAdd.sin_addr));
			ip_add = LocalAdd.sin_addr.s_addr;
		} else {
			ip_add = INADDR_ANY;
		}
#else
		ip_add = INADDR_ANY;
#endif
	}
	if (peer_name && peer_port) {
#ifdef WIN32
		if ((inet_addr(peer_name)== ip_add)) {
			optval = 1;
			setsockopt(sock->socket, SOL_SOCKET, SO_USELOOPBACK, SSO_CAST &optval, sizeof(optval));
		}
#endif
	}

	LocalAdd.sin_family = AF_INET;
	LocalAdd.sin_port = htons(port);
	LocalAdd.sin_addr.s_addr = ip_add;
	addrlen = sizeof(struct sockaddr_in);


	if (options & GF_SOCK_REUSE_PORT) {
		optval = 1;
		setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, SSO_CAST &optval, sizeof(optval));
#ifdef SO_REUSEPORT
		optval = 1;
		setsockopt(sock->socket, SOL_SOCKET, SO_REUSEPORT, SSO_CAST &optval, sizeof(optval));
#endif
	}

	/*bind the socket*/
	ret = bind(sock->socket, (struct sockaddr *) &LocalAdd, (int) addrlen);
	if (ret == SOCKET_ERROR) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[socket] cannot bind socket - socket error %x\n", LASTSOCKERROR));
		ret = GF_IP_CONNECTION_FAILURE;
	}

	if (peer_name && peer_port) {
		sock->dest_addr.sin_port = htons(peer_port);
		sock->dest_addr.sin_family = AF_INET;
		sock->dest_addr.sin_addr.s_addr = inet_addr(peer_name);
		if (sock->dest_addr.sin_addr.s_addr == INADDR_NONE) {
			Host = gethostbyname(peer_name);
			if (Host == NULL) ret = GF_IP_ADDRESS_NOT_FOUND;
			else memcpy((char *) &sock->dest_addr.sin_addr, Host->h_addr_list[0], sizeof(u32));
		}
		sock->flags |= GF_SOCK_HAS_PEER;
	}
	if (sock->flags & GF_SOCK_HAS_PEER) {
		GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[socket] socket bound to %08X - port %d - remote peer: %s:%d\n", ip_add, port, peer_name, peer_port));
	} else {
		GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[socket] socket bound to %08X - port %d\n", ip_add, port));
	}
	return ret;
#endif
}
예제 #2
0
파일: os_net.c 프로젝트: Keemotion/GPAC4iOS
GF_EXPORT
GF_Err gf_sk_setup_multicast(GF_Socket *sock, const char *multi_IPAdd, u16 MultiPortNumber, u32 TTL, Bool NoBind, char *local_interface_ip)
{
	s32 ret;
	u32 flag;
	struct ip_mreq M_req;
	u32 optval;
#ifdef GPAC_HAS_IPV6
	struct sockaddr *addr;
	struct addrinfo *res, *aip;
	Bool is_ipv6 = 0;
	u32 type;
#endif
	unsigned long local_add_id;

	if (!sock || sock->socket) return GF_BAD_PARAM;

	if (TTL > 255) TTL = 255;

	/*check the address*/
	if (!gf_sk_is_multicast_address(multi_IPAdd)) return GF_BAD_PARAM;

	/*turn on MobileIP*/
	if (local_interface_ip && MobileIPAdd && !strcmp(MobileIPAdd, local_interface_ip) ) {
		if (gf_net_mobileip_ctrl(1)==GF_OK) {
			sock->flags |= GF_SOCK_IS_MIP;
		} else {
			local_interface_ip = NULL;
		}
	}


#ifdef GPAC_HAS_IPV6
	is_ipv6 = gf_net_is_ipv6(multi_IPAdd) || gf_net_is_ipv6(local_interface_ip) ? 1 : 0;
	type = (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM;

	if (is_ipv6) {

		res = gf_sk_get_ipv6_addr(local_interface_ip, MultiPortNumber, AF_UNSPEC, AI_PASSIVE, type);
		if (!res) {
			if (local_interface_ip) {
				res = gf_sk_get_ipv6_addr(NULL, MultiPortNumber, AF_UNSPEC, AI_PASSIVE, type);
				local_interface_ip = NULL;
			}
			if (!res) return GF_IP_CONNECTION_FAILURE;
		}

		/*for all interfaces*/
		for (aip=res; aip!=NULL; aip=aip->ai_next) {
			if (type != (u32) aip->ai_socktype) continue;
			sock->socket = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
			if (sock->socket == INVALID_SOCKET) {
				sock->socket = NULL_SOCKET;
				continue;
			}

			if ((aip->ai_family!=PF_INET) && aip->ai_next && (aip->ai_next->ai_family==PF_INET) && !gf_net_is_ipv6(multi_IPAdd)) continue;

			/*enable address reuse*/
			optval = 1;
			setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
#ifdef SO_REUSEPORT
			optval = 1;
			setsockopt(sock->socket, SOL_SOCKET, SO_REUSEPORT, SSO_CAST &optval, sizeof(optval));
#endif

			/*TODO: copy over other properties (recption buffer size & co)*/
			if (sock->flags & GF_SOCK_NON_BLOCKING) gf_sk_set_block_mode(sock, 1);

			memcpy(&sock->dest_addr, aip->ai_addr, aip->ai_addrlen);
			sock->dest_addr_len = (u32) aip->ai_addrlen;

			if (!NoBind) {
				ret = bind(sock->socket, aip->ai_addr, (int) aip->ai_addrlen);
				if (ret == SOCKET_ERROR) {
					closesocket(sock->socket);
					sock->socket = NULL_SOCKET;
					continue;
				}
			}
			if (aip->ai_family==PF_INET6) sock->flags |= GF_SOCK_IS_IPV6;
			else sock->flags &= ~GF_SOCK_IS_IPV6;
			break;
		}
		freeaddrinfo(res);
		if (!sock->socket) return GF_IP_CONNECTION_FAILURE;


		if (!gf_sk_ipv6_set_remote_address(sock, multi_IPAdd, MultiPortNumber))
			return GF_IP_CONNECTION_FAILURE;

		addr = (struct sockaddr *)&sock->dest_addr;
		if (addr->sa_family == AF_INET) {
			M_req.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
			M_req.imr_interface.s_addr = INADDR_ANY;
			ret = setsockopt(sock->socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &M_req, sizeof(M_req));
			if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
			/*set TTL*/
			ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &TTL, sizeof(TTL));
			if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
			/*Disable loopback*/
			flag = 1;
			ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &flag, sizeof(flag));
			if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
		}

		if (addr->sa_family == AF_INET6) {
			struct ipv6_mreq M_reqV6;

			memcpy(&M_reqV6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
			M_reqV6.ipv6mr_interface = 0;

			/*set TTL*/
			ret = setsockopt(sock->socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &TTL, sizeof(TTL));
			if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
			/*Disable loopback*/
			flag = 1;
			ret = setsockopt(sock->socket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *) &flag, sizeof(flag));
			if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;

			ret = setsockopt(sock->socket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *) &M_reqV6, sizeof(M_reqV6));
			if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
		}
		sock->flags |= GF_SOCK_IS_MULTICAST | GF_SOCK_HAS_PEER;
		return GF_OK;
	}
#endif

	//IPv4 setup
	sock->socket = socket(AF_INET, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
	if (sock->flags & GF_SOCK_NON_BLOCKING) gf_sk_set_block_mode(sock, 1);
	sock->flags &= ~GF_SOCK_IS_IPV6;

	/*enable address reuse*/
	optval = 1;
	ret = setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, SSO_CAST &optval, sizeof(optval));
#ifdef SO_REUSEPORT
	optval = 1;
	setsockopt(sock->socket, SOL_SOCKET, SO_REUSEPORT, SSO_CAST &optval, sizeof(optval));
#endif

	if (local_interface_ip) local_add_id = inet_addr(local_interface_ip);
	else local_add_id = htonl(INADDR_ANY);

	if (!NoBind) {
		struct sockaddr_in local_address;

		local_address.sin_family = AF_INET;
		local_address.sin_addr.s_addr = local_add_id;
		local_address.sin_port = htons( MultiPortNumber);

		ret = bind(sock->socket, (struct sockaddr *) &local_address, sizeof(local_address));
		if (ret == SOCKET_ERROR) {
			/*retry without specifying the local add*/
			local_address.sin_addr.s_addr = local_add_id = htonl(INADDR_ANY);
			local_interface_ip = NULL;
			ret = bind(sock->socket, (struct sockaddr *) &local_address, sizeof(local_address));
			if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
		}
		/*setup local interface*/
		if (local_interface_ip) {
			ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_IF, (char *) &local_add_id, sizeof(local_add_id));
			if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
		}
	}

	/*now join the multicast*/
	M_req.imr_multiaddr.s_addr = inet_addr(multi_IPAdd);
	M_req.imr_interface.s_addr = local_add_id;

	ret = setsockopt(sock->socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &M_req, sizeof(M_req));
	if (ret == SOCKET_ERROR) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[core] cannot join multicast: error %d\n", LASTSOCKERROR));
		return GF_IP_CONNECTION_FAILURE;
	}
	/*set the Time To Live*/
	ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&TTL, sizeof(TTL));
	if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;
	/*Disable loopback*/
	flag = 1;
	ret = setsockopt(sock->socket, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &flag, sizeof(flag));
//	if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE;

#ifdef GPAC_HAS_IPV6
	((struct sockaddr_in *) &sock->dest_addr)->sin_family = AF_INET;
	((struct sockaddr_in *) &sock->dest_addr)->sin_addr.s_addr = M_req.imr_multiaddr.s_addr;
	((struct sockaddr_in *) &sock->dest_addr)->sin_port = htons( MultiPortNumber);
	sock->dest_addr_len = sizeof(struct sockaddr);
#else
	sock->dest_addr.sin_family = AF_INET;
	sock->dest_addr.sin_addr.s_addr = M_req.imr_multiaddr.s_addr;
	sock->dest_addr.sin_port = htons( MultiPortNumber);
#endif

	sock->flags |= GF_SOCK_IS_MULTICAST | GF_SOCK_HAS_PEER;
	return GF_OK;
}
예제 #3
0
파일: os_net.c 프로젝트: Keemotion/GPAC4iOS
//connects a socket to a remote peer on a given port
GF_Err gf_sk_connect(GF_Socket *sock, const char *PeerName, u16 PortNumber, const char *local_ip)
{
	s32 ret;
#ifdef GPAC_HAS_IPV6
	u32 type = (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM;
	struct addrinfo *res, *aip, *lip;

	gf_sk_free(sock);

	res = gf_sk_get_ipv6_addr(PeerName, PortNumber, AF_UNSPEC, AI_PASSIVE, type);
	if (!res) return GF_IP_CONNECTION_FAILURE;

	/*turn on MobileIP*/
	if (local_ip && MobileIPAdd && !strcmp(MobileIPAdd, local_ip) ) {
		if (gf_net_mobileip_ctrl(1)==GF_OK) {
			sock->flags |= GF_SOCK_IS_MIP;
		} else {
			local_ip = NULL;
		}
	}

	lip = NULL;
	if (local_ip) {
		lip = gf_sk_get_ipv6_addr(local_ip, PortNumber, AF_UNSPEC, AI_PASSIVE, type);
		if (!lip && local_ip) {
			lip = gf_sk_get_ipv6_addr(NULL, PortNumber, AF_UNSPEC, AI_PASSIVE, type);
			local_ip = NULL;
		}
	}

	/*for all interfaces*/
	for (aip=res; aip!=NULL; aip=aip->ai_next) {
		if (type != (u32) aip->ai_socktype) continue;
		sock->socket = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
		if (sock->socket == INVALID_SOCKET) {
			sock->socket = NULL_SOCKET;
			continue;
		}
		if (sock->flags & GF_SOCK_NON_BLOCKING) gf_sk_set_block_mode(sock, 1);
		if (aip->ai_family==PF_INET6) sock->flags |= GF_SOCK_IS_IPV6;
		else sock->flags &= ~GF_SOCK_IS_IPV6;

		if (lip) {
			ret = bind(sock->socket, lip->ai_addr, (int) lip->ai_addrlen);
			if (ret == SOCKET_ERROR) {
				closesocket(sock->socket);
				sock->socket = NULL_SOCKET;
				continue;
			}
		}

		ret = connect(sock->socket, aip->ai_addr, (int) aip->ai_addrlen);
		if (ret == SOCKET_ERROR) {
			closesocket(sock->socket);
			sock->socket = NULL_SOCKET;
			continue;
		}

		memcpy(&sock->dest_addr, aip->ai_addr, aip->ai_addrlen);
		sock->dest_addr_len = (u32) aip->ai_addrlen;
		freeaddrinfo(res);
		if (lip) freeaddrinfo(lip);
		return GF_OK;
	}
	freeaddrinfo(res);
	if (lip) freeaddrinfo(lip);
	return GF_IP_CONNECTION_FAILURE;

#else
	struct hostent *Host;

	if (local_ip) {
		/*this will turn on MobileIP if needed*/
		GF_Err e = gf_sk_bind(sock, local_ip, PortNumber, PeerName, PortNumber, GF_SOCK_REUSE_PORT);
		if (e) return e;
	}
	if (!sock->socket) {
		sock->socket = socket(AF_INET, (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
		if (sock->flags & GF_SOCK_NON_BLOCKING)
			gf_sk_set_block_mode(sock, 1);
	}

	/*setup the address*/
	sock->dest_addr.sin_family = AF_INET;
	sock->dest_addr.sin_port = htons(PortNumber);
	/*get the server IP*/
	sock->dest_addr.sin_addr.s_addr = inet_addr(PeerName);
	if (sock->dest_addr.sin_addr.s_addr==INADDR_NONE) {
		Host = gethostbyname(PeerName);
		if (Host == NULL) {
			switch (LASTSOCKERROR) {
#ifndef __SYMBIAN32__
			case ENETDOWN: return GF_IP_NETWORK_FAILURE;
			//case ENOHOST: return GF_IP_ADDRESS_NOT_FOUND;
#endif
			default: return GF_IP_NETWORK_FAILURE;
			}
		}
		memcpy((char *) &sock->dest_addr.sin_addr, Host->h_addr_list[0], sizeof(u32));
	}

	if (sock->flags & GF_SOCK_IS_TCP) {
		ret = connect(sock->socket, (struct sockaddr *) &sock->dest_addr, sizeof(struct sockaddr));
		if (ret == SOCKET_ERROR) {
			u32 res = LASTSOCKERROR;
			GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[Core] Couldn't connect socket - last sock error %d\n", res));
			switch (res) {
			case EAGAIN: return GF_IP_SOCK_WOULD_BLOCK;
#ifdef WIN32
			case WSAEINVAL:
				if (sock->flags & GF_SOCK_NON_BLOCKING)
					return GF_IP_SOCK_WOULD_BLOCK;
#endif
			case EISCONN: return GF_OK;
			case ENOTCONN: return GF_IP_CONNECTION_FAILURE;
			case ECONNRESET: return GF_IP_CONNECTION_FAILURE;
			case EMSGSIZE: return GF_IP_CONNECTION_FAILURE;
			case ECONNABORTED: return GF_IP_CONNECTION_FAILURE;
			case ENETDOWN: return GF_IP_CONNECTION_FAILURE;
			default: return GF_IP_CONNECTION_FAILURE;
			}
		}
	}
#endif
	return GF_OK;
}
예제 #4
0
PNC_CallbackData *PNC_Init_SceneGenerator(GF_RTPChannel *p_chan, GF_RTPHeader *p_hdr, char *default_scene,
										  u32 socketType, u16 socketPort, int debug)
{
	GF_Err e;
	PNC_CallbackData *data = gf_malloc(sizeof(PNC_CallbackData));
	int *i;
	data->chan = p_chan;
	data->hdr = p_hdr;
	data->debug = debug;
	memset( (void*) (data->buffer), '\0', RECV_BUFFER_SIZE_FOR_COMMANDS);
	data->bufferPosition = 0;
	/* Loading the initial scene as the encoding context */
	data->codec = gf_seng_init((void*)data, default_scene);
	if (!data->codec) {
		fprintf(stderr, "Cannot create BIFS Engine from %s\n", default_scene);
		gf_free(data);
		return NULL;
	}
	data->server_socket = NULL;
	data->socket = NULL;

	if (socketType == GF_SOCK_TYPE_TCP)
	{
		data->server_socket = gf_sk_new(socketType);
		e = gf_sk_bind(data->server_socket, NULL, (u16) socketPort, NULL, 0, 0);
		if (e)
			fprintf(stderr, "Failed to bind : %s\n", gf_error_to_string(e));
		e |= gf_sk_listen(data->server_socket, 1);
		if (e)
			fprintf(stderr, "Failed to listen : %s\n", gf_error_to_string(e));
		e |= gf_sk_set_block_mode(data->server_socket, 0);
		if (e)
			fprintf(stderr, "Failed to set block mode : %s\n", gf_error_to_string(e));
		e |= gf_sk_server_mode(data->server_socket, 0);
		if (e)
			fprintf(stderr, "Failed to set server mode : %s\n", gf_error_to_string(e));
	} else {
		data->socket = gf_sk_new(socketType);
		e = gf_sk_bind(data->socket, NULL, (u16) socketPort, NULL, 0, 0);
	}
	/*
	char buffIp[1024];
	u16 port = 0;
	u32 socket_type = 0;
	e |= gf_sk_get_local_ip(data->socket, buffIp);
	e |= gf_sk_get_local_info(data->socket, &port, &socket_type);
	dprintf(DEBUG_RTP_serv_generator, "RTS_serv_generator %s:%d %s\n",
		buffIp, port, socket_type==GF_SOCK_TYPE_UDP?"UDP":"TCP", e==GF_OK?"OK":"ERROR");
	*/
	if (e) {
		fprintf(stderr, "Cannot bind socket to port %d (%s)\n", socketPort, gf_error_to_string(e));
		if (data->socket)
			gf_sk_del(data->socket);
		if (data->server_socket)
			gf_sk_del(data->server_socket);
		gf_free(data);
		return NULL;
	}
	data->extension = gf_malloc(sizeof(PNC_CallbackExt));
	((PNC_CallbackExt * )data->extension)->i = 0;
	((PNC_CallbackExt * )data->extension)->lastTS = 0;
	i = &((PNC_CallbackExt*)data->extension)->i;
	return data;
}
예제 #5
0
int main (const int argc, const char** argv)
{
	GF_Err e;
	Bool run;

	/* location of the configuration file: 0 wait for config on a socket, 1 use the given file */
	u32 config_flag;	
	char config_file_name[MAX_BUF];

	int dest_port;
	unsigned short tcp_port = 0;
	/* Should be fine on WIFI network */
	unsigned short mtu_size = 1492;
	int debug = 0;
	TCP_Input *tcp_conf = NULL;
	GF_Thread *tcp_thread;
	GF_Err th_err_tcp;

	GF_Err th_err_rap;
	RAP_Input *rap_conf;
	GF_Thread *rap_thread;

	CONF_Data *conf;	
	GF_Config *gf_config_file;
	GF_Err res;
	
	GF_Socket *UDP_feedback_socket;
	u32 socketType_for_updates;
	
	PNC_CallbackData * data;
	GF_RTPChannel * chan;
	GF_RTPHeader hdr;
	u32 timer = -1;
	
	GF_Mutex *carrousel_mutex;	
	char sdp_fmt[5000];
	tcp_thread = NULL;
	
	/* init gpac lib */
	gf_sys_init();
	gf_log_set_level(GF_LOG_ERROR);
	gf_log_set_tools(GF_LOG_NETWORK|GF_LOG_RTP|GF_LOG_SCENE|GF_LOG_PARSER|GF_LOG_AUTHOR|GF_LOG_CODING|GF_LOG_SCRIPT);
	
	GF_SAFEALLOC(conf, CONF_Data);
		
	tcp_port = config_flag = 0;
	socketType_for_updates = GF_SOCK_TYPE_UDP;
	if (command_line_parsing(argc, argv, &tcp_port, config_file_name, (int *) &config_flag, &mtu_size, &debug, &socketType_for_updates)){
		print_usage();
		return -1;
	}
	setDebugMode( debug );
	gf_config_file = NULL;
	if (config_flag == 1)
	{
		char *cfg_path;
		char *cfg_fname;
		char *tmp;
		
		cfg_fname = config_file_name;
		cfg_path = config_file_name;
		tmp = strrchr(cfg_fname, GF_PATH_SEPARATOR);
		if (tmp) {
			cfg_fname = tmp+1;
			tmp[0] = 0;
		} else {
			cfg_path = ".";
		}
		gf_config_file = gf_cfg_new(cfg_path, cfg_fname);	
		if (!gf_config_file) {
			fprintf(stderr, "Cannot open config file %s\n", config_file_name);
			return -1;
		} else {
			dprintf(DEBUG_broadcaster, "Using config file %s.\n", config_file_name);
		}
		if (parse_config(gf_config_file, conf, debug)) return -1;
		tcp_port = atoi(conf->config_input_port);
	}
	else
	{
		GF_SAFEALLOC(tcp_conf, TCP_Input);
		tcp_conf->config_flag = &config_flag;
		tcp_conf->RAPtimer = &timer;
		tcp_conf->port = tcp_port;
		tcp_conf->config = conf;
		tcp_thread = gf_th_new("TCPInterface");

		/* Starting the thread which will write the received config in a temporary file */
		th_err_tcp = gf_th_run(tcp_thread, tcp_server, tcp_conf);
		
		fprintf(stdout, "Waiting for configuration on port %d...\n", tcp_conf->port);

		while(config_flag == 0) { 
			gf_sleep(1000); 
		}
		fprintf(stdout, "Configuration File received. Starting Streaming ...\n");
	}
	
	timer = atoi(conf->rap_timer);
	dest_port = atoi(conf->dest_port);
	res = PNC_InitRTP(&chan, (char *)conf->dest_ip, dest_port, mtu_size);
 	if (res != 0) {
		fprintf(stderr, "Cannot initialize RTP output (error: %d)\n", res); 
		exit(1);
	} 

	carrousel_mutex = gf_mx_new("Carrousel");
	data = PNC_Init_SceneGenerator(chan, &hdr, (char *) conf->scene_init_file,
								   socketType_for_updates, (u16) atoi(conf->modif_input_port), debug); 
	if (!data) {
		fprintf(stderr, "Cannot initialize Scene Generator\n"); 
		exit(1);
	}
	data->carrousel_mutex = carrousel_mutex;
	data->RAPsent = 1;
	
	UDP_feedback_socket = gf_sk_new(GF_SOCK_TYPE_UDP);
	e = gf_sk_bind(UDP_feedback_socket, NULL, (u16)atoi(conf->feedback_port), (char*)conf->feedback_ip, (u16)atoi(conf->feedback_port), 0);
	if (e) {
		fprintf(stderr, "Cannot bind socket for bitrate feedback information (%s)\n", gf_error_to_string(e));
	} else {
		e = gf_sk_set_block_mode(UDP_feedback_socket, 1);
		if (e) {
			fprintf(stderr, "Cannot set feedback socket block mode (%s)\n", gf_error_to_string(e));
		}
	}
	data->feedback_socket = UDP_feedback_socket;

	PNC_InitPacketiser(data, sdp_fmt, mtu_size); 
	PNC_SendInitScene(data);

	GF_SAFEALLOC(rap_conf, RAP_Input);
	rap_conf->RAPtimer = &timer;
	rap_conf->carrousel_mutex = carrousel_mutex;
	rap_conf->data = data;
	rap_thread = gf_th_new("RAPGenerator");
	th_err_rap = gf_th_run(rap_thread, RAP_send, rap_conf);

	sdp_generator(data, (char *)conf->dest_ip, sdp_fmt);
	
	run = 1;
	while (run)
	{
		GF_Err e = PNC_processBIFSGenerator(data); 
		if (e) {
			fprintf(stderr, "Cannot Process BIFS data (%s)\n", gf_error_to_string(e));
			break;
		}

		if (has_input()) {
			char c = get_a_char();
			switch (c) {
			case 'q':
				run = 0;
				break;
			}
		}
		gf_sleep(10);
	}

	/* waiting for termination of the RAP thread */
	rap_conf->status = 0;
	while (rap_conf->status != 2)
		gf_sleep(0);
	gf_free(rap_conf);
	gf_th_del(rap_thread);

	/* waiting for termination of the TCP listening thread */
	if (tcp_conf) {
		tcp_conf->status = 0;
		while (tcp_conf->status != 2)
			gf_sleep(0);
		gf_free(tcp_conf);
		gf_th_del(tcp_thread);
	}

	PNC_Close_SceneGenerator(data);
	
	gf_free(conf);
	
	if (gf_config_file)
		gf_cfg_del(gf_config_file);

	gf_mx_del(carrousel_mutex);
	gf_sys_close();
	return 0;
}
예제 #6
0
u32 tcp_server(void *par)
{
	TCP_Input *input = par;
	u32 *timer = input->RAPtimer;
	char buffer[MAX_BUF];
	unsigned char temp[MAX_BUF];
	FILE *fp;
	u32 byte_read;
	int ret;
	GF_Config *gf_config_file;
	GF_Socket *TCP_socket;
	GF_Socket *conn_socket;
	GF_Err e;
	
	int debug = input->debug;
	input->status = 1;

	TCP_socket = gf_sk_new(GF_SOCK_TYPE_TCP);
	e = gf_sk_bind(TCP_socket, NULL, input->port, NULL, 0, 0);
	e = gf_sk_listen(TCP_socket, 1);
	e = gf_sk_set_block_mode(TCP_socket, 1);
	e = gf_sk_server_mode(TCP_socket, 0);
	
	while(input->status == 1)
	{	
		memset(buffer, 0, sizeof(buffer));	
		e = gf_sk_accept(TCP_socket, &conn_socket);
		if (e == GF_OK) {
			memset(buffer, 0, sizeof(buffer));
			e = gf_sk_receive(conn_socket, buffer, MAX_BUF, 0, &byte_read);
		}

		switch (e) {
			case GF_IP_NETWORK_EMPTY:
				gf_sleep(33);
				continue;
			case GF_OK:					
				break;
			default:
				fprintf(stderr, "Error with TCP socket : %s\n", gf_error_to_string(e));
				exit(1);
				break;
		}

		if((*(input->config_flag)) == 0)
		{
			u32 num_retry;
			fp = fopen("temp.cfg", "w+");
			if (!fp) {
				fprintf(stderr, "Error opening temp file for the configuration\n");
				exit(1);
			}
			ret = fwrite(buffer, 1, byte_read, fp);
			fclose(fp);
			
			/* parsing config info */
			gf_config_file = gf_cfg_new(".", "temp.cfg");
			if (!gf_config_file) {
				fprintf(stderr, "Error opening the config file %s\n", gf_error_to_string(e));
				exit(-1);
			}
			parse_config(gf_config_file, input->config, debug);

			/* Acknowledging the configuration */ 
			gf_sk_send(conn_socket, "OK\n", 3);

			memset(temp, 0, sizeof(temp));
			fp = fopen(input->config->scene_init_file, "w+");
			if (!fp) {
				fprintf(stderr, "Error opening temp file for reception of the initial scene\n");
				exit(1);
			}
			num_retry=10;

			while (1)
			{
				GF_Err e = gf_sk_receive(conn_socket, temp, sizeof(temp), 0, &byte_read);

				if (e == GF_OK) {
					fwrite(temp, 1, byte_read, fp);
				} else if (e==GF_IP_NETWORK_EMPTY) {
					num_retry--;
					if (!num_retry)
						break;
					gf_sleep(1);
				} else {
					fprintf(stderr, "Error receiving initial scene: %s\n", gf_error_to_string(e));
					break;
				}
			}
			fclose(fp);
			*(input->config_flag) = 1;
		}
		/* we only wait now for the config updates */
		if ( (*(input->config_flag)) == 1) {
			ret = sscanf(buffer, "DelaiMax=%d\n", timer);							
			fprintf(stdout, "RAP timer changed, now : %d\n", *timer);
		}
		gf_sk_del(conn_socket);
	}

	input->status = 2;
	return GF_OK;
}
예제 #7
0
static void gf_dm_connect(GF_DownloadSession *sess)
{
	GF_Err e;
	u16 proxy_port = 0;
	const char *proxy;
	if (!sess->sock) {
		//sess->num_retry = 40;
		sess->sock = gf_sk_new(GF_SOCK_TYPE_TCP);
	}

	/*connect*/
	sess->status = GF_NETIO_SETUP;
	gf_dm_sess_notify_state(sess, sess->status, GF_OK);
	
	/*PROXY setup*/
	proxy = gf_cfg_get_key(sess->dm->cfg, "HTTPProxy", "Enabled");
	if (proxy && !strcmp(proxy, "yes")) {
		proxy = gf_cfg_get_key(sess->dm->cfg, "HTTPProxy", "Port");
		proxy_port = proxy ? atoi(proxy) : 80;
		
		proxy = gf_cfg_get_key(sess->dm->cfg, "HTTPProxy", "Name");
	} else {
		proxy = NULL;
	}

	if (proxy) {
		e = gf_sk_connect(sess->sock, (char *) proxy, proxy_port);
	} else {
		e = gf_sk_connect(sess->sock, sess->server_name, sess->port);
	}
	/*retry*/
	if ((e == GF_IP_SOCK_WOULD_BLOCK) && sess->num_retry) {
		sess->status = GF_NETIO_SETUP;
		sess->num_retry--;
		return;
	}

	/*failed*/
	if (e) {
		sess->status = GF_NETIO_STATE_ERROR;
		sess->last_error = e;
		gf_dm_sess_notify_state(sess, sess->status, e);
		return;
	} 
	
	sess->status = GF_NETIO_CONNECTED;
	gf_dm_sess_notify_state(sess, GF_NETIO_CONNECTED, GF_OK);
	gf_sk_set_block_mode(sess->sock, 1);
	gf_dm_configure_cache(sess);

#ifdef GPAC_HAS_SSL
	/*socket is connected, configure SSL layer*/
	if (!sess->ssl && sess->dm->ssl_ctx && (sess->flags & GF_DOWNLOAD_SESSION_USE_SSL)) {
		int ret;
		long vresult;
		char common_name[256];
	    X509 *cert;
		Bool success = 1;

		sess->ssl = SSL_new(sess->dm->ssl_ctx);
		SSL_set_fd(sess->ssl, gf_sk_get_handle(sess->sock));
		SSL_set_connect_state(sess->ssl);
		ret = SSL_connect(sess->ssl);
		assert(ret>0);

		cert = SSL_get_peer_certificate(sess->ssl);       
		/*if we have a cert, check it*/
		if (cert) {
			vresult = SSL_get_verify_result(sess->ssl);
			if (vresult != X509_V_OK) success = 0;
			else {
				common_name[0] = 0;
				X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, common_name, sizeof (common_name));
				if (!pattern_match(common_name, sess->server_name)) success = 0;
			}
			X509_free(cert);

			if (!success) {
				gf_dm_disconnect(sess);
				sess->status = GF_NETIO_STATE_ERROR;
				sess->last_error = GF_AUTHENTICATION_FAILURE;
				gf_dm_sess_notify_state(sess, sess->status, sess->last_error);
			}
		}
	}
#endif
}