Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
db066a96
Commit
db066a96
authored
Sep 13, 2012
by
Vicent Martí
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #901 from carlosmn/winhttp
http: use WinHTTP on Windows
parents
57ad9f2e
3ce22c74
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
204 additions
and
34 deletions
+204
-34
CMakeLists.txt
+7
-3
src/transports/http.c
+196
-30
src/util.c
+1
-1
No files found.
CMakeLists.txt
View file @
db066a96
...
...
@@ -29,7 +29,12 @@ ENDIF()
# Find required dependencies
INCLUDE_DIRECTORIES
(
src include deps/http-parser
)
FILE
(
GLOB SRC_HTTP deps/http-parser/*.c
)
IF
(
WIN32 AND NOT MINGW
)
ADD_DEFINITIONS
(
-DGIT_WINHTTP
)
ELSE
()
FIND_PACKAGE
(
OpenSSL
)
FILE
(
GLOB SRC_HTTP deps/http-parser/*.c
)
ENDIF
()
# Specify sha1 implementation
IF
(
SHA1_TYPE STREQUAL
"ppc"
)
...
...
@@ -75,7 +80,7 @@ OPTION (PROFILE "Generate profiling information" OFF)
# Platform specific compilation flags
IF
(
MSVC
)
#
Not using __stdcall with the CRT causes problems
#
Default to stdcall, as that's what the CLR expects and how the Windows API is built
OPTION
(
STDCALL
"Buildl libgit2 with the __stdcall convention"
ON
)
SET
(
CMAKE_C_FLAGS
"/W4 /MP /nologo /Zi
${
CMAKE_C_FLAGS
}
"
)
...
...
@@ -106,7 +111,6 @@ IF (NOT CMAKE_BUILD_TYPE)
SET
(
CMAKE_BUILD_TYPE
"Debug"
CACHE STRING
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
FORCE
)
ENDIF
()
FIND_PACKAGE
(
OpenSSL
)
IF
(
OPENSSL_FOUND
)
ADD_DEFINITIONS
(
-DGIT_SSL
)
INCLUDE_DIRECTORIES
(
${
OPENSSL_INCLUDE_DIR
}
)
...
...
src/transports/http.c
View file @
db066a96
...
...
@@ -4,7 +4,6 @@
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include <stdlib.h>
#include "git2.h"
#include "http_parser.h"
...
...
@@ -20,6 +19,13 @@
#include "filebuf.h"
#include "repository.h"
#include "protocol.h"
#if GIT_WINHTTP
# include <winhttp.h>
# pragma comment(lib, "winhttp.lib")
#endif
#define WIDEN2(s) L ## s
#define WIDEN(s) WIDEN2(s)
enum
last_cb
{
NONE
,
...
...
@@ -47,6 +53,11 @@ typedef struct {
#ifdef GIT_WIN32
WSADATA
wsd
;
#endif
#ifdef GIT_WINHTTP
HINTERNET
session
;
HINTERNET
connection
;
HINTERNET
request
;
#endif
}
transport_http
;
static
int
gen_request
(
git_buf
*
buf
,
const
char
*
path
,
const
char
*
host
,
const
char
*
op
,
...
...
@@ -77,17 +88,158 @@ static int gen_request(git_buf *buf, const char *path, const char *host, const c
return
0
;
}
static
int
do_connect
(
transport_http
*
t
,
const
char
*
host
,
const
char
*
port
)
static
int
send_request
(
transport_http
*
t
,
const
char
*
service
,
void
*
data
,
ssize_t
content_length
,
int
ls
)
{
#ifndef GIT_WINHTTP
git_buf
request
=
GIT_BUF_INIT
;
const
char
*
verb
;
verb
=
ls
?
"GET"
:
"POST"
;
/* Generate and send the HTTP request */
if
(
gen_request
(
&
request
,
t
->
path
,
t
->
host
,
verb
,
service
,
content_length
,
ls
)
<
0
)
{
giterr_set
(
GITERR_NET
,
"Failed to generate request"
);
return
-
1
;
}
if
(
gitno_send
((
git_transport
*
)
t
,
request
.
ptr
,
request
.
size
,
0
)
<
0
)
{
git_buf_free
(
&
request
);
return
-
1
;
}
if
(
content_length
)
{
if
(
gitno_send
((
git_transport
*
)
t
,
data
,
content_length
,
0
)
<
0
)
return
-
1
;
}
return
0
;
#else
wchar_t
*
url
,
*
verb
,
*
ct
;
git_buf
buf
=
GIT_BUF_INIT
;
BOOL
ret
;
DWORD
flags
;
void
*
buffer
;
wchar_t
*
types
[]
=
{
L"*/*"
,
NULL
,
};
verb
=
ls
?
L"GET"
:
L"POST"
;
buffer
=
data
?
data
:
WINHTTP_NO_REQUEST_DATA
;
flags
=
t
->
parent
.
use_ssl
?
WINHTTP_FLAG_SECURE
:
0
;
if
(
ls
)
git_buf_printf
(
&
buf
,
"%s/info/refs?service=git-%s"
,
t
->
path
,
service
);
else
git_buf_printf
(
&
buf
,
"%s/git-%s"
,
t
->
path
,
service
);
if
(
git_buf_oom
(
&
buf
))
return
-
1
;
url
=
gitwin_to_utf16
(
git_buf_cstr
(
&
buf
));
if
(
!
url
)
goto
on_error
;
t
->
request
=
WinHttpOpenRequest
(
t
->
connection
,
verb
,
url
,
NULL
,
WINHTTP_NO_REFERER
,
types
,
flags
);
git__free
(
url
);
if
(
t
->
request
==
NULL
)
{
git_buf_free
(
&
buf
);
giterr_set
(
GITERR_OS
,
"Failed to open request"
);
return
-
1
;
}
git_buf_clear
(
&
buf
);
if
(
git_buf_printf
(
&
buf
,
"Content-Type: application/x-git-%s-request"
,
service
)
<
0
)
goto
on_error
;
ct
=
gitwin_to_utf16
(
git_buf_cstr
(
&
buf
));
if
(
!
ct
)
goto
on_error
;
if
(
WinHttpAddRequestHeaders
(
t
->
request
,
ct
,
(
ULONG
)
-
1L
,
WINHTTP_ADDREQ_FLAG_ADD
)
==
FALSE
)
{
giterr_set
(
GITERR_OS
,
"Failed to add a header to the request"
);
goto
on_error
;
}
if
(
!
t
->
parent
.
check_cert
)
{
int
flags
=
SECURITY_FLAG_IGNORE_CERT_CN_INVALID
|
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
|
SECURITY_FLAG_IGNORE_UNKNOWN_CA
;
if
(
WinHttpSetOption
(
t
->
request
,
WINHTTP_OPTION_SECURITY_FLAGS
,
&
flags
,
sizeof
(
flags
))
==
FALSE
)
{
giterr_set
(
GITERR_OS
,
"Failed to set options to ignore cert errors"
);
goto
on_error
;
}
}
if
(
WinHttpSendRequest
(
t
->
request
,
WINHTTP_NO_ADDITIONAL_HEADERS
,
0
,
data
,
content_length
,
content_length
,
0
)
==
FALSE
)
{
giterr_set
(
GITERR_OS
,
"Failed to send request"
);
goto
on_error
;
}
ret
=
WinHttpReceiveResponse
(
t
->
request
,
NULL
);
if
(
ret
==
FALSE
)
{
giterr_set
(
GITERR_OS
,
"Failed to receive response"
);
goto
on_error
;
}
return
0
;
on_error:
git_buf_free
(
&
buf
);
if
(
t
->
request
)
WinHttpCloseHandle
(
t
->
request
);
t
->
request
=
NULL
;
return
-
1
;
#endif
}
static
int
do_connect
(
transport_http
*
t
)
{
#ifndef GIT_WINHTTP
if
(
t
->
parent
.
connected
&&
http_should_keep_alive
(
&
t
->
parser
))
return
0
;
if
(
gitno_connect
((
git_transport
*
)
t
,
host
,
port
)
<
0
)
if
(
gitno_connect
((
git_transport
*
)
t
,
t
->
host
,
t
->
port
)
<
0
)
return
-
1
;
t
->
parent
.
connected
=
1
;
return
0
;
#else
wchar_t
*
ua
=
L"git/1.0 (libgit2 "
WIDEN
(
LIBGIT2_VERSION
)
L")"
;
wchar_t
*
host
;
int32_t
port
;
t
->
session
=
WinHttpOpen
(
ua
,
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY
,
WINHTTP_NO_PROXY_NAME
,
WINHTTP_NO_PROXY_BYPASS
,
0
);
if
(
t
->
session
==
NULL
)
{
giterr_set
(
GITERR_OS
,
"Failed to init WinHTTP"
);
goto
on_error
;
}
host
=
gitwin_to_utf16
(
t
->
host
);
if
(
host
==
NULL
)
goto
on_error
;
if
(
git__strtol32
(
&
port
,
t
->
port
,
NULL
,
10
)
<
0
)
goto
on_error
;
t
->
connection
=
WinHttpConnect
(
t
->
session
,
host
,
port
,
0
);
git__free
(
host
);
if
(
t
->
connection
==
NULL
)
{
giterr_set
(
GITERR_OS
,
"Failed to connect to host"
);
goto
on_error
;
}
t
->
parent
.
connected
=
1
;
return
0
;
on_error:
if
(
t
->
session
)
{
WinHttpCloseHandle
(
t
->
session
);
t
->
session
=
NULL
;
}
return
-
1
;
#endif
}
/*
...
...
@@ -216,13 +368,18 @@ static int http_recv_cb(gitno_buffer *buf)
git_transport
*
transport
=
(
git_transport
*
)
buf
->
cb_data
;
transport_http
*
t
=
(
transport_http
*
)
transport
;
size_t
old_len
;
gitno_buffer
inner
;
char
buffer
[
2048
];
#ifdef GIT_WINHTTP
DWORD
recvd
;
#else
gitno_buffer
inner
;
int
error
;
#endif
if
(
t
->
transfer_finished
)
return
0
;
#ifndef GIT_WINHTTP
gitno_buffer_setup
(
transport
,
&
inner
,
buffer
,
sizeof
(
buffer
));
if
((
error
=
gitno_recv
(
&
inner
))
<
0
)
...
...
@@ -232,6 +389,21 @@ static int http_recv_cb(gitno_buffer *buf)
http_parser_execute
(
&
t
->
parser
,
&
t
->
settings
,
inner
.
data
,
inner
.
offset
);
if
(
t
->
error
<
0
)
return
t
->
error
;
#else
old_len
=
buf
->
offset
;
if
(
WinHttpReadData
(
t
->
request
,
buffer
,
sizeof
(
buffer
),
&
recvd
)
==
FALSE
)
{
giterr_set
(
GITERR_OS
,
"Failed to read data from the network"
);
return
t
->
error
=
-
1
;
}
if
(
buf
->
len
-
buf
->
offset
<
recvd
)
{
giterr_set
(
GITERR_NET
,
"Can't fit data in the buffer"
);
return
t
->
error
=
-
1
;
}
memcpy
(
buf
->
data
+
buf
->
offset
,
buffer
,
recvd
);
buf
->
offset
+=
recvd
;
#endif
return
(
int
)(
buf
->
offset
-
old_len
);
}
...
...
@@ -241,6 +413,8 @@ static void setup_gitno_buffer(git_transport *transport)
{
transport_http
*
t
=
(
transport_http
*
)
transport
;
/* WinHTTP takes care of this for us */
#ifndef GIT_WINHTTP
http_parser_init
(
&
t
->
parser
,
HTTP_RESPONSE
);
t
->
parser
.
data
=
t
;
t
->
transfer_finished
=
0
;
...
...
@@ -250,6 +424,7 @@ static void setup_gitno_buffer(git_transport *transport)
t
->
settings
.
on_headers_complete
=
on_headers_complete
;
t
->
settings
.
on_body
=
on_body_fill_buffer
;
t
->
settings
.
on_message_complete
=
on_message_complete
;
#endif
gitno_buffer_setup_callback
(
transport
,
&
transport
->
buffer
,
t
->
buffer
,
sizeof
(
t
->
buffer
),
http_recv_cb
,
t
);
}
...
...
@@ -289,17 +464,10 @@ static int http_connect(git_transport *transport, int direction)
t
->
service
=
git__strdup
(
service
);
GITERR_CHECK_ALLOC
(
t
->
service
);
if
((
ret
=
do_connect
(
t
,
t
->
host
,
t
->
port
))
<
0
)
if
((
ret
=
do_connect
(
t
))
<
0
)
goto
cleanup
;
/* Generate and send the HTTP request */
if
((
ret
=
gen_request
(
&
request
,
t
->
path
,
t
->
host
,
"GET"
,
service
,
0
,
1
))
<
0
)
{
giterr_set
(
GITERR_NET
,
"Failed to generate request"
);
goto
cleanup
;
}
if
(
gitno_send
(
transport
,
request
.
ptr
,
request
.
size
,
0
)
<
0
)
if
((
ret
=
send_request
(
t
,
"upload-pack"
,
NULL
,
0
,
1
))
<
0
)
goto
cleanup
;
setup_gitno_buffer
(
transport
);
...
...
@@ -332,36 +500,24 @@ cleanup:
static
int
http_negotiation_step
(
struct
git_transport
*
transport
,
void
*
data
,
size_t
len
)
{
transport_http
*
t
=
(
transport_http
*
)
transport
;
git_buf
request
=
GIT_BUF_INIT
;
int
ret
;
/* First, send the data as a HTTP POST request */
if
((
ret
=
do_connect
(
t
,
t
->
host
,
t
->
port
))
<
0
)
if
((
ret
=
do_connect
(
t
))
<
0
)
return
-
1
;
if
((
ret
=
gen_request
(
&
request
,
t
->
path
,
t
->
host
,
"POST"
,
"upload-pack"
,
len
,
0
))
<
0
)
goto
on_error
;
if
((
ret
=
gitno_send
(
transport
,
request
.
ptr
,
request
.
size
,
0
))
<
0
)
goto
on_error
;
if
((
ret
=
gitno_send
(
transport
,
data
,
len
,
0
))
<
0
)
goto
on_error
;
git_buf_free
(
&
request
);
if
(
send_request
(
t
,
"upload-pack"
,
data
,
len
,
0
)
<
0
)
return
-
1
;
/* Then we need to set up the buffer to grab data from the HTTP response */
setup_gitno_buffer
(
transport
);
return
0
;
on_error:
git_buf_free
(
&
request
);
return
-
1
;
}
static
int
http_close
(
git_transport
*
transport
)
{
#ifndef GIT_WINHTTP
if
(
gitno_ssl_teardown
(
transport
)
<
0
)
return
-
1
;
...
...
@@ -369,6 +525,16 @@ static int http_close(git_transport *transport)
giterr_set
(
GITERR_OS
,
"Failed to close the socket: %s"
,
strerror
(
errno
));
return
-
1
;
}
#else
transport_http
*
t
=
(
transport_http
*
)
transport
;
if
(
t
->
request
)
WinHttpCloseHandle
(
t
->
request
);
if
(
t
->
connection
)
WinHttpCloseHandle
(
t
->
connection
);
if
(
t
->
session
)
WinHttpCloseHandle
(
t
->
session
);
#endif
transport
->
connected
=
0
;
...
...
@@ -445,7 +611,7 @@ int git_transport_http(git_transport **out)
int
git_transport_https
(
git_transport
**
out
)
{
#if
def GIT_SSL
#if
defined(GIT_SSL) || defined(GIT_WINHTTP)
transport_http
*
t
;
if
(
git_transport_http
((
git_transport
**
)
&
t
)
<
0
)
return
-
1
;
...
...
src/util.c
View file @
db066a96
...
...
@@ -28,7 +28,7 @@ int git_libgit2_capabilities()
#ifdef GIT_THREADS
|
GIT_CAP_THREADS
#endif
#if
def GIT_SSL
#if
defined(GIT_SSL) || defined(GIT_WINHTTP)
|
GIT_CAP_HTTPS
#endif
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment