📄 connect.c
字号:
/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2003, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://curl.haxx.se/docs/copyright.html. * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id: connect.c,v 1.65 2003/10/18 20:34:33 bagder Exp $ ***************************************************************************/#include "setup.h"#ifndef WIN32/* headers for non-win32 */#include <sys/time.h>#include <sys/socket.h>#include <sys/types.h>#include <sys/ioctl.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_NETDB_H#include <netdb.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h>#endif#ifdef HAVE_NETINET_IN_H#include <netinet/in.h>#endif#ifdef HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#ifdef HAVE_STDLIB_H#include <stdlib.h> /* required for free() prototype, without it, this crashes on macos 68K */#endif#ifdef VMS#include <in.h>#include <inet.h>#endif#endif#include <stdio.h>#include <errno.h>#include <string.h>#ifndef TRUE#define TRUE 1#define FALSE 0#endif#ifdef WIN32#define HAVE_IOCTLSOCKET#include <windows.h>#define EINPROGRESS WSAEINPROGRESS#define EWOULDBLOCK WSAEWOULDBLOCK#define EISCONN WSAEISCONN#define ENOTSOCK WSAENOTSOCK#define ECONNREFUSED WSAECONNREFUSED#endif#include "urldata.h"#include "sendf.h"#include "if2ip.h"/* The last #include file should be: */#ifdef CURLDEBUG#include "memdebug.h"#endifint Curl_ourerrno(void){#ifdef WIN32 return (int)GetLastError();#else return errno;#endif}/************************************************************************* * Curl_nonblock * * Description: * Set the socket to either blocking or non-blocking mode. */int Curl_nonblock(int sockfd, /* operate on this */ int nonblock /* TRUE or FALSE */){#undef SETBLOCK#ifdef HAVE_O_NONBLOCK /* most recent unix versions */ int flags; flags = fcntl(sockfd, F_GETFL, 0); if (TRUE == nonblock) return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); else return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));#define SETBLOCK 1#endif#ifdef HAVE_FIONBIO /* older unix versions */ int flags; flags = nonblock; return ioctl(sockfd, FIONBIO, &flags);#define SETBLOCK 2#endif#ifdef HAVE_IOCTLSOCKET /* Windows? */ int flags; flags = nonblock; return ioctlsocket(sockfd, FIONBIO, &flags);#define SETBLOCK 3#endif#ifdef HAVE_IOCTLSOCKET_CASE /* presumably for Amiga */ return IoctlSocket(sockfd, FIONBIO, (long)nonblock);#define SETBLOCK 4#endif#ifdef HAVE_SO_NONBLOCK /* BeOS */ long b = nonblock ? 1 : 0; return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));#define SETBLOCK 5#endif#ifdef HAVE_DISABLED_NONBLOCKING return 0; /* returns success */#define SETBLOCK 6#endif#ifndef SETBLOCK#error "no non-blocking method was found/used/set"#endif}/* * waitconnect() returns: * 0 fine connect * -1 select() error * 1 select() timeout * 2 select() returned with an error condition */staticint waitconnect(int sockfd, /* socket */ int timeout_msec){ fd_set fd; fd_set errfd; struct timeval interval; int rc; /* now select() until we get connect or timeout */ FD_ZERO(&fd); FD_SET(sockfd, &fd); FD_ZERO(&errfd); FD_SET(sockfd, &errfd); interval.tv_sec = timeout_msec/1000; timeout_msec -= interval.tv_sec*1000; interval.tv_usec = timeout_msec*1000; rc = select(sockfd+1, NULL, &fd, &errfd, &interval); if(-1 == rc) /* error, no connect here, try next */ return -1; else if(0 == rc) /* timeout, no connect today */ return 1; if(FD_ISSET(sockfd, &errfd)) /* error condition caught */ return 2; /* we have a connect! */ return 0;}static CURLcode bindlocal(struct connectdata *conn, int sockfd){#ifdef HAVE_INET_NTOA struct SessionHandle *data = conn->data; /************************************************************* * Select device to bind socket to *************************************************************/ if (strlen(data->set.device)<255) { struct sockaddr_in sa; struct Curl_dns_entry *h=NULL; size_t size; char myhost[256] = ""; in_addr_t in; int rc; /* First check if the given name is an IP address */ in=inet_addr(data->set.device); if((in == CURL_INADDR_NONE) && Curl_if2ip(data->set.device, myhost, sizeof(myhost))) { /* * We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer */ rc = Curl_resolv(conn, myhost, 0, &h); if(rc == 1) rc = Curl_wait_for_resolv(conn, &h); } else { if(strlen(data->set.device)>1) { /* * This was not an interface, resolve the name as a host name * or IP number */ rc = Curl_resolv(conn, data->set.device, 0, &h); if(rc == 1) rc = Curl_wait_for_resolv(conn, &h); if(h) /* we know data->set.device is shorter than the myhost array */ strcpy(myhost, data->set.device); } } if(! *myhost) { /* need to fix this h=Curl_gethost(data, getmyhost(*myhost,sizeof(myhost)), hostent_buf, sizeof(hostent_buf)); */ return CURLE_HTTP_PORT_FAILED; } infof(data, "We bind local end to %s\n", myhost); in=inet_addr(myhost); if (CURL_INADDR_NONE != in) { if ( h ) { Curl_addrinfo *addr = h->addr; Curl_resolv_unlock(data, h); /* we don't need it anymore after this function has returned */#ifdef ENABLE_IPV6 (void)sa; /* prevent compiler warning */ if( bind(sockfd, addr->ai_addr, addr->ai_addrlen) >= 0) { /* we succeeded to bind */ struct sockaddr_in6 add; size = sizeof(add); if(getsockname(sockfd, (struct sockaddr *) &add, (socklen_t *)&size)<0) { failf(data, "getsockname() failed"); return CURLE_HTTP_PORT_FAILED; } }#else memset((char *)&sa, 0, sizeof(sa)); memcpy((char *)&sa.sin_addr, addr->h_addr, addr->h_length); sa.sin_family = AF_INET; sa.sin_addr.s_addr = in; sa.sin_port = 0; /* get any port */ if( bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) >= 0) { /* we succeeded to bind */ struct sockaddr_in add; size = sizeof(add); if(getsockname(sockfd, (struct sockaddr *) &add, (socklen_t *)&size)<0) { failf(data, "getsockname() failed"); return CURLE_HTTP_PORT_FAILED; } }#endif else { switch(errno) { case EBADF: failf(data, "Invalid descriptor: %d", errno); break; case EINVAL: failf(data, "Invalid request: %d", errno); break; case EACCES: failf(data, "Address is protected, user not superuser: %d", errno); break; case ENOTSOCK: failf(data, "Argument is a descriptor for a file, not a socket: %d", errno); break; case EFAULT: failf(data, "Inaccessable memory error: %d", errno); break; case ENAMETOOLONG: failf(data, "Address too long: %d", errno); break; case ENOMEM: failf(data, "Insufficient kernel memory was available: %d", errno); break; default: failf(data, "errno %d", errno); break; } /* end of switch(errno) */ return CURLE_HTTP_PORT_FAILED; } /* end of else */ } /* end of if h */ else { failf(data,"could't find my own IP address (%s)", myhost); return CURLE_HTTP_PORT_FAILED; } } /* end of inet_addr */ else { failf(data, "could't find my own IP address (%s)", myhost); return CURLE_HTTP_PORT_FAILED; } return CURLE_OK; } /* end of device selection support */#endif /* end of HAVE_INET_NTOA */ return CURLE_HTTP_PORT_FAILED;}/* * verifyconnect() returns TRUE if the connect really has happened. */static bool verifyconnect(int sockfd){#if defined(SO_ERROR) && !defined(WIN32) int err = 0; socklen_t errSize = sizeof(err); if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) err = Curl_ourerrno(); if ((0 == err) || (EISCONN == err)) /* we are connected, awesome! */ return TRUE; /* This wasn't a successful connect */ return FALSE;#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -