Ticket #1930: tcp-getaddrinfo.patch
| File tcp-getaddrinfo.patch, 8.4 KB (added by , 15 years ago) |
|---|
-
stream/tcp.c
77 77 connect2Server_with_af(char *host, int port, int af,int verb) { 78 78 int socket_server_fd; 79 79 int err; 80 socklen_t err_len;80 socklen_t err_len; 81 81 int ret,count = 0; 82 82 fd_set set; 83 83 struct timeval tv; 84 union {85 struct sockaddr_in four;86 #ifdef HAVE_AF_INET687 struct sockaddr_in6 six;88 #endif89 } server_address;90 size_t server_address_size;91 void *our_s_addr; // Pointer to sin_addr or sin6_addr92 struct hostent *hp=NULL;93 84 char buf[255]; 85 struct addrinfo hints, *res, *rp; 86 char portstr[6]; 94 87 95 88 #if HAVE_WINSOCK2_H 96 89 unsigned long val; … … 107 100 } 108 101 #endif 109 102 110 socket_server_fd = socket(af, SOCK_STREAM, 0); 103 snprintf(portstr, 6, "%d", port); 104 portstr[5] = 0; 105 memset(&hints, 0, sizeof hints); 106 hints.ai_family = af; 107 err = getaddrinfo(host, portstr, &hints, &res); 111 108 112 113 if( socket_server_fd==-1 ) {114 // mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to create %s socket:\n", af2String(af));109 if (err != 0 || !res) { 110 snprintf(buf, 255, "%s: %s", host, gai_strerror(err)); 111 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantResolv, af2String(af), buf); 115 112 return TCP_ERROR_FATAL; 116 113 } 117 114 118 #if defined(SO_RCVTIMEO) && defined(SO_SNDTIMEO) 119 #if HAVE_WINSOCK2_H 120 /* timeout in milliseconds */ 121 to = 10 * 1000; 122 #else 123 to.tv_sec = 10; 124 to.tv_usec = 0; 125 #endif 126 setsockopt(socket_server_fd, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to)); 127 setsockopt(socket_server_fd, SOL_SOCKET, SO_SNDTIMEO, &to, sizeof(to)); 128 #endif 115 rp = res; 116 while (rp) { 129 117 130 switch (af) { 131 case AF_INET: our_s_addr = (void *) &server_address.four.sin_addr; break; 132 #ifdef HAVE_AF_INET6 133 case AF_INET6: our_s_addr = (void *) &server_address.six.sin6_addr; break; 134 #endif 135 default: 136 mp_msg(MSGT_NETWORK,MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af); 137 return TCP_ERROR_FATAL; 138 } 118 socket_server_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); 139 119 140 141 memset(&server_address, 0, sizeof(server_address)); 142 143 #if HAVE_INET_PTON 144 if (inet_pton(af, host, our_s_addr)!=1) 145 #elif HAVE_INET_ATON 146 if (inet_aton(host, our_s_addr)!=1) 147 #elif HAVE_WINSOCK2_H 148 if ( inet_addr(host)==INADDR_NONE ) 149 #endif 150 { 151 if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ResolvingHostForAF, host, af2String(af)); 152 153 #ifdef HAVE_GETHOSTBYNAME2 154 hp=(struct hostent*)gethostbyname2( host, af ); 155 #else 156 hp=(struct hostent*)gethostbyname( host ); 157 #endif 158 if( hp==NULL ) { 159 if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantResolv, af2String(af), host); 160 return TCP_ERROR_FATAL; 120 if( socket_server_fd==-1 ) { 121 // mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to create %s socket:\n", af2String(af)); 122 err = TCP_ERROR_FATAL; 123 goto retry_next_host1; 161 124 } 162 125 163 memcpy( our_s_addr, (void*)hp->h_addr_list[0], hp->h_length ); 164 } 126 #if defined(SO_RCVTIMEO) && defined(SO_SNDTIMEO) 165 127 #if HAVE_WINSOCK2_H 166 else { 167 unsigned long addr = inet_addr(host); 168 memcpy( our_s_addr, (void*)&addr, sizeof(addr) ); 169 } 128 /* timeout in milliseconds */ 129 to = 10 * 1000; 130 #else 131 to.tv_sec = 10; 132 to.tv_usec = 0; 170 133 #endif 171 172 switch (af) { 173 case AF_INET: 174 server_address.four.sin_family=af; 175 server_address.four.sin_port=htons(port); 176 server_address_size = sizeof(server_address.four); 177 break; 178 #ifdef HAVE_AF_INET6 179 case AF_INET6: 180 server_address.six.sin6_family=af; 181 server_address.six.sin6_port=htons(port); 182 server_address_size = sizeof(server_address.six); 183 break; 134 setsockopt(socket_server_fd, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to)); 135 setsockopt(socket_server_fd, SOL_SOCKET, SO_SNDTIMEO, &to, sizeof(to)); 184 136 #endif 185 default:186 mp_msg(MSGT_NETWORK,MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af);187 return TCP_ERROR_FATAL;188 }189 137 190 #if HAVE_INET_PTON 191 inet_ntop(af, our_s_addr, buf, 255); 192 #elif HAVE_INET_ATON || defined(HAVE_WINSOCK2_H) 193 av_strlcpy( buf, inet_ntoa( *((struct in_addr*)our_s_addr) ), 255); 194 #endif 195 if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ConnectingToServer, host, buf , port ); 138 getnameinfo(rp->ai_addr, rp->ai_addrlen, buf, 255, NULL, 0, NI_NUMERICHOST); 196 139 197 // Turn the socket as non blocking so we can timeout on the connection 140 if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ConnectingToServer, host, buf , port ); 141 142 // Turn the socket as non blocking so we can timeout on the connection 198 143 #if !HAVE_WINSOCK2_H 199 fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK );144 fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK ); 200 145 #else 201 val = 1;202 ioctlsocket( socket_server_fd, FIONBIO, &val );146 val = 1; 147 ioctlsocket( socket_server_fd, FIONBIO, &val ); 203 148 #endif 204 if( connect( socket_server_fd, (struct sockaddr*)&server_address, server_address_size )==-1 ) { 149 150 if( connect( socket_server_fd, rp->ai_addr, rp->ai_addrlen )==-1 ) { 205 151 #if !HAVE_WINSOCK2_H 206 if( errno!=EINPROGRESS ) {152 if( errno!=EINPROGRESS ) { 207 153 #else 208 if( (WSAGetLastError() != WSAEINPROGRESS) && (WSAGetLastError() != WSAEWOULDBLOCK) ) {154 if( (WSAGetLastError() != WSAEINPROGRESS) && (WSAGetLastError() != WSAEWOULDBLOCK) ) { 209 155 #endif 210 if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantConnect2Server, af2String(af)); 211 closesocket(socket_server_fd); 212 return TCP_ERROR_PORT; 156 if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantConnect2Server, af2String(af)); 157 closesocket(socket_server_fd); 158 err = TCP_ERROR_PORT; 159 goto retry_next_host2; 160 } 213 161 } 214 }215 tv.tv_sec =0;216 tv.tv_usec = 500000;217 FD_ZERO(&set );218 FD_SET( socket_server_fd, &set );219 // When the connection will be made, we will have a writeable fd220 while((ret = select(socket_server_fd+1, NULL, &set, NULL, &tv)) == 0) {221 if(count > 30 || stream_check_interrupt(500)) {222 if(count > 30)223 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnTimeout);224 else225 mp_msg(MSGT_NETWORK,MSGL_V,"Connection interrupted by user\n");226 return TCP_ERROR_TIMEOUT;227 }228 count++;229 FD_ZERO( &set );230 FD_SET( socket_server_fd, &set );231 tv.tv_sec = 0;232 tv.tv_usec = 500000;233 }234 if (ret < 0) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_SelectFailed);162 tv.tv_sec = 0; 163 tv.tv_usec = 500000; 164 FD_ZERO( &set ); 165 FD_SET( socket_server_fd, &set ); 166 // When the connection will be made, we will have a writeable fd 167 while((ret = select(socket_server_fd+1, NULL, &set, NULL, &tv)) == 0) { 168 if(count > 30 || stream_check_interrupt(500)) { 169 if(count > 30) 170 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnTimeout); 171 else 172 mp_msg(MSGT_NETWORK,MSGL_V,"Connection interrupted by user\n"); 173 err = TCP_ERROR_TIMEOUT; 174 goto retry_next_host2; 175 } 176 count++; 177 FD_ZERO( &set ); 178 FD_SET( socket_server_fd, &set ); 179 tv.tv_sec = 0; 180 tv.tv_usec = 500000; 181 } 182 if (ret < 0) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_SelectFailed); 235 183 236 // Turn back the socket as blocking184 // Turn back the socket as blocking 237 185 #if !HAVE_WINSOCK2_H 238 fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) & ~O_NONBLOCK );186 fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) & ~O_NONBLOCK ); 239 187 #else 240 val = 0;241 ioctlsocket( socket_server_fd, FIONBIO, &val );188 val = 0; 189 ioctlsocket( socket_server_fd, FIONBIO, &val ); 242 190 #endif 243 // Check if there were any errors 244 err_len = sizeof(int); 245 ret = getsockopt(socket_server_fd,SOL_SOCKET,SO_ERROR,&err,&err_len); 246 if(ret < 0) { 247 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_GetSockOptFailed,strerror(errno)); 248 return TCP_ERROR_FATAL; 249 } 250 if(err > 0) { 251 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnectError,strerror(err)); 252 return TCP_ERROR_PORT; 253 } 191 // Check if there were any errors 192 err_len = sizeof(int); 193 ret = getsockopt(socket_server_fd,SOL_SOCKET,SO_ERROR,&err,&err_len); 194 if(ret < 0) { 195 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_GetSockOptFailed,strerror(errno)); 196 err = TCP_ERROR_FATAL; 197 goto retry_next_host2; 198 } 199 if(err > 0) { 200 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnectError,strerror(err)); 201 err = TCP_ERROR_PORT; 202 goto retry_next_host2; 203 } 254 204 255 return socket_server_fd; 205 freeaddrinfo(res); 206 return socket_server_fd; 207 208 retry_next_host2: 209 closesocket(socket_server_fd); 210 retry_next_host1: 211 rp = rp->ai_next; 212 } 213 freeaddrinfo(res); 214 return err; 256 215 } 257 216 258 217 // Connect to a server using a TCP connection
