GF_EXPORT char *gf_rtp_streamer_format_sdp_header(char *app_name, char *ip_dest, char *session_name, char *iod64) { u64 size; char *sdp; FILE *tmp = gf_temp_file_new(); if (!tmp) return NULL; /* write SDP header*/ fprintf(tmp, "v=0\n"); fprintf(tmp, "o=%s 3326096807 1117107880000 IN IP%d %s\n", app_name, gf_net_is_ipv6(ip_dest) ? 6 : 4, ip_dest); fprintf(tmp, "s=%s\n", (session_name ? session_name : "GPAC Scene Streaming Session")); fprintf(tmp, "c=IN IP%d %s\n", gf_net_is_ipv6(ip_dest) ? 6 : 4, ip_dest); fprintf(tmp, "t=0 0\n"); if (iod64) fprintf(tmp, "a=mpeg4-iod:\"data:application/mpeg4-iod;base64,%s\"\n", iod64); gf_f64_seek(tmp, 0, SEEK_END); size = gf_f64_tell(tmp); gf_f64_seek(tmp, 0, SEEK_SET); sdp = gf_malloc(sizeof(char) * (size_t)(size+1)); size = fread(sdp, 1, (size_t)size, tmp); sdp[size] = 0; fclose(tmp); return sdp; }
int sdp_generator(PNC_CallbackData *data, char *ip_dest, char *sdp_fmt) { GF_SceneEngine *codec; GF_ESD *esd = NULL; u32 size,size64; char *buffer; char buf64[5000]; FILE *fp; int ret; char temp[5000]; u16 port; u32 socket_type; gf_sk_get_local_info(data->chan->rtp, &port, &socket_type); fp = fopen("broadcaster.sdp", "w+"); if(fp == NULL) { fprintf(stderr, "Cannot open SDP file broadcaster.sdp\n"); exit(1); } ret = fwrite("v=0\n", 1, 4, fp); sprintf(temp, "o=GpacBroadcaster 3326096807 1117107880000 IN IP%d %s\n", gf_net_is_ipv6(ip_dest) ? 6 : 4, ip_dest); ret = fwrite(temp, 1, strlen(temp), fp); ret = fwrite("s=MPEG4Broadcaster\n", 1, 19, fp); sprintf(temp, "c=IN IP%d %s\n", gf_net_is_ipv6(ip_dest) ? 6 : 4, ip_dest); ret = fwrite(temp, 1, strlen(temp), fp); ret = fwrite("t=0 0\n", 1, 6, fp); codec = (GF_SceneEngine *) data->codec; if (codec) { buffer = NULL; size = 0; gf_odf_desc_write((GF_Descriptor *) codec->ctx->root_od, &buffer, &size); esd = gf_list_get(codec->ctx->root_od->ESDescriptors, 0); size64 = gf_base64_encode((unsigned char *) buffer, size, (unsigned char *) buf64, 2000); buf64[size64] = 0; free(buffer); sprintf(temp, "a=mpeg4-iod:\"data:application/mpeg4-iod;base64,%s\"\n", buf64); ret = fwrite(temp, 1, strlen(temp), fp); } sprintf(temp, "m=application %d RTP/AVP 96\n", port); ret = fwrite(temp, 1, strlen(temp), fp); ret = fwrite("a=rtpmap:96 mpeg4-generic/1000\n", 1, 31, fp); if (esd) { sprintf(temp, "a=mpeg4-esid:%d\n", esd->ESID); ret = fwrite(temp, 1, strlen(temp), fp); } sprintf(temp, "%s\n", sdp_fmt); ret = fwrite(temp, 1, strlen(temp), fp); fflush(fp); fclose(fp); dprintf(DEBUG_sdp_generator, "SDP file generated in broadcaster.sdp\n"); return GF_OK; }
int sdp_generator(PNC_CallbackData * data, char *ip_dest, char *sdp_fmt) { GF_BifsEngine *codec; GF_ESD *esd; u32 size,size64; char *buffer; char buf64[5000]; FILE *fp; int ret; char temp[5000]; u16 port; u32 socket_type; // fonctions necessaires pour recuperer les informations necessaires a la construction du fichier gf_sk_get_local_info(data->chan->rtp, &port, &socket_type); // fprintf(stdout, "%s --------- %d\n", ip_adresse, port); fp = fopen("broadcaster.sdp", "w+"); if(fp == NULL) { fprintf(stdout, "[broadcaster] : erreur, probleme a ouvrir file temp pour scene initiale\n"); exit(1); } // ecriture du fichier SDP ret = fwrite("v=0\n", 1, 4, fp); sprintf(temp, "o=GpacBroadcaster 3326096807 1117107880000 IN IP%d %s\n", gf_net_is_ipv6(ip_dest) ? 6 : 4, ip_dest); ret = fwrite(temp, 1, strlen(temp), fp); ret = fwrite("s=MPEG4Broadcaster\n", 1, 19, fp); sprintf(temp, "c=IN IP%d %s\n", gf_net_is_ipv6(ip_dest) ? 6 : 4, ip_dest); ret = fwrite(temp, 1, strlen(temp), fp); ret = fwrite("t=0 0\n", 1, 6, fp); // GF_BIFSEngine codec = (GF_BifsEngine *) data->codec; buffer = NULL; size = 0; gf_odf_desc_write((GF_Descriptor *) codec->ctx->root_od, &buffer, &size); esd = gf_list_get(codec->ctx->root_od->ESDescriptors, 0); //encode in Base64 the iod size64 = gf_base64_encode((unsigned char *) buffer, size, (unsigned char *) buf64, 2000); // size64 = gf_base64_encode(buffer, size, buf64, 2000); buf64[size64] = 0; free(buffer); // fprintf(stdout, "a=mpeg4-iod:\"data:application/mpeg4-iod;base64,%s\"\n", buf64); sprintf(temp, "a=mpeg4-iod:\"data:application/mpeg4-iod;base64,%s\"\n", buf64); ret = fwrite(temp, 1, strlen(temp), fp); sprintf(temp, "m=application %d RTP/AVP 96\n", port); ret = fwrite(temp, 1, strlen(temp), fp); ret = fwrite("a=rtpmap:96 mpeg4-generic/1000\n", 1, 31, fp); sprintf(temp, "a=mpeg4-esid:%d\n", esd->ESID); ret = fwrite(temp, 1, strlen(temp), fp); // fprintf(stdout, "%s\n", sdp_fmt); sprintf(temp, "%s\n", sdp_fmt); ret = fwrite(temp, 1, strlen(temp), fp); fclose(fp); fprintf(stdout, "[sdp generator] : fichier SDP generater in broadcaster.sdp\n"); return GF_OK; }
static GF_Err gf_isom_streamer_setup_sdp(GF_ISOMRTPStreamer *streamer, char*sdpfilename, char **out_sdp_buffer) { GF_RTPTrack *track; FILE *sdp_out; char filename[GF_MAX_PATH]; char sdpLine[20000]; strcpy(filename, sdpfilename ? sdpfilename : "videosession.sdp"); sdp_out = gf_f64_open(filename, "wt"); if (!sdp_out) return GF_IO_ERR; if (!out_sdp_buffer) { sprintf(sdpLine, "v=0"); fprintf(sdp_out, "%s\n", sdpLine); sprintf(sdpLine, "o=MP4Streamer 3357474383 1148485440000 IN IP%d %s", gf_net_is_ipv6(streamer->dest_ip) ? 6 : 4, streamer->dest_ip); fprintf(sdp_out, "%s\n", sdpLine); sprintf(sdpLine, "s=livesession"); fprintf(sdp_out, "%s\n", sdpLine); sprintf(sdpLine, "i=This is an MP4 time-sliced Streaming demo"); fprintf(sdp_out, "%s\n", sdpLine); sprintf(sdpLine, "u=http://gpac.sourceforge.net"); fprintf(sdp_out, "%s\n", sdpLine); sprintf(sdpLine, "e=admin@"); fprintf(sdp_out, "%s\n", sdpLine); sprintf(sdpLine, "c=IN IP%d %s", gf_net_is_ipv6(streamer->dest_ip) ? 6 : 4, streamer->dest_ip); fprintf(sdp_out, "%s\n", sdpLine); sprintf(sdpLine, "t=0 0"); fprintf(sdp_out, "%s\n", sdpLine); sprintf(sdpLine, "a=x-copyright: Streamed with GPAC (C)2000-200X - http://gpac.sourceforge.net\n"); fprintf(sdp_out, "%s\n", sdpLine); } track = streamer->stream; while (track) { char *sdp_media=NULL; const char *KMS = NULL; char *dsi = NULL; u32 w, h; u32 dsi_len = 0; GF_DecoderConfig *dcd = gf_isom_get_decoder_config(streamer->isom, track->track_num, 1); if (dcd && dcd->decoderSpecificInfo) { dsi = dcd->decoderSpecificInfo->data; dsi_len = dcd->decoderSpecificInfo->dataLength; } w = h = 0; if (gf_isom_get_media_type(streamer->isom, track->track_num) == GF_ISOM_MEDIA_VISUAL) { gf_isom_get_visual_info(streamer->isom, track->track_num, 1, &w, &h); } gf_isom_get_ismacryp_info(streamer->isom, track->track_num, 1, NULL, NULL, NULL, NULL, &KMS, NULL, NULL, NULL); /*TODO retrieve DIMS content encoding from track to set the flags */ gf_rtp_streamer_append_sdp_extended(track->rtp, gf_isom_get_track_id(streamer->isom, track->track_num), dsi, dsi_len, streamer->isom, track->track_num, (char *)KMS, w, h, &sdp_media); if (sdp_media) { fprintf(sdp_out, "%s", sdp_media); gf_free(sdp_media); } if (dcd) gf_odf_desc_del((GF_Descriptor *)dcd); track = track->next; } fprintf(sdp_out, "\n"); fclose(sdp_out); if (out_sdp_buffer) { u64 size; sdp_out = gf_f64_open(filename, "r"); gf_f64_seek(sdp_out, 0, SEEK_END); size = gf_f64_tell(sdp_out); gf_f64_seek(sdp_out, 0, SEEK_SET); if (*out_sdp_buffer) gf_free(*out_sdp_buffer); *out_sdp_buffer = gf_malloc(sizeof(char)*(size_t)(size+1)); size = fread(*out_sdp_buffer, 1, (size_t)size, sdp_out); fclose(sdp_out); (*out_sdp_buffer)[size]=0; } return GF_OK; }
static GF_Err gf_isom_streamer_setup_sdp(GF_ISOMRTPStreamer *streamer, char*sdpfilename, char **out_sdp_buffer) { GF_RTPTrack *track; FILE *sdp_out; char filename[GF_MAX_PATH]; char sdpLine[20000]; u32 t, count; u8 *payload_type; strcpy(filename, sdpfilename ? sdpfilename : "videosession.sdp"); sdp_out = gf_fopen(filename, "wt"); if (!sdp_out) return GF_IO_ERR; if (!out_sdp_buffer) { sprintf(sdpLine, "v=0"); fprintf(sdp_out, "%s\n", sdpLine); sprintf(sdpLine, "o=MP4Streamer 3357474383 1148485440000 IN IP%d %s", gf_net_is_ipv6(streamer->dest_ip) ? 6 : 4, streamer->dest_ip); fprintf(sdp_out, "%s\n", sdpLine); sprintf(sdpLine, "s=livesession"); fprintf(sdp_out, "%s\n", sdpLine); sprintf(sdpLine, "i=This is an MP4 time-sliced Streaming demo"); fprintf(sdp_out, "%s\n", sdpLine); sprintf(sdpLine, "u=http://gpac.sourceforge.net"); fprintf(sdp_out, "%s\n", sdpLine); sprintf(sdpLine, "e=admin@"); fprintf(sdp_out, "%s\n", sdpLine); sprintf(sdpLine, "c=IN IP%d %s", gf_net_is_ipv6(streamer->dest_ip) ? 6 : 4, streamer->dest_ip); fprintf(sdp_out, "%s\n", sdpLine); sprintf(sdpLine, "t=0 0"); fprintf(sdp_out, "%s\n", sdpLine); sprintf(sdpLine, "a=x-copyright: Streamed with GPAC (C)2000-200X - http://gpac.sourceforge.net"); fprintf(sdp_out, "%s\n", sdpLine); if (streamer->base_track) { sprintf(sdpLine, "a=group:DDP L%d", streamer->base_track); fprintf(sdp_out, "%s", sdpLine); count = gf_isom_get_track_count(streamer->isom); for (t = 0; t < count; t++) { if (gf_isom_has_track_reference(streamer->isom, t+1, GF_ISOM_REF_BASE, gf_isom_get_track_id(streamer->isom, streamer->base_track))) { sprintf(sdpLine, " L%d", t+1); fprintf(sdp_out, "%s", sdpLine); } } fprintf(sdp_out, "\n"); } } /*prepare array of payload type*/ count = gf_isom_get_track_count(streamer->isom); payload_type = (u8 *)gf_malloc(count * sizeof(u8)); track = streamer->stream; while (track) { payload_type[track->track_num-1] = gf_rtp_streamer_get_payload_type(track->rtp); track = track->next; } track = streamer->stream; while (track) { char *sdp_media=NULL; const char *KMS = NULL; char *dsi = NULL; u32 w, h; u32 dsi_len = 0; GF_DecoderConfig *dcd; //use inspect mode so that we don't aggregate xPS from the base in the enhancement ESD gf_isom_set_nalu_extract_mode(streamer->isom, track->track_num, GF_ISOM_NALU_EXTRACT_INSPECT); dcd = gf_isom_get_decoder_config(streamer->isom, track->track_num, 1); if (dcd && dcd->decoderSpecificInfo) { dsi = dcd->decoderSpecificInfo->data; dsi_len = dcd->decoderSpecificInfo->dataLength; } w = h = 0; if (gf_isom_get_media_type(streamer->isom, track->track_num) == GF_ISOM_MEDIA_VISUAL) { gf_isom_get_visual_info(streamer->isom, track->track_num, 1, &w, &h); } gf_isom_get_ismacryp_info(streamer->isom, track->track_num, 1, NULL, NULL, NULL, NULL, &KMS, NULL, NULL, NULL); /*TODO retrieve DIMS content encoding from track to set the flags */ gf_rtp_streamer_append_sdp_extended(track->rtp, gf_isom_get_track_id(streamer->isom, track->track_num), dsi, dsi_len, streamer->isom, track->track_num, (char *)KMS, w, h, &sdp_media); if (streamer->base_track) gf_rtp_streamer_append_sdp_decoding_dependency(streamer->isom, track->track_num, payload_type, &sdp_media); if (sdp_media) { fprintf(sdp_out, "%s", sdp_media); gf_free(sdp_media); } if (dcd) gf_odf_desc_del((GF_Descriptor *)dcd); track = track->next; } fprintf(sdp_out, "\n"); gf_fclose(sdp_out); if (out_sdp_buffer) { u64 size; sdp_out = gf_fopen(filename, "r"); gf_fseek(sdp_out, 0, SEEK_END); size = gf_ftell(sdp_out); gf_fseek(sdp_out, 0, SEEK_SET); if (*out_sdp_buffer) gf_free(*out_sdp_buffer); *out_sdp_buffer = gf_malloc(sizeof(char)*(size_t)(size+1)); size = fread(*out_sdp_buffer, 1, (size_t)size, sdp_out); gf_fclose(sdp_out); (*out_sdp_buffer)[size]=0; } gf_free(payload_type); return GF_OK; }
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; }
//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 }