Skip to content

Commit

Permalink
Curl_socket: internal replacement for socket()
Browse files Browse the repository at this point in the history
Moved out into a separate function to work as a "generic" socket()
replacement.
  • Loading branch information
bagder committed Dec 5, 2011
1 parent 5971d40 commit 9109cde
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 58 deletions.
125 changes: 67 additions & 58 deletions lib/connect.c
Expand Up @@ -89,18 +89,6 @@
#undef SO_NOSIGPIPE
#endif

struct Curl_sockaddr_ex {
int family;
int socktype;
int protocol;
unsigned int addrlen;
union {
struct sockaddr addr;
struct Curl_sockaddr_storage buff;
} _sa_ex_u;
};
#define sa_addr _sa_ex_u.addr

static bool verifyconnect(curl_socket_t sockfd, int *error);

static CURLcode
Expand Down Expand Up @@ -841,56 +829,13 @@ singleipconnect(struct connectdata *conn,
struct SessionHandle *data = conn->data;
curl_socket_t sockfd;
CURLcode res = CURLE_OK;
#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
struct sockaddr_in6 * const sa6 = (void *)&addr.sa_addr;
#endif

*sockp = CURL_SOCKET_BAD;

/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
* curl_sockaddr structure with enough space available to directly hold
* any protocol-specific address structures. The variable declared here
* will be used to pass / receive data to/from the fopensocket callback
* if this has been set, before that, it is initialized from parameters.
*/

addr.family = ai->ai_family;
addr.socktype = conn->socktype;
addr.protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
addr.addrlen = ai->ai_addrlen;

if(addr.addrlen > sizeof(struct Curl_sockaddr_storage))
addr.addrlen = sizeof(struct Curl_sockaddr_storage);
memcpy(&addr.sa_addr, ai->ai_addr, addr.addrlen);

*connected = FALSE; /* default is not connected */

if(data->set.fopensocket)
/*
* If the opensocket callback is set, all the destination address
* information is passed to the callback. Depending on this information the
* callback may opt to abort the connection, this is indicated returning
* CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
* the callback returns a valid socket the destination address information
* might have been changed and this 'new' address will actually be used
* here to connect.
*/
sockfd = data->set.fopensocket(data->set.opensocket_client,
CURLSOCKTYPE_IPCXN,
(struct curl_sockaddr *)&addr);
else
/* opensocket callback not set, so simply create the socket now */
sockfd = socket(addr.family, addr.socktype, addr.protocol);

if(sockfd == CURL_SOCKET_BAD)
/* no socket, no connection */
return CURLE_OK;

#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
if(conn->scope && (addr.family == AF_INET6))
sa6->sin6_scope_id = conn->scope;
#endif
res = Curl_socket(conn, ai, &addr, &sockfd);
if(res)
return res;

/* store remote address and port used in this connection attempt */
if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
Expand Down Expand Up @@ -1170,3 +1115,67 @@ int Curl_closesocket(struct connectdata *conn,
else
return sclose(sock);
}

/*
* Create a socket based on info from 'conn' and 'ai'.
*
* Fill in 'addr' and 'sockfd' accordingly if OK is returned. If the open
* socket callback is set, used that!
*
*/
CURLcode Curl_socket(struct connectdata *conn,
const Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr,
curl_socket_t *sockfd)
{
struct SessionHandle *data = conn->data;
#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
#endif

/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
* curl_sockaddr structure with enough space available to directly hold
* any protocol-specific address structures. The variable declared here
* will be used to pass / receive data to/from the fopensocket callback
* if this has been set, before that, it is initialized from parameters.
*/

addr->family = ai->ai_family;
addr->socktype = conn->socktype;
addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
addr->addrlen = ai->ai_addrlen;

if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
addr->addrlen = sizeof(struct Curl_sockaddr_storage);
memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);

if(data->set.fopensocket)
/*
* If the opensocket callback is set, all the destination address
* information is passed to the callback. Depending on this information the
* callback may opt to abort the connection, this is indicated returning
* CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
* the callback returns a valid socket the destination address information
* might have been changed and this 'new' address will actually be used
* here to connect.
*/
*sockfd = data->set.fopensocket(data->set.opensocket_client,
CURLSOCKTYPE_IPCXN,
(struct curl_sockaddr *)addr);
else
/* opensocket callback not set, so simply create the socket now */
*sockfd = socket(addr->family, addr->socktype, addr->protocol);

if(*sockfd == CURL_SOCKET_BAD)
/* no socket, no connection */
return CURLE_FAILED_INIT;

#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
if(conn->scope && (addr->family == AF_INET6))
sa6->sin6_scope_id = conn->scope;
#endif

return CURLE_OK;

}
32 changes: 32 additions & 0 deletions lib/connect.h
Expand Up @@ -24,6 +24,7 @@
#include "setup.h"

#include "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */
#include "sockaddr.h"

CURLcode Curl_is_connected(struct connectdata *conn,
int sockindex,
Expand Down Expand Up @@ -72,4 +73,35 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd);
void Curl_persistconninfo(struct connectdata *conn);
int Curl_closesocket(struct connectdata *conn, curl_socket_t sock);

/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
* curl_sockaddr structure with enough space available to directly hold any
* protocol-specific address structures. The variable declared here will be
* used to pass / receive data to/from the fopensocket callback if this has
* been set, before that, it is initialized from parameters.
*/
struct Curl_sockaddr_ex {
int family;
int socktype;
int protocol;
unsigned int addrlen;
union {
struct sockaddr addr;
struct Curl_sockaddr_storage buff;
} _sa_ex_u;
};
#define sa_addr _sa_ex_u.addr

/*
* Create a socket based on info from 'conn' and 'ai'.
*
* Fill in 'addr' and 'sockfd' accordingly if OK is returned. If the open
* socket callback is set, used that!
*
*/
CURLcode Curl_socket(struct connectdata *conn,
const Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr,
curl_socket_t *sockfd);

#endif /* HEADER_CURL_CONNECT_H */

0 comments on commit 9109cde

Please sign in to comment.