📄 symbian_net.cpp
字号:
//binds the given socket to the specified port. If ReUse is true//this will enable reuse of ports on a single machineGF_Err gf_sk_bind(GF_Socket *sock, u16 port, char *peer_name, u16 peer_port, u32 options){#ifdef GPAC_IPV6 struct addrinfo *res, *aip; int af; u32 type;#else size_t addrlen; struct sockaddr_in LocalAdd; struct hostent *Host; char buf[GF_MAX_IP_NAME_LEN];#endif s32 ret; s32 optval; if (!sock || sock->socket) return GF_BAD_PARAM; #ifdef GPAC_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) return GF_IP_CONNECTION_FAILURE;#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 = res->ai_addrlen; freeaddrinfo(res); } res = gf_sk_get_ipv6_addr(NULL, port, af, AI_PASSIVE, type); 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;#ifdef WIN32 /*recurrent pb with win32: this is not a true dual-stack, listening with a v6 socket for v4 source is most of the time failing. On win32, only move for connection-less V6 sockets if no other way available*/ if (aip->ai_next && (aip->ai_next->ai_family==PF_INET)) continue;#endif sock->socket = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol); if (sock->socket == INVALID_SOCKET) { sock->socket = (SOCKET)NULL; continue; } if (options & GF_SOCK_REUSE_PORT) { optval = 1; setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval)); } if (sock->flags & GF_SOCK_NON_BLOCKING) gf_sk_set_block_mode(sock, 1); ret = bind(sock->socket, aip->ai_addr, aip->ai_addrlen); if (ret == SOCKET_ERROR) { closesocket(sock->socket); sock->socket = (SOCKET)NULL; continue; } if (aip->ai_family==PF_INET6) sock->flags |= GF_SOCK_IS_IPV6; else sock->flags &= ~GF_SOCK_IS_IPV6; if (peer_name && peer_port) sock->flags |= GF_SOCK_HAS_SOURCE; freeaddrinfo(res); return GF_OK; } freeaddrinfo(res); return GF_IP_CONNECTION_FAILURE;#else 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); sock->flags &= ~GF_SOCK_IS_IPV6; } memset((void *) &LocalAdd, 0, sizeof(LocalAdd)); ret = gethostname(buf, GF_MAX_IP_NAME_LEN); if (ret == SOCKET_ERROR) return GF_IP_ADDRESS_NOT_FOUND; /*get the IP address*/ Host = gethostbyname(buf); if (Host == NULL) return GF_IP_ADDRESS_NOT_FOUND; /*setup the address*/ memcpy((char *) &LocalAdd.sin_addr, Host->h_addr_list[0], sizeof(LocalAdd.sin_addr)); LocalAdd.sin_family = AF_INET; LocalAdd.sin_addr.s_addr = INADDR_ANY; LocalAdd.sin_port = htons(port); 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)); } /*bind the socket*/ ret = bind(sock->socket, (struct sockaddr *) &LocalAdd, addrlen); if (ret == SOCKET_ERROR) return 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) return GF_IP_ADDRESS_NOT_FOUND; memcpy((char *) &sock->dest_addr.sin_addr, Host->h_addr_list[0], sizeof(u32)); } sock->flags |= GF_SOCK_HAS_SOURCE; }#endif return GF_OK;}//send length bytes of a bufferGF_Err gf_sk_send(GF_Socket *sock, char *buffer, u32 length){ GF_Err e; u32 Count; s32 Res;#ifndef __SYMBIAN32__ u32 ready; struct timeval timeout; fd_set Group;#endif e = GF_OK; //the socket must be bound or connected if (!sock || !sock->socket) return GF_BAD_PARAM;#ifndef __SYMBIAN32__ //can we write? FD_ZERO(&Group); FD_SET(sock->socket, &Group); timeout.tv_sec = 0; timeout.tv_usec = SOCK_MICROSEC_WAIT; ready = select(sock->socket+1, NULL, &Group, NULL, &timeout); if (ready == SOCKET_ERROR) { switch (LASTSOCKERROR) { case EAGAIN: return GF_IP_SOCK_WOULD_BLOCK; default: return GF_IP_NETWORK_FAILURE; } } //should never happen (to check: is writeability is guaranteed for not-connected sockets) if (!ready || !FD_ISSET(sock->socket, &Group)) { return GF_IP_NETWORK_EMPTY; }#endif //direct writing Count = 0; while (Count < length) { if (sock->flags & GF_SOCK_IS_TCP) { Res = send(sock->socket, (char *) &buffer[Count], length - Count, 0); } else { Res = sendto(sock->socket, (char *) &buffer[Count], length - Count, 0, (struct sockaddr *) &sock->dest_addr, sock->dest_addr_len); } if (Res == SOCKET_ERROR) { switch (LASTSOCKERROR) { case EAGAIN: return GF_IP_SOCK_WOULD_BLOCK;#ifndef __SYMBIAN32__ case ENOTCONN: case ECONNRESET: return GF_IP_CONNECTION_CLOSED;#endif default: return GF_IP_NETWORK_FAILURE; } } Count += Res; } return GF_OK;}GF_EXPORTu32 gf_sk_is_multicast_address(char *multi_IPAdd){#ifdef GPAC_IPV6 u32 val; struct addrinfo *res; if (!multi_IPAdd) return 0; res = gf_sk_get_ipv6_addr(multi_IPAdd, 0, AF_UNSPEC, AI_PASSIVE, SOCK_STREAM); if (!res) return 0; val = 0; if (res->ai_addr->sa_family == AF_INET) { val = IN_MULTICAST(ntohl(((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr)); } else if (res->ai_addr->sa_family == AF_INET6) { val = IN6_IS_ADDR_MULTICAST(& ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr); } freeaddrinfo(res); return val;#else if (!multi_IPAdd) return 0; return ((htonl(inet_addr(multi_IPAdd)) >> 8) & 0x00f00000) == 0x00e00000; #endif}GF_Err gf_sk_setup_multicast(GF_Socket *sock, 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_IPV6 struct sockaddr *addr; struct addrinfo *res, *aip; u32 type;#else u_long local_add_id;#endif 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;#ifdef GPAC_IPV6 type = (sock->flags & GF_SOCK_IS_TCP) ? SOCK_STREAM : SOCK_DGRAM; 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 = (SOCKET)NULL; continue; } /*enable address reuse*/ optval = SO_REUSEADDR; setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval)); /*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 = aip->ai_addrlen; if (!NoBind) { ret = bind(sock->socket, aip->ai_addr, aip->ai_addrlen); if (ret == SOCKET_ERROR) { closesocket(sock->socket); sock->socket = (SOCKET)NULL; 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; ret = setsockopt(sock->socket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *) &M_reqV6, sizeof(M_reqV6)); if (ret == SOCKET_ERROR) return GF_IP_CONNECTION_FAILURE; /*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; } #else /*enable address reuse*/ optval = SO_REUSEADDR; setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, SSO_CAST &optval, sizeof(optval)); 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) 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; 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; return GF_OK;}//fetch nb bytes on a socket and fill the buffer from startFrom//length is the allocated size of the receiving buffer//BytesRead is the number of bytes read from the networkGF_Err gf_sk_receive(GF_Socket *sock, char *buffer, u32 length, u32 startFrom, u32 *BytesRead){ GF_Err e; s32 res;#ifndef __SYMBIAN32__ u32 ready; struct timeval timeout; fd_set Group;#endif e = GF_OK; *BytesRead = 0; if (!sock->socket) return GF_BAD_PARAM; if (startFrom >= length) return GF_IO_ERR;#ifndef __SYMBIAN32__ //can we read? FD_ZERO(&Group); FD_SET(sock->socket, &Group); timeout.tv_sec = 0; timeout.tv_usec = SOCK_MICROSEC_WAIT; res = 0; ready = select(sock->socket+1, &Group, NULL, NULL, &timeout); if (ready == SOCKET_ERROR) { switch (LASTSOCKERROR) { case EAGAIN: return GF_IP_SOCK_WOULD_BLOCK; default: GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[socket] cannot select (error %d)\n", LASTSOCKERROR)); return GF_IP_NETWORK_FAILURE; } } if (!FD_ISSET(sock->socket, &Group)) { return GF_IP_NETWORK_EMPTY; }#endif if (sock->flags & GF_SOCK_HAS_SOURCE) res = recvfrom(sock->socket, (char *) buffer + startFrom, length - startFrom, 0, (struct sockaddr *)&sock->dest_addr, &sock->dest_addr_len); else res = recv(sock->socket, (char *) buffer + startFrom, length - startFrom, 0); if (res == SOCKET_ERROR) { res = LASTSOCKERROR; switch (res) { case EAGAIN: return GF_IP_SOCK_WOULD_BLOCK;#ifndef __SYMBIAN32__ case EMSGSIZE: return GF_OUT_OF_MEM; case ENOTCONN: case ECONNRESET: case ECONNABORTED: return GF_IP_CONNECTION_CLOSED;#endif default: GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[socket] cannot read from network (%d)\n", LASTSOCKERROR)); return GF_IP_NETWORK_FAILURE; } } *BytesRead = res; return GF_OK;}GF_Err gf_sk_listen(GF_Socket *sock, u32 MaxConnection){ s32 i; if (!sock || !sock->socket) return GF_BAD_PARAM; if (MaxConnection >= SOMAXCONN) MaxConnection = SOMAXCONN;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -