Jackett: .NET Core 2 Investigation/Thoughts

Created on 17 Aug 2017  路  46Comments  路  Source: Jackett/Jackett

.NET Core 2 was released earlier this week

Have a had a quick play and it is more polished than 1.0 with tooling now present and the ability to use class libraries written before NETStandard and NETCore eg CsQuery

At the same time it isn't going an hour job, biggest job on initial mucking around was changing the web server from Owin to Kestrel, but @chibidev 's recent changes should simply things and .NET Core is designed for this instead of an addition like Owin

Advantages from switching
-No more Mono
-Behaviour should be predictable in terms of one set of code (no more CurlSharp) and no more developing on .NET and then 95% of users of running it on Mono
-Runtime gets packaged with the release, so everyone runs the version that it was developed on, instead of a million different Mono versions

Thoughts?
Worthwhile?

I'm happy to contribute, but haven't got the time or ability to do the entire thing

@kaso17 @chibidev @JigSawFr


Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

Core Needs Investigations

All 46 comments

It could be great to switch on .Net Core 2 for all advantages that you said. I think we could create a new branch and start working on ?

If we can continue to use CsQuery it should be possible to make the necessary changes. That was the biggest show stopper for me last time I checked.

I'm just a little bit concerned regarding the ARM32 users (Synlogogy, rasperypi, ...). AFAIK .NET core is not officially supported for ARM32 but there's community support. Not sure how complete/stable it is.
On the other hand it might solve a lot of problems with users which are stuck with old mono 4.6 versions.

@flightlevel do you know how crypto is implemented in .NET core? Is it platform independent or does it still rely on platform specific libraries? Is TLS 1.3 supported?

@flightlevel Thanks for launching up the conversation. I'd really want to move forward with this, however it's unclear to me how big of a work we're really talking about.
From what I can gather most changes will affect the startup and the additional filters/attributes we have on the controllers.
Would it be possible to somehow estimate the work to be done?

@kaso17 ARM32 builds are now available in preview (https://github.com/dotnet/announcements/issues/29). I don't know how big of a userbase we're talking about, but it might not impact them that much. It's unclear though how long do they have to wait for non-preview ARM32, so it might be a little risky jumping in right now.

Thanks for the comments guys

ARM32
Don't think its a show stopper, think its just more later to the party. .NET core 2.1 due later this year as well. This https://github.com/dotnet/announcements/issues/29 The builds are not yet supported by Microsoft and have preview status. Please give us feedback. 'Yet' implies that it will eventually to me and roadmap indicates goals are to have a high quality ARM32 version https://github.com/dotnet/core/blob/master/roadmap.md Personally have more confidence in Microsoft preview than the current Mono mess. But maybe once we get something that builds, we can ask a few Pi users to see if it will run for them...

TLS
.NET core uses the OS https://stackoverflow.com/questions/39354863/why-is-openssl-required-to-run-net-core-on-os-x-mac-os . So if it runs in your web browser should just work unlike Mono

Time frame
I'm terrible at that, will try and get a branch up over the weekend and everyone can have a muck around, see what they think

Had a bit of a play https://github.com/Jackett/Jackett/tree/dotnetcore
As expected biggest area of work initially looks to be the controllers, will try and have another go on Sunday

@flightlevel it's not possible to compare the branch to the current master, can you convert it to a proper branch?

Done, its brutal though, just trying to simplify things, more proof of concept

The bower packages needed in the bower.json are:

"dependencies": {
    "bootstrap": "boostrap#3.3.4",
    "components-font-awesome": "4.3.0",
    "datatables": "1.10.13",
    "jquery": "3.1.1",
    "remarkable-bootstrap-notify": "3.0.2",
    "filesize": "3.1.2",
    "handlebars": "3.0.3"
  }

Really would appreciate this!

I'm happy to pick this up, started playing around with it today and it looks like it's entirely possible without too much work.

My current thinking is to split the code up into .NET Standard libraries, get that working with .NET Framework on the current build system and then start working on the actual .NET Core implementation.

In order to have both running at the same time I believe we'll have to clean up the architecture somewhat and move to VS2017, .NET 4.5.2 and .Mono 4.6 - will open another issue tracker for this and see how we go.

Okay, so I've made some progress.
https://github.com/NathanNZ/Jackett/tree/feature/netcore-preparation

Only one library seems to be causing issues now, so I've put in a pull request for that and we'll see how we go:
https://github.com/elcattivo/CloudFlareUtilities/pull/19

After that I'll need to write some unit tests for some of the troublesome areas (I've commented in TODO's) and then we'll see how we go.

Awesome work there @NathanNZ

Hey guys, just to let you know I won't be continuing this work. This started as something I was working on to assist a friend who used Jackett to make a small docker image using .net core for his own small side project but unfortunately I'm struggling to put aside the time to work on hobby projects I don't personally use day to day. (plus testing and finding inspiration is much harder).

On a positive note it shouldn't be too difficult to put the final bits together now that everything is running on .NET Standard - good luck and keep up the great work!

Thank you for all the effort you put into this.

Is there any forward momentum still on this? Tried locating the forks/branches for the Core code changes and progress as I'm going to be using Jackett myself soon and would prefer net core over mono; even if some assembly is required. Re @kaso17 & @NathanNZ

I did not find any forks / branches either... @NathanNZ did you commit your work anywhere?

I belief the only thing left is the porting of the web server part to ASP.NET core.
I don't think anyone is working on this currently.
While I never worked with ASP.NET core I wouldn't expect that it to be to much work.

Besides that we probably have to exclude JackettTray (Contains references to System.Windows.Forms) and JackettService.exe (Windows Service stuff) from the .NET core build.
Besides that the Jackett.Common and Jackett.Console project should contain only minimal references (Service start/stop/install) to non .NET core supported APIs. All of them should be easy to completely exclude in the .NET core build.

@PhyberApex all of @NathanNZ's work has been merged into master, there are currently no active branches

Is this still wanted?
What is left to be done?

definitely still wanted.

Migrating the web server to ASP.NET core is probably the only bigger piece of work left.

Alright, I'll give it a go and see how far I can get.

Edit: Nevermind, this is too messy for me to work with. Someone with more experience with the Jackett core should do this.

Made a start on this in https://github.com/Jackett/Jackett/tree/dotnetcore
Have tried not to make the commits too big
Going relatively smoothly so far, have got the basics to load up i.e. can do a test and get results

Current plan is create a new project called 'Jackett.Server' (can change name later). This will cover the functions of both 'Jackett.Console' and 'Jackett'. It means we can build both versions (full framework mono and net core) in the crossover period, both consuming Jackett.Common

Thanks to @NathanNZ done an awesome job

-Next steps are authorization and doing something with the configuration e.g. run on port supplied

One challenge is going to be the data protection API. It works fine as is on net core being Windows based, but obvious isn't present on other OSes. The new version looks easy to use https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/?view=aspnetcore-2.1 just not sure how hard it would be to migrate indexers for non windows users yet (or maybe they just have to reconfigure them)

@kaso17 Okay with me bumping supported systems on the readme to
Mono 5.4 or .NET 4.6.1?

@flightlevel yes, given that even the embedded Systems (qnap, synology, ...) migrated to mono >=5.8 it shouldn't be a problem.

@kaso17 @garfield69
If you use Windows, can you have a play with Jackett Service and Jackett Tray in the pre-release to make sure I haven't broken anything.
Bigger project than I thought, getting there though...

@flightlevel 1158 works fine for me on linux and on windows 7 (service update + fresh install + tray).
But it seems like the automatic release description is broken (see the v0.8.1160 draft).

Thanks @kaso17 for testing
Yeah that's weird with 1160, then it worked fine for 1162 with the TNTVillage commit but still didn't include yours, will investigate if it happens again

Think I'm finally there! Jackett is now running on NET461 in a project that it is .NET Core Compatible

Major changes

  • New project Jackett.Server handles the functions of Jackett.Console & Jackett
  • Dependency injection container has moved from the Jackett.Common library to the Jackett.Server application
  • Startup configuration is now loaded without dependency injection
  • All protected passwords will be re-protected using Microsoft.AspNetCore.DataProtection which is cross platform. Once we leave Mono, we will lose access to the DPAPI and passwords won't be able to be unprotected
  • Jackett.Server is both full framework net461 and netcoreapp2.1 compatible

Deployment

Happy to take ideas, was thinking something along of the lines of:

Phase 1
  • Non breaking change for users v0.9, really shouldn't notice anything too different
  • Fairly sizeable code change, so likely to be some issues
  • The same three artifacts as current will be released, difference being they will need .NET 4.6.1+ or Mono 5.8+
  • As users upgrade their passwords will automatically be re-protected with Microsoft.AspNetCore.DataProtection
  • Iron out any regressions and more refactoring can take place as once Owin releases are finished: CurlSharp, Jackett, Jackett.Console & some Common logic won't be needed

    Phase 2
  • Probably a couple of months later

  • Breaking change for non-Windows users v1.0, won't be using Mono to start Jackett
  • Code changes should be very minor, just updating the update logic to handle the extra artifacts e.g. ARM32
  • Can easily continue releasing a Mono build for a period while users transition as the code base will be the same

Testing

@kaso17 @garfield69 can you have a try of:
Make sure you backup your indexer configs so you don't have to reconfigure indexers when using an Owin version
https://ci.appveyor.com/project/Jackett/jackett/build/0.8.1172/artifacts
Experimental.Jackett.Binaries.Mono.tar.gz
Experimental.Jackett.Binaries.Windows.zip
Experimental.Jackett.Installer.Windows.exe
and see what you think. I've got a very basic setup (english only private trackers, no reverse proxy), so definitely needs more testing
I think the next step after that should be creating a Beta testers 'issue' and getting some users to try it out before pre-release so we don't get stuck on continuous pre-releases now that it seems like lots of users use the pre-releases

@kaso17
Can you have a look at the code and see what you think? It's far from perfect, but I think cleaner than what we had previously. Would like to go further with the refactoring but it's just a bit painful at the moment having to make legacy changes, will be much easier once that stuff goes.
Merging it back into master should be low risk. The only two files that we currently use that will get changed are the solution file to add the new project and the build script. With the two sets of artifacts can potentially release the Kestrel version to Windows users for testing without having to go to Mono users at the same time.

Only did a quick test run without looking at it in detail yet.

On an amd64 Ubuntu 16.04 system SSL isn't working:

06-24 12:11:56 Debug WebClient(HttpWebClient).GetString(Url:https://api.broadcasthe.net)
06-24 12:11:56 Error On attempt 3 checking for results from BroadcastTheNet: The SSL connection could not be established, see inner exception.
06-24 12:11:56 Info Executed action Jackett.Server.Controllers.IndexerApiController.Test (JackettConsole) in 2782.7587ms
06-24 12:11:56 Error Jackett.Common.IndexerException: Exception (broadcastthenet): error:2006D002:BIO routines:BIO_new_file:system lib ---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> Interop+Crypto+OpenSslCryptographicException: error:2006D002:BIO routines:BIO_new_file:system lib
   at Interop.Crypto.CheckValidOpenSslHandle(SafeHandle handle)
   at Internal.Cryptography.Pal.StorePal.LoadMachineStores()
   at Internal.Cryptography.Pal.StorePal.FromSystemStore(String storeName, StoreLocation storeLocation, OpenFlags openFlags)
   at System.Security.Cryptography.X509Certificates.X509Store.Open(OpenFlags flags)
   at Internal.Cryptography.Pal.OpenSslX509ChainProcessor.FindCandidates(X509Certificate2 leaf, X509Certificate2Collection extraStore, HashSet`1 downloaded, HashSet`1 systemTrusted, TimeSpan& remainingDownloadTime)
   at Internal.Cryptography.Pal.ChainPal.BuildChain(Boolean useMachineContext, ICertificatePal cert, X509Certificate2Collection extraStore, OidCollection applicationPolicy, OidCollection certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, DateTime verificationTime, TimeSpan timeout)
   at System.Security.Cryptography.X509Certificates.X509Chain.Build(X509Certificate2 certificate, Boolean throwOnException)
   at System.Security.Cryptography.X509Certificates.X509Chain.Build(X509Certificate2 certificate)
   at System.Net.Security.CertificateValidation.BuildChainAndVerifyProperties(X509Chain chain, X509Certificate2 remoteCertificate, Boolean checkCertName, String hostName)
   at System.Net.Security.SecureChannel.VerifyRemoteCertificate(RemoteCertValidationCallback remoteCertValidationCallback, ProtocolToken& alertToken)
   at System.Net.Security.SslState.CompleteHandshake(ProtocolToken& alertToken)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Security.SslState.ThrowIfExceptional()
   at System.Net.Security.SslState.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)
   at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
   at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__47_1(IAsyncResult iar)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at Jackett.Common.Indexers.BaseWebIndexer.PostDataWithCookiesAndRetry(String url, IEnumerable`1 data, String cookieOverride, String referer, Dictionary`2 headers, String rawbody, Nullable`1 emulateBrowser) in C:\projects\jackett\src\Jackett.Common\Indexers\BaseIndexer.cs:line 521
   at Jackett.Common.Indexers.BroadcastTheNet.PerformQuery(TorznabQuery query) in C:\projects\jackett\src\Jackett.Common\Indexers\BroadcastTheNet.cs:line 99
   at Jackett.Common.Indexers.BaseIndexer.ResultsForQuery(TorznabQuery query) in C:\projects\jackett\src\Jackett.Common\Indexers\BaseIndexer.cs:line 325
   --- End of inner exception stack trace ---
   at Jackett.Common.Indexers.BaseIndexer.ResultsForQuery(TorznabQuery query) in C:\projects\jackett\src\Jackett.Common\Indexers\BaseIndexer.cs:line 345
   at Jackett.Common.Indexers.BaseWebIndexer.ResultsForQuery(TorznabQuery query) in C:\projects\jackett\src\Jackett.Common\Indexers\BaseIndexer.cs:line 808
   at Jackett.Common.Services.IndexerManagerService.TestIndexer(String name) in C:\projects\jackett\src\Jackett.Common\Services\IndexerManagerService.cs:line 222
   at Jackett.Server.Controllers.IndexerApiController.Test() in C:\projects\jackett\src\Jackett.Server\Controllers\IndexerApiController.cs:line 128
   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at Jackett.Server.Middleware.CustomExceptionHandler.Invoke(HttpContext httpContext) in C:\projects\jackett\src\Jackett.Server\Middleware\CustomExceptionHandler.cs:line 29 Jackett.Common.IndexerException: Exception (broadcastthenet): error:2006D002:BIO routines:BIO_new_file:system lib ---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> Interop+Crypto+OpenSslCryptographicException: error:2006D002:BIO routines:BIO_new_file:system lib
   at Interop.Crypto.CheckValidOpenSslHandle(SafeHandle handle)
   at Internal.Cryptography.Pal.StorePal.LoadMachineStores()
   at Internal.Cryptography.Pal.StorePal.FromSystemStore(String storeName, StoreLocation storeLocation, OpenFlags openFlags)
   at System.Security.Cryptography.X509Certificates.X509Store.Open(OpenFlags flags)
   at Internal.Cryptography.Pal.OpenSslX509ChainProcessor.FindCandidates(X509Certificate2 leaf, X509Certificate2Collection extraStore, HashSet`1 downloaded, HashSet`1 systemTrusted, TimeSpan& remainingDownloadTime)
   at Internal.Cryptography.Pal.ChainPal.BuildChain(Boolean useMachineContext, ICertificatePal cert, X509Certificate2Collection extraStore, OidCollection applicationPolicy, OidCollection certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, DateTime verificationTime, TimeSpan timeout)
   at System.Security.Cryptography.X509Certificates.X509Chain.Build(X509Certificate2 certificate, Boolean throwOnException)
   at System.Security.Cryptography.X509Certificates.X509Chain.Build(X509Certificate2 certificate)
   at System.Net.Security.CertificateValidation.BuildChainAndVerifyProperties(X509Chain chain, X509Certificate2 remoteCertificate, Boolean checkCertName, String hostName)
   at System.Net.Security.SecureChannel.VerifyRemoteCertificate(RemoteCertValidationCallback remoteCertValidationCallback, ProtocolToken& alertToken)
   at System.Net.Security.SslState.CompleteHandshake(ProtocolToken& alertToken)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Security.SslState.ThrowIfExceptional()
   at System.Net.Security.SslState.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)
   at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
   at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__47_1(IAsyncResult iar)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at Jackett.Common.Indexers.BaseWebIndexer.PostDataWithCookiesAndRetry(String url, IEnumerable`1 data, String cookieOverride, String referer, Dictionary`2 headers, String rawbody, Nullable`1 emulateBrowser) in C:\projects\jackett\src\Jackett.Common\Indexers\BaseIndexer.cs:line 521
   at Jackett.Common.Indexers.BroadcastTheNet.PerformQuery(TorznabQuery query) in C:\projects\jackett\src\Jackett.Common\Indexers\BroadcastTheNet.cs:line 99
   at Jackett.Common.Indexers.BaseIndexer.ResultsForQuery(TorznabQuery query) in C:\projects\jackett\src\Jackett.Common\Indexers\BaseIndexer.cs:line 325
   --- End of inner exception stack trace ---
   at Jackett.Common.Indexers.BaseIndexer.ResultsForQuery(TorznabQuery query) in C:\projects\jackett\src\Jackett.Common\Indexers\BaseIndexer.cs:line 345
   at Jackett.Common.Indexers.BaseWebIndexer.ResultsForQuery(TorznabQuery query) in C:\projects\jackett\src\Jackett.Common\Indexers\BaseIndexer.cs:line 808
   at Jackett.Common.Services.IndexerManagerService.TestIndexer(String name) in C:\projects\jackett\src\Jackett.Common\Services\IndexerManagerService.cs:line 222
   at Jackett.Server.Controllers.IndexerApiController.Test() in C:\projects\jackett\src\Jackett.Server\Controllers\IndexerApiController.cs:line 128
   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at Jackett.Server.Middleware.CustomExceptionHandler.Invoke(HttpContext httpContext) in C:\projects\jackett\src\Jackett.Server\Middleware\CustomExceptionHandler.cs:line 29
06-24 12:11:57 Info Request finished in 4383.5778ms 500 application/json

Interesting... thanks @kaso17
I tested on Debian 9 with Mono 5.8 and Ubuntu 14 with Mono 5.12 and https indexers work for me

Could be something to do with the patch in build script for mono builds here https://github.com/Jackett/Jackett/blob/dotnetcore/build.cake#L229-L237

Are you running the mono build or netcore build?

Apparently the error error:2006D002:BIO routines:BIO_new_file:system lib means it doesn't have read permissions for one of the certs

Microsoft issue
Emby issue

I'm running the netcore build.
Indeed the problem was just a missing read permissions on one of the certificates in /etc/ssl/certs/. I see it's already fixed in netcore master.

Really great work!

Your transition plan sounds fine to me. I think we definitely should continue to provide a mono version for some time (especially for the embedded systems which often run really old openssl versions).

Do you have any plans for the data protection API transition for mono users? I don't think we can dynamically load the corresponding mono assemblies to unprotect them (probably needs some mono native code). Any chance you already tried this? I would suggest to add some "store passwords in plaintext" option which users can use during the transition.

Regarding migration: shouldn't it be possible to use the same migration logic used in BaseIndexer/MigratedFromDPAPI() for windows in case of mono too (essentially just by removing the isWindows check)? So the upgrade path would be normal/owin mono version => experimental/kestrel mono version => native netcore version

bool runningOnDotNetCore = RuntimeInformation.FrameworkDescription.IndexOf("core", StringComparison.OrdinalIgnoreCase) >= 0;
bool isWindows = Environment.OSVersion.Platform == PlatformID.Win32NT;

if (!isWindows && runningOnDotNetCore)
{
    // User isn't running Windows, but is running on .NET Core framework, no access to the DPAPI, so don't bother trying to migrate
    return false;
}

Could have named that variable better, really should be runningOnDotNetCoreFramework. The only time it shouldn't try and migrate is when we've lost access to Mono (running linux & you're running using the NetCore framework). We can probably put a good error in once we get to the .NET core stage i.e. run vers 0.9 before using .NET core version to keep your indexers...
So should do all of the above today, we are definitely on the same page. Hoping you'll test with all your indexers! It converted my owin indexers fine when I ran the Kestrel Mono version. Could then use those indexers in the native .NET core version. Just for that reason I think it's worth us staying on the Kestrel mono version for a while so most users will have their indexers converted before we even get to .Net core through normal updates. Should have included no .NET core release until we get to Phase 2

And agree we'll need Mono for a while. Think at this stage Microsoft support ARMv7 ie. works on Raspberry PI 2 & 3 but not Pi zero. And think some of the Synology & QNAP are less than v7. Will be interesting to see how Emby & Ombi go, think they plan to completely stop Mono...

Found an issue with refactored updater not starting the Windows service, will do another pre-release when I have some time tomorrow

Ok, the current migration is definitely not working for some indexers on windows and linux.
I'll look into this later.

6b44cc9b741f60f557f9f95d331283595491d8b2 and 8de0b0cbad5c920fd7f72c4a8a6f1e58cd70d8cb should fix the problem

The HttpClient certificate validation callback needs a little work too.
Using the global ServicePointManager.ServerCertificateValidationCallback no longer works. We've to adjust the ServerCertificateCustomValidationCallback property of the HttpClientHandler instance.

Thanks @kaso17
Can you have a go at the cert validation callback, sounds a bit beyond me.
Also, I've effectively hardcoded to use httpclient https://github.com/Jackett/Jackett/blob/dotnetcore/src/Jackett.Server/Program.cs#L51
Is that right or should we prefer httpclient2?

Sorry guys, I've been away from my development machine for the last month on a family emergency, which looks to go on for at least one or two month more.
Difficult to provide meaningful testing on my samsung table while away from home :-(
I will sporadically do simple updates using github web however, but expect reduced contributions from me for the moment. Cheers.

@garfield69 no worries, more important things than Jackett, good luck

@kaso17
Do you think we are ready for some beta testers?
Thinking
merge dotnetcoressl in
merge dotnetcore into master (won't change any of our released artifacts for now)
Disable the dotnetcore artifacts in the build script for now so that people don't start using them yet

yes, I think we're ready.

If you are keen for .NET Core support and run Mono, please try the latest beta version, its the last major step before we can support .NET Core
More details here
https://github.com/Jackett/Jackett/issues/3322

@kaso17 @garfield69 your thoughts appreciated

Will spend some time getting the update process going for .NET Core in the New Year

Was thinking now is the time for any breaking changes if you've got any you'd like to make. Users are going to have to download the .NET Core version and change their start scripts from mono JacketConsole.exe

Currently the .NET Core version is started with ./JackettConsole Thinking that ./Jackett probably makes more sense ???

Proposed plan

  • Windows is out of scope for now. We need full framewok for the tray icon (unless we moved to NSSM like Ombi). Can revisit once .NET Core 3.0 comes out which supports WinForms
  • Will still build a Mono version to support FreeBSD and older ARM NASes (pre ARMv7) and give people time to transition
  • First .NET Core release would go to OSX, due to smaller user base and smaller number of variables compared to Linux. Then Linux x64 and then Linux ARM

Proposed artificats

Jackett.Binaries.Mono.tar.gz NET461, no changes, same as today
Jackett.Binaries.Windows.zip NET461, no changes, same as today
Jackett.Installer.Windows.exe NET461, no changes, same as today
Jackett.Binaries.macOS.tar.gz All .NET Core (Jackett & Updater), (OSX or macOS??? tar.gz or zip???)
Jackett.Binaries.Linux-x64.tar.gz All .NET Core (Jackett & Updater), (x64 or AMD64???)
Jackett.Binaries.Linux-ARM32.tar.gz All .NET Core (Jackett & Updater), (ARM32 or ARM???)

I can dig out a MacMini for testing, no ARM devices though

I can help with test runs for x64 builds on win10, and on my virtual box I can do similar for ubuntu18 and Mojave.
But I'm no use to you regarding strategy decisions on platform software directions or build method selections. It's all out of scope of my limited expertise ;-)

I would vote for ./jackett (all lower case).

I've no breaking changes planned.
The only thing I could imagine is to change to some platform independent package management tool (but I'm not sure if there's such a thing) to avoid some problems with the current updater (mostly incomplete updates due to wrong permissions).

Regarding artifact naming I usually would recommend to stay close to the runtime IDs but to avoid confusion I would go with macOS/AMD64/ARM32.

Definitely tar.gz in favor of zip (to have control over file permissions).

I don't have access to macOS/aarch64 devices either.

Now that macOS beta https://github.com/Jackett/Jackett/issues/4948 has been released this issue has run its course

Future plans are:

  • Encourage users to migrate to the .NET Core version of Jackett where able
  • Investigate options once .NET Core 3 is released. Potentially Windows will be able to be converted then and potentially a FreeBSD version of Jackett
  • At some future time (not any time soon), deprecate the Mono version. With Jellyfin and Ombi already .NET Core only and Sonarr and Radarr have .NET Core on their roadmap, acceptance should be easier
Was this page helpful?
4.7 / 5 - 3 ratings