Skip to content

Commit

Permalink
unsafe is no longer mandatory
Browse files Browse the repository at this point in the history
  • Loading branch information
Jayatubi committed Mar 7, 2019
1 parent d4beb1a commit d759e55
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 110 deletions.
87 changes: 56 additions & 31 deletions Assets/curl-unity/Scripts/CurlEasy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,18 @@ public long recievedDataLength

private GCHandle thisHandle;

#if !ALLOW_UNSAFE
private byte[] buffer;
private byte[] AcquireBuffer(long size)
{
if (buffer == null || buffer.Length < size)
{
buffer = new byte[size];
}
return buffer;
}
#endif

private static string s_capath;

static CurlEasy()
Expand Down Expand Up @@ -202,10 +214,7 @@ public CURLE GetInfo(CURLINFO info, out string value)
var result = Lib.curl_easy_getinfo_ptr(easyPtr, info, ref ptr);
if (ptr != IntPtr.Zero)
{
unsafe
{
value = Marshal.PtrToStringAnsi((IntPtr)ptr.ToPointer());
}
value = Marshal.PtrToStringAnsi(ptr);
}
return result;
}
Expand Down Expand Up @@ -328,9 +337,9 @@ private void Prepare()
// Fill request header
var requestHeader = new CurlSlist(IntPtr.Zero);
requestHeader.Append($"Content-Type:{contentType}");
if (this.userHeader != null)
if (userHeader != null)
{
foreach (var entry in this.userHeader)
foreach (var entry in userHeader)
{
requestHeader.Append(entry.Key + ":" + entry.Value);
}
Expand Down Expand Up @@ -527,60 +536,76 @@ public string GetResponseHeader(string key)
[AOT.MonoPInvokeCallback(typeof(Delegates.HeaderFunction))]
private static int HeaderFunction(IntPtr ptr, int size, int nmemb, IntPtr userdata)
{
size = size * nmemb;
var thiz = ((GCHandle)userdata).Target as CurlEasy;
#if ALLOW_UNSAFE
unsafe
{
size = size * nmemb;
var ums = new UnmanagedMemoryStream((byte*)ptr, size);
var thiz = ((GCHandle)userdata).Target as CurlEasy;
ums.CopyTo(thiz.responseHeaderStream);
return size;
}
#else
var bytes = thiz.AcquireBuffer(size);
Marshal.Copy(ptr, bytes, 0, size);
thiz.responseHeaderStream.Write(bytes, 0, size);
#endif
return size;
}

[AOT.MonoPInvokeCallback(typeof(Delegates.WriteFunction))]
private static int WriteFunction(IntPtr ptr, int size, int nmemb, IntPtr userdata)
{
size = size * nmemb;
var thiz = ((GCHandle)userdata).Target as CurlEasy;
#if ALLOW_UNSAFE
unsafe
{
size = size * nmemb;
var ums = new UnmanagedMemoryStream((byte*)ptr, size);
var thiz = ((GCHandle)userdata).Target as CurlEasy;
ums.CopyTo(thiz.responseBodyStream);
return size;
}
#else
var bytes = thiz.AcquireBuffer(size);
Marshal.Copy(ptr, bytes, 0, size);
thiz.responseBodyStream.Write(bytes, 0, size);
#endif
return size;
}

[AOT.MonoPInvokeCallback(typeof(Delegates.DebugFunction))]
private static int DebugFunction(IntPtr ptr, CURLINFODEBUG type, IntPtr data, int size, IntPtr userdata)
{
if (type == CURLINFODEBUG.HEADER_OUT)
{
StreamReader sr = null;
var thiz = ((GCHandle)userdata).Target as CurlEasy;
#if ALLOW_UNSAFE
unsafe
{
var ums = new UnmanagedMemoryStream((byte*)data, size);
var sr = new StreamReader(ums);
sr = new StreamReader(ums);
}
#else
var bytes = thiz.AcquireBuffer(size);
Marshal.Copy(ptr, bytes, 0, size);
sr = new StreamReader(new MemoryStream(bytes));
#endif
// Handle first line
var firstLine = sr.ReadLine();

// Handle first line
while (true)
{
var line = sr.ReadLine();
if (!string.IsNullOrEmpty(line))
{
var firstLine = sr.ReadLine();
var index = line.IndexOf(':');
if (thiz.outHeader == null) thiz.outHeader = new Dictionary<string, string>();
var key = line.Substring(0, index).Trim();
var value = line.Substring(index + 1).Trim();
thiz.outHeader[key] = value;
}

while (true)
else
{
var line = sr.ReadLine();
if (!string.IsNullOrEmpty(line))
{
var index = line.IndexOf(':');
var thiz = ((GCHandle)userdata).Target as CurlEasy;
if (thiz.outHeader == null) thiz.outHeader = new Dictionary<string, string>();
var key = line.Substring(0, index).Trim();
var value = line.Substring(index + 1).Trim();
thiz.outHeader[key] = value;
}
else
{
break;
}
break;
}
}
}
Expand Down
29 changes: 11 additions & 18 deletions Assets/curl-unity/Scripts/CurlSlist.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,31 @@ public CurlSlist(IntPtr _ptr)

public void Dispose()
{
unsafe
if (ptr != IntPtr.Zero)
{
if (ptr != IntPtr.Zero)
{
Lib.curl_slist_free_all((IntPtr)(ptr));
ptr = IntPtr.Zero;
}
Lib.curl_slist_free_all(ptr);
ptr = IntPtr.Zero;
}
}

public List<string> GetStrings()
{
var result = new List<string>();
unsafe

var iter = ptr;
while (iter != IntPtr.Zero)
{
var iter = (__curl_slist*)(ptr);
while(iter != null)
{
result.Add(Marshal.PtrToStringAnsi(iter->data));
iter = (__curl_slist*)(iter->next);
}
var slist = Marshal.PtrToStructure<__curl_slist>(iter);
result.Add(Marshal.PtrToStringAnsi(slist.data));
iter = slist.next;
}

return result;
}

public void Append(string value)
{
unsafe
{
var head = (__curl_slist*)(ptr);
ptr = Lib.curl_slist_append((IntPtr)head, value);
}
ptr = Lib.curl_slist_append(ptr, value);
}

public static explicit operator IntPtr(CurlSlist slist)
Expand Down
37 changes: 1 addition & 36 deletions Packages/manifest.json
Original file line number Diff line number Diff line change
@@ -1,40 +1,5 @@
{
"dependencies": {
"com.unity.ads": "2.0.8",
"com.unity.analytics": "3.2.2",
"com.unity.collab-proxy": "1.2.15",
"com.unity.package-manager-ui": "2.0.3",
"com.unity.purchasing": "2.0.3",
"com.unity.textmeshpro": "1.3.0",
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.animation": "1.0.0",
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.cloth": "1.0.0",
"com.unity.modules.director": "1.0.0",
"com.unity.modules.imageconversion": "1.0.0",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.particlesystem": "1.0.0",
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.physics2d": "1.0.0",
"com.unity.modules.screencapture": "1.0.0",
"com.unity.modules.terrain": "1.0.0",
"com.unity.modules.terrainphysics": "1.0.0",
"com.unity.modules.tilemap": "1.0.0",
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.uielements": "1.0.0",
"com.unity.modules.umbra": "1.0.0",
"com.unity.modules.unityanalytics": "1.0.0",
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.unitywebrequestassetbundle": "1.0.0",
"com.unity.modules.unitywebrequestaudio": "1.0.0",
"com.unity.modules.unitywebrequesttexture": "1.0.0",
"com.unity.modules.unitywebrequestwww": "1.0.0",
"com.unity.modules.vehicles": "1.0.0",
"com.unity.modules.video": "1.0.0",
"com.unity.modules.vr": "1.0.0",
"com.unity.modules.wind": "1.0.0",
"com.unity.modules.xr": "1.0.0"
"com.unity.package-manager-ui": "2.0.3"
}
}
5 changes: 3 additions & 2 deletions ProjectSettings/ProjectSettings.asset
Original file line number Diff line number Diff line change
Expand Up @@ -528,15 +528,16 @@ PlayerSettings:
webGLCompressionFormat: 1
webGLLinkerTarget: 1
webGLThreadsSupport: 0
scriptingDefineSymbols: {}
scriptingDefineSymbols:
1:
platformArchitecture:
iOS: 1
scriptingBackend:
Android: 1
il2cppCompilerConfiguration: {}
managedStrippingLevel: {}
incrementalIl2cppBuild: {}
allowUnsafeCode: 1
allowUnsafeCode: 0
additionalIl2CppArgs:
scriptingRuntimeVersion: 1
apiCompatibilityLevelPerPlatform:
Expand Down
59 changes: 36 additions & 23 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# curl-unity

This is a C# wrapper for Unity to use [libcurl](https://github.com/curl/curl) with [http2](https://github.com/curl/curl)/[openssl](https://github.com/openssl/openssl) enabled.
This is a C# wrapper for Unity to use [libcurl](https://github.com/curl/curl) with [http2](https://github.com/nghttp2/nghttp2)/[openssl](https://github.com/openssl/openssl) enabled.

## Supported platforms

Expand All @@ -21,8 +21,8 @@ This is a C# wrapper for Unity to use [libcurl](https://github.com/curl/curl) wi

## Requirements

* [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/) is requried for macOS/iOS/Android. It could be installed via `brew install pkg-config` on macOS.
* [CMake](https://cmake.org/download/) is required for all platforms.
* [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/) is requried for macOS/iOS/Android. It could be installed via `brew install pkg-config` on macOS.
* [NDK r16b](https://developer.android.com/ndk/downloads/older_releases.html) is required for Android.
* Xcode is required for macOS/iOS.
* Visual Studio 2017 and [Perl](https://www.activestate.com/products/activeperl/downloads/) is required for Windows.
Expand All @@ -49,41 +49,61 @@ Build `curl.bundle` for macOS. Please use this script on macOS.

Build `curl.dll` for Windows. Please use this script on Windows.

# Install

Copy `Assets/curl-unity` to anywhere under your Unity project and done.

Besides, for a better performance you could enable `Allow unsafe code` and add `ALLOW_UNSAFE` to the `Scripting Define Symbols` in the project settings.

![project settings](doc/project_settings.png)

# Usage

## Blocking perform
## Non-blocking multi perform (single thread, recommended)

> Only by using this multi perform that could take the advantage of HTTP/2 multiplexing feature.
```csharp
void Start()
{
var easy = new CurlEasy();
easy.url = "https://nghttp2.org";
easy.useHttp2 = true;
easy.timeout = 5000;
if (easy.Perform() == CURLE.OK)
for (int i = 0; i < 5; i++)
{
var easy = new CurlEasy();
easy.url = "https://nghttp2.org";
easy.useHttp2 = true;
easy.timeout = 5000;
easy.performCallback = OnPerformCallback;

// You could also create your own CurlMulti instance
easy.MultiPerform(CurlMulti.DefaultMulti);
}
}

void OnPerformCallback(CURLE result, CurlEasy easy)
{
if (result == CURLE.OK)
{
Debug.Log(Encoding.UTF8.GetString(easy.inData));
Debug.Log(easy.inText);
}
}
```

## Non-Blocking perform via multi thread
## Non-blocking easy perform (multi thread, experimental, lock is not implemented yet)
```csharp
void Start()
async void Start()
{
var easy = new CurlEasy();
easy.url = "https://nghttp2.org";
easy.useHttp2 = true;
easy.timeout = 5000;
if (await easy.PerformAsync() == CURLE.OK)
{
Debug.Log(Encoding.UTF8.GetString(easy.inData));
Debug.Log(easy.inText);
}
}
```


## Non-Blocking perform via single thread (Recommended)
## Blocking easy perform

```csharp
void Start()
Expand All @@ -92,16 +112,9 @@ void Start()
easy.url = "https://nghttp2.org";
easy.useHttp2 = true;
easy.timeout = 5000;

var multi = new CurlMulti();
easy.MultiPerform(multi, OnPerformCallback);
}

void OnPerformCallback(CURLE result, CurlEasy easy)
{
if (result == CURLE.OK)
if (easy.Perform() == CURLE.OK)
{
Debug.Log(Encoding.UTF8.GetString(easy.inData));
Debug.Log(easy.inText);
}
}
```
Binary file added doc/project_settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit d759e55

Please sign in to comment.