-
Notifications
You must be signed in to change notification settings - Fork 894
/
Copy pathSmartSubtransportRegistration.cs
105 lines (90 loc) · 3.88 KB
/
SmartSubtransportRegistration.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using LibGit2Sharp.Core;
using LibGit2Sharp.Core.Handles;
namespace LibGit2Sharp
{
/// <summary>
/// An object representing the registration of a SmartSubtransport type with libgit2
/// under a particular scheme (eg "http").
/// </summary>
/// <typeparam name="T">The type of SmartSubtransport to register</typeparam>
public sealed class SmartSubtransportRegistration<T> : SmartSubtransportRegistrationData
where T : SmartSubtransport, new()
{
/// <summary>
/// Creates a new native registration for a smart protocol transport
/// in libgit2.
/// </summary>
/// <param name="scheme">The URL scheme (eg "http") to register</param>
internal SmartSubtransportRegistration(string scheme)
{
Scheme = scheme;
RegistrationPointer = CreateRegistrationPointer();
FunctionPointer = CreateFunctionPointer();
}
private IntPtr CreateRegistrationPointer()
{
var registration = new GitSmartSubtransportRegistration();
registration.SubtransportCallback = Marshal.GetFunctionPointerForDelegate(EntryPoints.SubtransportCallback);
registration.Rpc = typeof(RpcSmartSubtransport).IsAssignableFrom(typeof(T)) ? (uint)1 : (uint)0;
var registrationPointer = Marshal.AllocHGlobal(Marshal.SizeOf(registration));
Marshal.StructureToPtr(registration, registrationPointer, false);
return registrationPointer;
}
private IntPtr CreateFunctionPointer()
{
return Marshal.GetFunctionPointerForDelegate(EntryPoints.TransportCallback);
}
internal void Free()
{
Marshal.FreeHGlobal(RegistrationPointer);
RegistrationPointer = IntPtr.Zero;
}
private static class EntryPoints
{
// Because our GitSmartSubtransportRegistration structure exists on the managed heap only for a short time (to be marshaled
// to native memory with StructureToPtr), we need to bind to static delegates. If at construction time
// we were to bind to the methods directly, that's the same as newing up a fresh delegate every time.
// Those delegates won't be rooted in the object graph and can be collected as soon as StructureToPtr finishes.
public static GitSmartSubtransportRegistration.create_callback SubtransportCallback = new GitSmartSubtransportRegistration.create_callback(Subtransport);
public static NativeMethods.git_transport_cb TransportCallback = new NativeMethods.git_transport_cb(Transport);
private static int Subtransport(
out IntPtr subtransport,
IntPtr transport,
IntPtr payload)
{
subtransport = IntPtr.Zero;
try
{
var obj = new T();
obj.Transport = transport;
subtransport = obj.GitSmartSubtransportPointer;
return 0;
}
catch (Exception ex)
{
Proxy.git_error_set_str(GitErrorCategory.Net, ex);
}
return (int)GitErrorCode.Error;
}
private static int Transport(
out IntPtr transport,
IntPtr remote,
IntPtr payload)
{
transport = IntPtr.Zero;
try
{
return NativeMethods.git_transport_smart(out transport, remote, payload);
}
catch (Exception ex)
{
Proxy.git_error_set_str(GitErrorCategory.Net, ex);
}
return (int)GitErrorCode.Error;
}
}
}
}