diff --git a/src/netops.c b/src/netops.c new file mode 100644 index 000000000..04f758fa4 --- /dev/null +++ b/src/netops.c @@ -0,0 +1,76 @@ +/* + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, + * as published by the Free Software Foundation. + * + * In addition to the permissions in the GNU General Public License, + * the authors give you unlimited permission to link the compiled + * version of this file into combinations with other programs, + * and to distribute those combinations without any restriction + * coming from the use of this file. (The General Public License + * restrictions do apply in other respects; for example, they cover + * modification of the file, and distribution when not linked into + * a combined executable.) + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include + +#include "git2/errors.h" + +#include "common.h" +#include "netops.h" + +int gitno_connect(const char *host, const char *port) +{ + struct addrinfo *info, *p; + struct addrinfo hints; + int ret, error = GIT_SUCCESS; + int s; + + memset(&hints, 0x0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + ret = getaddrinfo(host, port, &hints, &info); + if (ret != 0) { + error = GIT_EOSERR; + goto cleanup; + } + + for (p = info; p != NULL; p = p->ai_next) { + s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + if (s < 0) { + error = GIT_EOSERR; + goto cleanup; + } + + ret = connect(s, p->ai_addr, p->ai_addrlen); + /* If we can't connect, try the next one */ + if (ret < 0) { + continue; + } + + /* Return the socket */ + error = s; + goto cleanup; + } + + /* Oops, we couldn't connect to any address */ + error = GIT_EOSERR; + +cleanup: + freeaddrinfo(info); + return error; +} diff --git a/src/netops.h b/src/netops.h new file mode 100644 index 000000000..10627d486 --- /dev/null +++ b/src/netops.h @@ -0,0 +1,9 @@ +/* + * netops.h - convencience functions for networking + */ +#ifndef INCLUDE_netops_h__ +#define INCLUDE_netops_h__ + +int gitno_connect(const char *host, const char *port); + +#endif diff --git a/src/transport_git.c b/src/transport_git.c index e5c7b1dc4..12af21b51 100644 --- a/src/transport_git.c +++ b/src/transport_git.c @@ -42,6 +42,7 @@ #include "vector.h" #include "transport.h" #include "common.h" +#include "netops.h" typedef struct { int socket; @@ -91,53 +92,29 @@ static int do_connect(git_priv *priv, const char *url) char *host, *port, *msg; const char prefix[] = "git://"; int error, ret, msg_len, connected = 0; - struct addrinfo *info, *p; - struct addrinfo hints; - - memset(&hints, 0x0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6 */ - hints.ai_socktype = SOCK_STREAM; /* TCP */ if (!git__prefixcmp(url, prefix)) url += STRLEN(prefix); error = extract_host_and_port(&host, &port, url); + s = gitno_connect(host, port); + connected = 1; - ret = getaddrinfo(host, port, &hints, &info); - if (ret != 0) { - info = NULL; - error = git__throw(GIT_EOSERR, "Failed to get address info: %s", gai_strerror(ret)); + error = git_pkt_gen_proto(&msg, &msg_len, url); + if (error < GIT_SUCCESS) goto cleanup; - } - for (p = info; p != NULL; p = p->ai_next) { - s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); - if (s < 0) { - error = git__throw(GIT_EOSERR, "Failed to create socket"); - goto cleanup; - } - - ret = connect(s, p->ai_addr, p->ai_addrlen); - if (ret < 0) { /* Try the next one */ - continue; - } - connected = 1; - - error = git_pkt_gen_proto(&msg, &msg_len, url); - if (error < GIT_SUCCESS) - break; - - /* FIXME: Do this in a loop */ - ret = send(s, msg, msg_len, 0); - free(msg); - if (ret < 0) - error = git__throw(GIT_EOSERR, "Failed to send request"); + /* FIXME: Do this in a loop */ + ret = send(s, msg, msg_len, 0); + free(msg); + if (ret < 0) { + error = git__throw(GIT_EOSERR, "Failed to send request"); + goto cleanup; } priv->socket = s; cleanup: - freeaddrinfo(info); free(host); free(port);