static s32 tcp_socket(void) { s32 s, res; s = net_socket(PF_INET, SOCK_STREAM, IPPROTO_IP); if (s < 0) return s; // Switch off Nagle with TCP_NODELAY u32 nodelay = 1; net_setsockopt(s,IPPROTO_TCP,TCP_NODELAY,&nodelay,sizeof(nodelay)); res = net_fcntl(s, F_GETFL, 0); if (res < 0) { net_close(s); return res; } res = net_fcntl(s, F_SETFL, res | IOS_O_NONBLOCK); if (res < 0) { net_close(s); return res; } return s; }
void network_init() { struct sockaddr_in my_name; my_name.sin_family = AF_INET; my_name.sin_port = htons(SERVER_PORT); my_name.sin_addr.s_addr = htonl(INADDR_ANY); net_init(); server_socket = net_socket(AF_INET, SOCK_STREAM, 0); int yes = 1; net_setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); while(net_bind(server_socket, (struct sockaddr*)&my_name, sizeof(my_name)) < 0) { } net_listen(server_socket, 0); struct sockaddr_in client_info; socklen_t ssize = sizeof(client_info); client_socket = net_accept(server_socket, (struct sockaddr*)&client_info, &ssize); network_printf("Hello world!\n"); }
int net_set_reuseaddress(int fd, int toggle) { int ret; ret = net_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &toggle, sizeof(toggle)); if (ret == -1) { net_error_out(fd, "net_set_reuseaddress"); } return ret; }
int net_set_keepalive(int fd, int toggle) { int ret; ret = net_setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &toggle, sizeof(toggle)); if (ret == -1) { net_error_out(fd, "net_set_keepalive"); } return ret; }
int net_set_linger(int fd, int toggle) { int ret; ret = net_setsockopt(fd, SOL_SOCKET, SO_LINGER, &toggle, sizeof(toggle)); if (ret == -1) { net_error_out(fd, "net_set_linger"); } return ret; }
/* NOTE: Possibly only supported on BSD and OSX? */ int net_set_nosigpipe(int fd, int toggle) { int ret = -1; #ifdef SO_NOSIGPIPE ret = net_setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &toggle, sizeof(toggle)); if (ret == -1) { net_error_out(fd, "net_set_nosigpipe"); } #endif return ret; }
int WaitForConnection(int& server_socket) { int addrlen; struct sockaddr_in my_name, peer_name; int status; server_socket = net_socket(AF_INET, SOCK_STREAM, 0); if (server_socket == -1) { printf("Failed to create server socket\n"); } int yes = 1; net_setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); memset(&my_name, 0, sizeof(my_name)); my_name.sin_family = AF_INET; my_name.sin_port = htons(DFF_CONN_PORT); my_name.sin_addr.s_addr = htonl(INADDR_ANY); status = net_bind(server_socket, (struct sockaddr*)&my_name, sizeof(my_name)); if (status == -1) { printf("Failed to bind server socket\n"); } status = net_listen(server_socket, 5); // TODO: Change second parameter.. if (status == -1) { printf("Failed to listen on server socket\n"); } printf("Listening now!\n"); int client_socket = -1; struct sockaddr_in client_info; socklen_t ssize = sizeof(client_info); int new_socket = net_accept(server_socket, (struct sockaddr*)&client_info, &ssize); if (new_socket < 0) { printf("accept failed!\n"); } else { client_socket = new_socket; printf("accept succeeded and returned %d\n", client_socket); } return client_socket; }
int net_is_ipv6_supported() { if (is_ipv6_supported == -1) { int ret = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (ret == -1) { #ifdef WINSOCK if (net_error() == WSAEAFNOSUPPORT) #else if (net_error() == EAFNOSUPPORT) #endif { LOG_TRACE("net_is_ipv6_supported(): IPv6 is not supported on this system."); is_ipv6_supported = 0; return 0; } net_error_out(ret, "net_is_ipv6_supported"); } else { #ifdef SOCK_DUAL_STACK_OPT int off = 0; if (net_setsockopt(ret, IPPROTO_IPV6, SOCK_DUAL_STACK_OPT, (char*) &off, sizeof(off)) < 0) { LOG_ERROR("net_socket_create(): Dual stack IPv6/IPv4 is not supported."); is_ipv6_supported = 0; } else { is_ipv6_supported = 1; } #else is_ipv6_supported = 0; #endif net_close(ret); } } return is_ipv6_supported; }
int net_socket_create(int af, int type, int protocol) { int sd = socket(af, type, protocol); if (sd == -1) { net_error_out(sd, "net_socket_create"); return -1; } #ifdef SOCK_DUAL_STACK_OPT /* BSD style */ if (af == AF_INET6) { int off = 0; if (net_setsockopt(sd, IPPROTO_IPV6, SOCK_DUAL_STACK_OPT, (char*) &off, sizeof(off)) < 0) { LOG_ERROR("net_socket_create(): Cannot set socket to dual stack mode IPv6/IPv4 (%d - %s).", net_error(), net_error_string(net_error())); } } #endif return sd; }
int net_set_recvbuf_size(int fd, size_t size) { return net_setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); }
int net_set_sendbuf_size(int fd, size_t size) { return net_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); }
/* return non zero if error */ static int tcp_open(URLContext *h, const char *uri, int flags) { struct addrinfo hints = { 0 }, *ai, *cur_ai; int port, fd = -1; TCPContext *s = h->priv_data; int listen_socket = 0; const char *p; char buf[256]; int ret; socklen_t optlen; int timeout = 50; char hostname[1024],proto[1024],path[1024]; char portstr[10]; av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); if (strcmp(proto,"tcp") || port <= 0 || port >= 65536) return AVERROR(EINVAL); p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "listen", p)) listen_socket = 1; if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { timeout = strtol(buf, NULL, 10); } } hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%d", port); ret = getaddrinfo(hostname, portstr, &hints, &ai); if (ret) { av_log(h, AV_LOG_ERROR, "Failed to resolve hostname %s: %s\n", hostname, gai_strerror(ret)); return AVERROR(EIO); } cur_ai = ai; restart: ret = AVERROR(EIO); fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); if (fd < 0) goto fail; if (listen_socket) { int fd1; int reuse = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); ret = bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); if (ret) { ret = ff_neterrno(); goto fail1; } listen(fd, 1); fd1 = accept(fd, NULL, NULL); if (fd1 < 0) { ret = ff_neterrno(); goto fail1; } closesocket(fd); fd = fd1; ff_socket_nonblock(fd, 1); } else { redo: #ifdef GEKKO // turn off Nagle u32 nodelay = 1; net_setsockopt(cur_ai->ai_family, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay)); #endif ff_socket_nonblock(fd, 1); ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); } if (ret < 0) { struct pollfd p = {fd, POLLOUT, 0}; ret = ff_neterrno(); if (ret == AVERROR(EINTR)) { if (ff_check_interrupt(&h->interrupt_callback)) { ret = AVERROR_EXIT; goto fail1; } goto redo; } if (ret != AVERROR(EINPROGRESS) && ret != AVERROR(EAGAIN)) goto fail; /* wait until we are connected or until abort */ while(timeout--) { if (ff_check_interrupt(&h->interrupt_callback)) { ret = AVERROR_EXIT; goto fail1; } ret = poll(&p, 1, 100); if (ret > 0) break; } if (ret <= 0) { ret = AVERROR(ETIMEDOUT); goto fail; } /* test error */ optlen = sizeof(ret); getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen); if (ret != 0) { av_log(h, AV_LOG_ERROR, "TCP connection to %s:%d failed: %s\n", hostname, port, strerror(ret)); ret = AVERROR(ret); goto fail; } } h->is_streamed = 1; s->fd = fd; freeaddrinfo(ai); return 0; fail: if (cur_ai->ai_next) { /* Retry with the next sockaddr */ cur_ai = cur_ai->ai_next; if (fd >= 0) closesocket(fd); goto restart; } fail1: if (fd >= 0) closesocket(fd); freeaddrinfo(ai); return ret; }
static int connect2Server_with_af(char *host, int port, int af,int verb) { int socket_server_fd; int err; socklen_t err_len; int ret,count = 0; fd_set set; struct timeval tv; union { struct sockaddr_in four; #ifdef HAVE_AF_INET6 struct sockaddr_in6 six; #endif } server_address; size_t server_address_size; void *our_s_addr; // Pointer to sin_addr or sin6_addr struct hostent *hp=NULL; char buf[255]; #if HAVE_WINSOCK2_H unsigned long val; int to; #else struct timeval to; #endif #if HAVE_WINSOCK2_H && defined(HAVE_AF_INET6) // our winsock name resolution code can not handle IPv6 if (af == AF_INET6) { mp_msg(MSGT_NETWORK, MSGL_WARN, "IPv6 not supported for winsock2\n"); return TCP_ERROR_FATAL; } #endif socket_server_fd = socket(af, SOCK_STREAM, 0); if( socket_server_fd==-1 ) { // mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to create %s socket:\n", af2String(af)); return TCP_ERROR_FATAL; } #if defined(SO_RCVTIMEO) && defined(SO_SNDTIMEO) #if HAVE_WINSOCK2_H /* timeout in milliseconds */ to = 10 * 1000; #else to.tv_sec = 10; to.tv_usec = 0; #endif setsockopt(socket_server_fd, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to)); setsockopt(socket_server_fd, SOL_SOCKET, SO_SNDTIMEO, &to, sizeof(to)); #endif switch (af) { case AF_INET: our_s_addr = (void *) &server_address.four.sin_addr; break; #ifdef HAVE_AF_INET6 case AF_INET6: our_s_addr = (void *) &server_address.six.sin6_addr; break; #endif default: mp_msg(MSGT_NETWORK,MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af); return TCP_ERROR_FATAL; } memset(&server_address, 0, sizeof(server_address)); #if HAVE_INET_PTON if (inet_pton(af, host, our_s_addr)!=1) #elif HAVE_INET_ATON if (inet_aton(host, our_s_addr)!=1) #elif HAVE_WINSOCK2_H if ( inet_addr(host)==INADDR_NONE ) #endif { if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ResolvingHostForAF, host, af2String(af)); #ifdef HAVE_GETHOSTBYNAME2 hp=(struct hostent*)gethostbyname2( host, af ); #else hp=(struct hostent*)gethostbyname( host ); #endif if( hp==NULL ) { if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantResolv, af2String(af), host); return TCP_ERROR_FATAL; } memcpy( our_s_addr, (void*)hp->h_addr_list[0], hp->h_length ); } #if HAVE_WINSOCK2_H else { unsigned long addr = inet_addr(host); memcpy( our_s_addr, (void*)&addr, sizeof(addr) ); } #endif switch (af) { case AF_INET: server_address.four.sin_family=af; server_address.four.sin_port=htons(port); server_address_size = sizeof(server_address.four); break; #ifdef HAVE_AF_INET6 case AF_INET6: server_address.six.sin6_family=af; server_address.six.sin6_port=htons(port); server_address_size = sizeof(server_address.six); break; #endif default: mp_msg(MSGT_NETWORK,MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af); return TCP_ERROR_FATAL; } #if HAVE_INET_PTON inet_ntop(af, our_s_addr, buf, 255); #elif HAVE_INET_ATON || defined(HAVE_WINSOCK2_H) av_strlcpy( buf, inet_ntoa( *((struct in_addr*)our_s_addr) ), 255); #endif if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ConnectingToServer, host, buf , port ); // Turn the socket as non blocking so we can timeout on the connection #if defined(GEKKO) // turn off Nagle u32 nodelay = 1; net_setsockopt(socket_server_fd,IPPROTO_TCP,TCP_NODELAY,&nodelay,sizeof(nodelay)); // net_fcntl(socket_server_fd, F_SETFL, net_fcntl(socket_server_fd, F_GETFL, 0) | IOS_O_NONBLOCK); u64 t1,t2; t1=ticks_to_millisecs(gettime()); do { ret = net_connect(socket_server_fd,(struct sockaddr*)&server_address,server_address_size); t2=ticks_to_millisecs(gettime()); if(t2-t1 > 8000) break; // 8 secs to try to connect usleep(500); }while(ret != -EISCONN); if(ret != -EISCONN) { closesocket(socket_server_fd); return TCP_ERROR_PORT; } // net_fcntl(socket_server_fd, F_SETFL, net_fcntl(socket_server_fd, F_GETFL, 0) & ~IOS_O_NONBLOCK); #elif !HAVE_WINSOCK2_H fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK ); #else val = 1; ioctlsocket( socket_server_fd, FIONBIO, &val ); #endif #if !defined(GEKKO) if( connect( socket_server_fd, (struct sockaddr*)&server_address, server_address_size )==-1 ) { #if !HAVE_WINSOCK2_H if( errno!=EINPROGRESS ) { #else if( (WSAGetLastError() != WSAEINPROGRESS) && (WSAGetLastError() != WSAEWOULDBLOCK) ) { #endif if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantConnect2Server, af2String(af)); closesocket(socket_server_fd); return TCP_ERROR_PORT; } } tv.tv_sec = 0; tv.tv_usec = 500000; FD_ZERO( &set ); FD_SET( socket_server_fd, &set ); // When the connection will be made, we will have a writeable fd while((ret = select(socket_server_fd+1, NULL, &set, NULL, &tv)) == 0) { if(count > 30 || stream_check_interrupt(500)) { if(count > 30) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnTimeout); else mp_msg(MSGT_NETWORK,MSGL_V,"Connection interrupted by user\n"); return TCP_ERROR_TIMEOUT; } count++; FD_ZERO( &set ); FD_SET( socket_server_fd, &set ); tv.tv_sec = 0; tv.tv_usec = 500000; } if (ret < 0) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_SelectFailed); // Turn back the socket as blocking #if !HAVE_WINSOCK2_H // fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) & ~O_NONBLOCK ); #else val = 0; ioctlsocket( socket_server_fd, FIONBIO, &val ); #endif // Check if there were any errors err_len = sizeof(int); ret = getsockopt(socket_server_fd,SOL_SOCKET,SO_ERROR,&err,&err_len); if(ret < 0) { mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_GetSockOptFailed,strerror(errno)); return TCP_ERROR_FATAL; } if(err > 0) { mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnectError,strerror(err)); return TCP_ERROR_PORT; } #endif return socket_server_fd; } // Connect to a server using a TCP connection // return -2 for fatal error, like unable to resolve name, connection timeout... // return -1 is unable to connect to a particular port int connect2Server(char *host, int port, int verb) { #ifdef HAVE_AF_INET6 int r; int s = TCP_ERROR_FATAL; r = connect2Server_with_af(host, port, network_prefer_ipv4 ? AF_INET:AF_INET6,verb); if (r >= 0) return r; s = connect2Server_with_af(host, port, network_prefer_ipv4 ? AF_INET6:AF_INET,verb); if (s == TCP_ERROR_FATAL) return r; return s; #else return connect2Server_with_af(host, port, AF_INET,verb); #endif }
static bool StartWiiLoadServer (void) { struct sockaddr_in sin; struct sockaddr_in client_address; s32 connection; int err; if ( wiiload.status == WIILOAD_HBREADY || wiiload.status == WIILOAD_HBZREADY) { // This isn't an error, simply we have received valid data. Host process should set hbready mode to IDLE or stop/restart the thread return true; } // Clean old data, if any if (wiiload.args) free (wiiload.args); wiiload.args = NULL; wiiload.argl = 0; printopt ("StartWiiLoadServer begin"); socklen_t addrlen = sizeof(client_address); //Open socket socket = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if (socket == INVALID_SOCKET) { printopt ("net_socket INVALID_SOCKET"); return false; } int one = 1; err = net_setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&one, sizeof(one)); if (err < 0) { printopt ("net_setsockopt %d"); return false; } sin.sin_family = AF_INET; sin.sin_port = htons(PORT); sin.sin_addr.s_addr = htonl(INADDR_ANY); int flags = net_fcntl(socket, F_GETFL, 0); flags = net_fcntl(socket, F_SETFL, flags|4); // Set non blocking err = net_bind(socket, (struct sockaddr*)&sin, sizeof(sin)); if (err < 0) { printopt ("net_bind error %d", err); net_close(socket); return false; } if (net_listen(socket, 10) < 0) { printopt ("net_listen error"); net_close(socket); return false; } printopt ("net_accept"); // WIILOAD_IDLE is set once. This because if an hb is executed it make no sense.... // Maybe it can be usefull for an app is an hb is rejected. Hosting appl. can set it by itsel wiiload.status = WIILOAD_IDLE; do { int i; for (i = 0; i < 10; i++) { usleep (50000); if (pauseWiiload) break; } if (pauseWiiload) { Debug ("WiiLoad thread paused"); pauseWiiload = 2; do { usleep (250*1000); } while (pauseWiiload && !stopNetworkThread); Debug ("WiiLoad thread resumed"); pauseWiiload = 0; } connection = net_accept(socket, (struct sockaddr*)&client_address, &addrlen); if (connection >= 0) { sprintf(wiiload.op, "%s", inet_ntoa(client_address.sin_addr)); if (!WiiLoad (connection)) { wiiload.status = WIILOAD_IDLE; } net_close(connection); } usleep (100); } while (!stopNetworkThread); net_close(socket); return true; }