]>
Commit | Line | Data |
---|---|---|
1b4f8140 | 1 | /* |
bb742ede | 2 | * Copyright (C) 2009-2011 the libgit2 contributors |
1b4f8140 | 3 | * |
bb742ede VM |
4 | * This file is part of libgit2, distributed under the GNU GPL v2 with |
5 | * a Linking Exception. For full terms see the included COPYING file. | |
1b4f8140 | 6 | */ |
39cdf272 | 7 | #ifndef _WIN32 |
6e34111e VM |
8 | # include <sys/types.h> |
9 | # include <sys/socket.h> | |
10 | # include <sys/select.h> | |
31ffc141 | 11 | # include <sys/time.h> |
6e34111e | 12 | # include <netdb.h> |
4e95ef02 | 13 | #else |
6e34111e VM |
14 | # define _WIN32_WINNT 0x0501 |
15 | # include <winsock2.h> | |
16 | # include <Ws2tcpip.h> | |
17 | # ifdef _MSC_VER | |
18 | # pragma comment(lib, "Ws2_32.lib") | |
19 | # endif | |
4e95ef02 | 20 | #endif |
1b4f8140 | 21 | |
6e34111e | 22 | |
1b4f8140 CMN |
23 | #include "git2/errors.h" |
24 | ||
25 | #include "common.h" | |
26 | #include "netops.h" | |
34bfb4b0 | 27 | #include "posix.h" |
1b4f8140 | 28 | |
0bd594b6 | 29 | void gitno_buffer_setup(gitno_buffer *buf, char *data, unsigned int len, int fd) |
ea7a5452 CMN |
30 | { |
31 | memset(buf, 0x0, sizeof(gitno_buffer)); | |
32 | memset(data, 0x0, len); | |
33 | buf->data = data; | |
b0bda0a4 | 34 | buf->len = len; |
ea7a5452 CMN |
35 | buf->offset = 0; |
36 | buf->fd = fd; | |
37 | } | |
38 | ||
39 | int gitno_recv(gitno_buffer *buf) | |
40 | { | |
41 | int ret; | |
42 | ||
43 | ret = recv(buf->fd, buf->data + buf->offset, buf->len - buf->offset, 0); | |
44 | if (ret < 0) | |
427ca3d3 | 45 | return git__throw(GIT_EOSERR, "Failed to receive data: %s", strerror(errno)); |
ea7a5452 CMN |
46 | if (ret == 0) /* Orderly shutdown, so exit */ |
47 | return GIT_SUCCESS; | |
48 | ||
49 | buf->offset += ret; | |
50 | ||
51 | return ret; | |
52 | } | |
53 | ||
54 | /* Consume up to ptr and move the rest of the buffer to the beginning */ | |
c7c787ce | 55 | void gitno_consume(gitno_buffer *buf, const char *ptr) |
ea7a5452 | 56 | { |
0bd594b6 | 57 | size_t consumed; |
ea7a5452 | 58 | |
0bd594b6 | 59 | assert(ptr - buf->data >= 0); |
ea7a5452 CMN |
60 | assert(ptr - buf->data <= (int) buf->len); |
61 | ||
c7c787ce | 62 | consumed = ptr - buf->data; |
ea7a5452 | 63 | |
c7c787ce CMN |
64 | memmove(buf->data, ptr, buf->offset - consumed); |
65 | memset(buf->data + buf->offset, 0x0, buf->len - buf->offset); | |
66 | buf->offset -= consumed; | |
ea7a5452 CMN |
67 | } |
68 | ||
69 | /* Consume const bytes and move the rest of the buffer to the beginning */ | |
0bd594b6 | 70 | void gitno_consume_n(gitno_buffer *buf, size_t cons) |
ea7a5452 CMN |
71 | { |
72 | memmove(buf->data, buf->data + cons, buf->len - buf->offset); | |
73 | memset(buf->data + cons, 0x0, buf->len - buf->offset); | |
74 | buf->offset -= cons; | |
75 | } | |
76 | ||
1b4f8140 CMN |
77 | int gitno_connect(const char *host, const char *port) |
78 | { | |
79 | struct addrinfo *info, *p; | |
80 | struct addrinfo hints; | |
81 | int ret, error = GIT_SUCCESS; | |
ccc9872d | 82 | GIT_SOCKET s; |
1b4f8140 CMN |
83 | |
84 | memset(&hints, 0x0, sizeof(struct addrinfo)); | |
85 | hints.ai_family = AF_UNSPEC; | |
86 | hints.ai_socktype = SOCK_STREAM; | |
87 | ||
88 | ret = getaddrinfo(host, port, &hints, &info); | |
89 | if (ret != 0) { | |
90 | error = GIT_EOSERR; | |
24384700 | 91 | info = NULL; |
1b4f8140 CMN |
92 | goto cleanup; |
93 | } | |
94 | ||
95 | for (p = info; p != NULL; p = p->ai_next) { | |
96 | s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); | |
ccc9872d CMN |
97 | #ifdef GIT_WIN32 |
98 | if (s == INVALID_SOCKET) { | |
99 | #else | |
1b4f8140 | 100 | if (s < 0) { |
ccc9872d | 101 | #endif |
1b4f8140 CMN |
102 | error = GIT_EOSERR; |
103 | goto cleanup; | |
104 | } | |
105 | ||
106 | ret = connect(s, p->ai_addr, p->ai_addrlen); | |
107 | /* If we can't connect, try the next one */ | |
108 | if (ret < 0) { | |
109 | continue; | |
110 | } | |
111 | ||
112 | /* Return the socket */ | |
113 | error = s; | |
114 | goto cleanup; | |
115 | } | |
116 | ||
117 | /* Oops, we couldn't connect to any address */ | |
ccc9872d | 118 | error = git__throw(GIT_EOSERR, "Failed to connect: %s", strerror(errno)); |
1b4f8140 CMN |
119 | |
120 | cleanup: | |
121 | freeaddrinfo(info); | |
122 | return error; | |
123 | } | |
4e95ef02 | 124 | |
ccc9872d | 125 | int gitno_send(GIT_SOCKET s, const char *msg, size_t len, int flags) |
4e95ef02 | 126 | { |
0bd594b6 VM |
127 | int ret; |
128 | size_t off = 0; | |
4e95ef02 CMN |
129 | |
130 | while (off < len) { | |
ccc9872d CMN |
131 | errno = 0; |
132 | ||
4e95ef02 CMN |
133 | ret = send(s, msg + off, len - off, flags); |
134 | if (ret < 0) | |
928dd90a | 135 | return git__throw(GIT_EOSERR, "Error sending data: %s", strerror(errno)); |
4e95ef02 CMN |
136 | |
137 | off += ret; | |
138 | } | |
139 | ||
140 | return off; | |
141 | } | |
74bd343a | 142 | |
34bfb4b0 | 143 | |
bad53552 CMN |
144 | #ifdef GIT_WIN32 |
145 | int gitno_close(GIT_SOCKET s) | |
146 | { | |
147 | return closesocket(s) == SOCKET_ERROR ? -1 : 0; | |
148 | } | |
149 | #else | |
150 | int gitno_close(GIT_SOCKET s) | |
151 | { | |
152 | return close(s); | |
153 | } | |
154 | #endif | |
155 | ||
74bd343a CMN |
156 | int gitno_select_in(gitno_buffer *buf, long int sec, long int usec) |
157 | { | |
158 | fd_set fds; | |
159 | struct timeval tv; | |
160 | ||
161 | tv.tv_sec = sec; | |
162 | tv.tv_usec = usec; | |
163 | ||
164 | FD_ZERO(&fds); | |
165 | FD_SET(buf->fd, &fds); | |
166 | ||
167 | /* The select(2) interface is silly */ | |
168 | return select(buf->fd + 1, &fds, NULL, NULL, &tv); | |
169 | } | |
db84b798 CMN |
170 | |
171 | int gitno_extract_host_and_port(char **host, char **port, const char *url, const char *default_port) | |
172 | { | |
173 | char *colon, *slash, *delim; | |
174 | int error = GIT_SUCCESS; | |
175 | ||
176 | colon = strchr(url, ':'); | |
177 | slash = strchr(url, '/'); | |
178 | ||
179 | if (slash == NULL) | |
180 | return git__throw(GIT_EOBJCORRUPTED, "Malformed URL: missing /"); | |
181 | ||
182 | if (colon == NULL) { | |
183 | *port = git__strdup(default_port); | |
184 | } else { | |
185 | *port = git__strndup(colon + 1, slash - colon - 1); | |
186 | } | |
187 | if (*port == NULL) | |
188 | return GIT_ENOMEM;; | |
189 | ||
190 | ||
191 | delim = colon == NULL ? slash : colon; | |
192 | *host = git__strndup(url, delim - url); | |
193 | if (*host == NULL) { | |
3286c408 | 194 | git__free(*port); |
db84b798 CMN |
195 | error = GIT_ENOMEM; |
196 | } | |
197 | ||
198 | return error; | |
199 | } |