//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 }
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; }
//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; }
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; }
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; }
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; }
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 }