mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-08 01:20:53 +00:00
Fix gitno_connect() error handling on Windows
gitno_connect() can return an error or socket, which is fine on most platforms where sockets are file descriptors (signed int), but on Windows, SOCKET is an unsigned type, which is problematic when we are trying to test if the socket was actually a negative error code. This fix seperates the error code and socket in gitno_connect(), and fixes the error handling in do_connect() functions to compensate. It appears that git_connect() and the git-transport do_connect() functions had bugs in the non-windows cases too (leaking sockets, and not properly reporting connection error, respectively) so I went ahead and fixed those too.
This commit is contained in:
parent
06ac3e7f34
commit
b4b96d56bf
14
src/netops.c
14
src/netops.c
@ -74,12 +74,11 @@ void gitno_consume_n(gitno_buffer *buf, size_t cons)
|
|||||||
buf->offset -= cons;
|
buf->offset -= cons;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gitno_connect(const char *host, const char *port)
|
int gitno_connect(const char *host, const char *port, GIT_SOCKET *s)
|
||||||
{
|
{
|
||||||
struct addrinfo *info, *p;
|
struct addrinfo *info, *p;
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
int ret, error = GIT_SUCCESS;
|
int ret, error = GIT_SUCCESS;
|
||||||
GIT_SOCKET s;
|
|
||||||
|
|
||||||
memset(&hints, 0x0, sizeof(struct addrinfo));
|
memset(&hints, 0x0, sizeof(struct addrinfo));
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = AF_UNSPEC;
|
||||||
@ -93,24 +92,25 @@ int gitno_connect(const char *host, const char *port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (p = info; p != NULL; p = p->ai_next) {
|
for (p = info; p != NULL; p = p->ai_next) {
|
||||||
s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
|
*s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
|
||||||
#ifdef GIT_WIN32
|
#ifdef GIT_WIN32
|
||||||
if (s == INVALID_SOCKET) {
|
if (*s == INVALID_SOCKET) {
|
||||||
#else
|
#else
|
||||||
if (s < 0) {
|
if (*s < 0) {
|
||||||
#endif
|
#endif
|
||||||
error = GIT_EOSERR;
|
error = GIT_EOSERR;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = connect(s, p->ai_addr, p->ai_addrlen);
|
ret = connect(*s, p->ai_addr, p->ai_addrlen);
|
||||||
/* If we can't connect, try the next one */
|
/* If we can't connect, try the next one */
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
close(*s);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the socket */
|
/* Return the socket */
|
||||||
error = s;
|
error = GIT_SUCCESS;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ int gitno_recv(gitno_buffer *buf);
|
|||||||
void gitno_consume(gitno_buffer *buf, const char *ptr);
|
void gitno_consume(gitno_buffer *buf, const char *ptr);
|
||||||
void gitno_consume_n(gitno_buffer *buf, size_t cons);
|
void gitno_consume_n(gitno_buffer *buf, size_t cons);
|
||||||
|
|
||||||
int gitno_connect(const char *host, const char *port);
|
int gitno_connect(const char *host, const char *port, GIT_SOCKET *s);
|
||||||
int gitno_send(GIT_SOCKET s, const char *msg, size_t len, int flags);
|
int gitno_send(GIT_SOCKET s, const char *msg, size_t len, int flags);
|
||||||
int gitno_close(GIT_SOCKET s);
|
int gitno_close(GIT_SOCKET s);
|
||||||
int gitno_send_chunk_size(int s, size_t len);
|
int gitno_send_chunk_size(int s, size_t len);
|
||||||
|
@ -106,10 +106,12 @@ static int do_connect(transport_git *t, const char *url)
|
|||||||
if (error < GIT_SUCCESS)
|
if (error < GIT_SUCCESS)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
s = gitno_connect(host, port);
|
error = gitno_connect(host, port, &s);
|
||||||
connected = 1;
|
if (error == GIT_SUCCESS) {
|
||||||
error = send_request(s, NULL, url);
|
connected = 1;
|
||||||
t->socket = s;
|
error = send_request(s, NULL, url);
|
||||||
|
t->socket = s;
|
||||||
|
}
|
||||||
|
|
||||||
git__free(host);
|
git__free(host);
|
||||||
git__free(port);
|
git__free(port);
|
||||||
|
@ -82,14 +82,15 @@ static int gen_request(git_buf *buf, const char *url, const char *host, const ch
|
|||||||
|
|
||||||
static int do_connect(transport_http *t, const char *host, const char *port)
|
static int do_connect(transport_http *t, const char *host, const char *port)
|
||||||
{
|
{
|
||||||
GIT_SOCKET s = -1;
|
int error = GIT_SUCCESS;
|
||||||
|
GIT_SOCKET s;
|
||||||
|
|
||||||
if (t->parent.connected && http_should_keep_alive(&t->parser))
|
if (t->parent.connected && http_should_keep_alive(&t->parser))
|
||||||
return GIT_SUCCESS;
|
return GIT_SUCCESS;
|
||||||
|
|
||||||
s = gitno_connect(host, port);
|
error = gitno_connect(host, port, &s);
|
||||||
if (s < GIT_SUCCESS) {
|
if (error != GIT_SUCCESS) {
|
||||||
return git__rethrow(s, "Failed to connect to host");
|
return git__rethrow(error, "Failed to connect to host");
|
||||||
}
|
}
|
||||||
t->socket = s;
|
t->socket = s;
|
||||||
t->parent.connected = 1;
|
t->parent.connected = 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user