mirror of
https://github.com/Jackett/Jackett.git
synced 2025-09-17 17:34:09 +02:00
MoreThanTv now working on mono with libcurl
This commit is contained in:
276
src/CurlSharp/CurlShare.cs
Normal file
276
src/CurlSharp/CurlShare.cs
Normal file
@@ -0,0 +1,276 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* CurlS#arp
|
||||
*
|
||||
* Copyright (c) 2013 Dr. Masroor Ehsan (masroore@gmail.com)
|
||||
* Portions copyright (c) 2004, 2005 Jeff Phillips (jeff@jeffp.net)
|
||||
*
|
||||
* This software is licensed as described in the file LICENSE, which you
|
||||
* should have received as part of this distribution.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of this Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the LICENSE file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
|
||||
* ANY KIND, either express or implied.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CurlSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This class provides an infrastructure for serializing access to data
|
||||
/// shared by multiple <see cref="CurlEasy" /> objects, including cookie data
|
||||
/// and Dns hosts. It implements the <c>curl_share_xxx</c> API.
|
||||
/// </summary>
|
||||
public class CurlShare : IDisposable
|
||||
{
|
||||
// private members
|
||||
private GCHandle _hThis; // for handle extraction
|
||||
private CurlShareCode _lastErrorCode;
|
||||
private string _lastErrorDescription;
|
||||
#if USE_LIBCURLSHIM
|
||||
private NativeMethods._ShimLockCallback _pDelLock; // lock delegate
|
||||
private NativeMethods._ShimUnlockCallback _pDelUnlock; // unlock delegate
|
||||
#endif
|
||||
private IntPtr _pShare; // share handle
|
||||
private CurlShareLockCallback _pfLock; // client lock delegate
|
||||
private CurlShareUnlockCallback _pfUnlock; // client unlock delegate
|
||||
private IntPtr _ptrThis; // numeric handle
|
||||
private Object _userData; // user data for delegates
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// This is thrown
|
||||
/// if <see cref="Curl" /> hasn't bee properly initialized.
|
||||
/// </exception>
|
||||
/// <exception cref="System.NullReferenceException">
|
||||
/// This is thrown if
|
||||
/// the native <c>share</c> handle wasn't created successfully.
|
||||
/// </exception>
|
||||
public CurlShare()
|
||||
{
|
||||
Curl.EnsureCurl();
|
||||
_pShare = NativeMethods.curl_share_init();
|
||||
EnsureHandle();
|
||||
LockFunction = null;
|
||||
UnlockFunction = null;
|
||||
UserData = null;
|
||||
installDelegates();
|
||||
}
|
||||
|
||||
public object UserData
|
||||
{
|
||||
get { return _userData; }
|
||||
set { _userData = value; }
|
||||
}
|
||||
|
||||
public CurlShareUnlockCallback UnlockFunction
|
||||
{
|
||||
get { return _pfUnlock; }
|
||||
set { _pfUnlock = value; }
|
||||
}
|
||||
|
||||
public CurlShareLockCallback LockFunction
|
||||
{
|
||||
get { return _pfLock; }
|
||||
set { _pfLock = value; }
|
||||
}
|
||||
|
||||
public CurlLockData Share
|
||||
{
|
||||
set { setShareOption(CurlShareOption.Share, value); }
|
||||
}
|
||||
|
||||
public CurlLockData Unshare
|
||||
{
|
||||
set { setShareOption(CurlShareOption.Unshare, value); }
|
||||
}
|
||||
|
||||
public CurlShareCode LastErrorCode
|
||||
{
|
||||
get { return _lastErrorCode; }
|
||||
}
|
||||
|
||||
public string LastErrorDescription
|
||||
{
|
||||
get { return _lastErrorDescription; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
~CurlShare()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set options for this object.
|
||||
/// </summary>
|
||||
/// <param name="option">
|
||||
/// One of the values in the <see cref="CurlShareOption" />
|
||||
/// enumeration.
|
||||
/// </param>
|
||||
/// <param name="parameter">
|
||||
/// An appropriate object based on the value passed in the
|
||||
/// <c>option</c> argument. See <see cref="CurlShareOption" />
|
||||
/// for more information about the appropriate parameter type.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="CurlShareCode" />, hopefully
|
||||
/// <c>CurlShareCode.Ok</c>.
|
||||
/// </returns>
|
||||
/// <exception cref="System.NullReferenceException">
|
||||
/// This is thrown if
|
||||
/// the native <c>share</c> handle wasn't created successfully.
|
||||
/// </exception>
|
||||
public CurlShareCode SetOpt(CurlShareOption option, Object parameter)
|
||||
{
|
||||
EnsureHandle();
|
||||
var retCode = CurlShareCode.Ok;
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case CurlShareOption.LockFunction:
|
||||
var lf = parameter as CurlShareLockCallback;
|
||||
if (lf == null)
|
||||
return CurlShareCode.BadOption;
|
||||
_pfLock = lf;
|
||||
break;
|
||||
|
||||
case CurlShareOption.UnlockFunction:
|
||||
var ulf = parameter as CurlShareUnlockCallback;
|
||||
if (ulf == null)
|
||||
return CurlShareCode.BadOption;
|
||||
_pfUnlock = ulf;
|
||||
break;
|
||||
|
||||
case CurlShareOption.Share:
|
||||
case CurlShareOption.Unshare:
|
||||
{
|
||||
var opt = (CurlLockData) Convert.ToInt32(parameter);
|
||||
retCode = setShareOption(option, opt);
|
||||
break;
|
||||
}
|
||||
|
||||
case CurlShareOption.UserData:
|
||||
_userData = parameter;
|
||||
break;
|
||||
|
||||
default:
|
||||
retCode = CurlShareCode.BadOption;
|
||||
break;
|
||||
}
|
||||
return retCode;
|
||||
}
|
||||
|
||||
private void setLastError(CurlShareCode code, CurlShareOption opt)
|
||||
{
|
||||
if (_lastErrorCode == CurlShareCode.Ok && code != CurlShareCode.Ok)
|
||||
{
|
||||
_lastErrorCode = code;
|
||||
_lastErrorDescription = string.Format("Error: {0} setting option {1}", StrError(code), opt);
|
||||
}
|
||||
}
|
||||
|
||||
private CurlShareCode setShareOption(CurlShareOption option, CurlLockData value)
|
||||
{
|
||||
var retCode = (value != CurlLockData.Cookie) && (value != CurlLockData.Dns)
|
||||
? CurlShareCode.BadOption
|
||||
: NativeMethods.curl_share_setopt(_pShare, option, (IntPtr) value);
|
||||
setLastError(retCode, option);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a String description of an error code.
|
||||
/// </summary>
|
||||
/// <param name="errorNum">
|
||||
/// The <see cref="CurlShareCode" /> for which to obtain the error
|
||||
/// string description.
|
||||
/// </param>
|
||||
/// <returns>The string description.</returns>
|
||||
public String StrError(CurlShareCode errorNum)
|
||||
{
|
||||
return Marshal.PtrToStringAnsi(NativeMethods.curl_share_strerror(errorNum));
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// if (disposing) cleanup managed objects
|
||||
if (_pShare != IntPtr.Zero)
|
||||
{
|
||||
#if USE_LIBCURLSHIM
|
||||
NativeMethods.curl_shim_cleanup_share_delegates(_pShare);
|
||||
#endif
|
||||
NativeMethods.curl_share_cleanup(_pShare);
|
||||
_hThis.Free();
|
||||
_ptrThis = IntPtr.Zero;
|
||||
_pShare = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal IntPtr GetHandle()
|
||||
{
|
||||
return _pShare;
|
||||
}
|
||||
|
||||
private void EnsureHandle()
|
||||
{
|
||||
if (_pShare == IntPtr.Zero)
|
||||
throw new NullReferenceException("No internal share handle");
|
||||
}
|
||||
|
||||
private void installDelegates()
|
||||
{
|
||||
_hThis = GCHandle.Alloc(this);
|
||||
_ptrThis = (IntPtr)_hThis;
|
||||
#if USE_LIBCURLSHIM
|
||||
_pDelLock = LockDelegate;
|
||||
_pDelUnlock = UnlockDelegate;
|
||||
NativeMethods.curl_shim_install_share_delegates(_pShare, _ptrThis, _pDelLock, _pDelUnlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static void LockDelegate(int data, int access, IntPtr userPtr)
|
||||
{
|
||||
var gch = (GCHandle) userPtr;
|
||||
var share = (CurlShare) gch.Target;
|
||||
if (share == null)
|
||||
return;
|
||||
if (share.LockFunction == null)
|
||||
return;
|
||||
share.LockFunction((CurlLockData) data, (CurlLockAccess) access, share.UserData);
|
||||
}
|
||||
|
||||
internal static void UnlockDelegate(int data, IntPtr userPtr)
|
||||
{
|
||||
var gch = (GCHandle) userPtr;
|
||||
var share = (CurlShare) gch.Target;
|
||||
if (share == null)
|
||||
return;
|
||||
if (share.UnlockFunction == null)
|
||||
return;
|
||||
share.UnlockFunction((CurlLockData) data, share.UserData);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user