Index: src/http_socket.c ================================================================== --- src/http_socket.c +++ src/http_socket.c @@ -45,11 +45,10 @@ ** There can only be a single socket connection open at a time. ** State information about that socket is stored in the following ** local variables: */ static int socketIsInit = 0; /* True after global initialization */ -static int addrIsInit = 0; /* True once addr is initialized */ #if defined(_WIN32) static WSADATA socketInfo; /* Windows socket initialize data */ #endif static int iSocket = -1; /* The socket on which we talk to the server */ static char *socketErrMsg = 0; /* Text of most recent socket error */ @@ -106,11 +105,10 @@ WSACleanup(); #endif socket_clear_errmsg(); socketIsInit = 0; } - addrIsInit = 0; } /* ** Close the currently open socket. If no socket is open, this routine ** is a no-op. @@ -134,54 +132,54 @@ ** pUrlDAta->port TCP/IP port to use. Ex: 80 ** ** Return the number of errors. */ int socket_open(UrlData *pUrlData){ - static struct sockaddr_in addr; /* The server address */ + int rc = 0; + struct addrinfo *ai = 0; + struct addrinfo hints; + char zPort[30]; + char zRemote[NI_MAXHOST]; socket_global_init(); - if( !addrIsInit ){ - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(pUrlData->port); - *(int*)&addr.sin_addr = inet_addr(pUrlData->name); - if( -1 == *(int*)&addr.sin_addr ){ -#ifndef FOSSIL_STATIC_LINK - struct hostent *pHost; - pHost = gethostbyname(pUrlData->name); - if( pHost!=0 ){ - memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length); - }else -#endif - { - socket_set_errmsg("can't resolve host name: %s", pUrlData->name); - return 1; - } - } - addrIsInit = 1; - - /* Set the Global.zIpAddr variable to the server we are talking to. - ** This is used to populate the ipaddr column of the rcvfrom table, - ** if any files are received from the server. - */ - g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr)); - } - iSocket = socket(AF_INET,SOCK_STREAM,0); + memset(&hints, 0, sizeof(struct addrinfo)); + assert( iSocket<0 ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + sqlite3_snprintf(sizeof(zPort),zPort,"%d", pUrlData->port); + rc = getaddrinfo(pUrlData->name, zPort, &hints, &ai); + if( rc ){ + socket_set_errmsg("getaddrinfo() fails: %s", gai_strerror(rc)); + goto end_socket_open; + } + rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, zRemote, sizeof(zRemote), + 0, 0, NI_NUMERICHOST); + if( rc ){ + socket_set_errmsg("getnameinfo() failed: %s", gai_strerror(rc)); + goto end_socket_open; + } + g.zIpAddr = mprintf("%s", zRemote); + iSocket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if( iSocket<0 ){ socket_set_errmsg("cannot create a socket"); - return 1; + rc = 1; + goto end_socket_open; } - if( connect(iSocket,(struct sockaddr*)&addr,sizeof(addr))<0 ){ + if( connect(iSocket,ai->ai_addr,ai->ai_addrlen)<0 ){ socket_set_errmsg("cannot connect to host %s:%d", pUrlData->name, pUrlData->port); - socket_close(); - return 1; + rc = 1; + goto end_socket_open; } #if !defined(_WIN32) signal(SIGPIPE, SIG_IGN); #endif - return 0; +end_socket_open: + if( rc && iSocket>=0 ) socket_close(); + if( ai ) freeaddrinfo(ai); + return rc; } /* ** Send content out over the open socket connection. */ Index: src/xfer.c ================================================================== --- src/xfer.c +++ src/xfer.c @@ -1966,12 +1966,12 @@ g.clockSkewSeen = 1; } fossil_force_newline(); fossil_print( - "%s finished with %lld bytes sent, %lld bytes received\n", - zOpType, nSent, nRcvd); + "Total bytes sent: %lld received: %lld ip: %s\n", + nSent, nRcvd, g.zIpAddr); transport_close(&g.url); transport_global_shutdown(&g.url); if( nErr && go==2 ){ db_multi_exec("DROP TABLE onremote"); manifest_crosslink_end(MC_PERMIT_HOOKS);