Paket internals - Framework Restrictions

Intro

Warning: This is a quite technically detailed article (besides some introduction). If you search for a paket intro there is a perfect up to date blog-series by Isaac:

There was a time I remember perfectly well when I thought that NuGet works perfectly fine. Additionally, I was already heavily contributing to FSharp.Formatting and from time to time to FAKE, so how could I use just another tool which might need some attention?

Paket Contributions FSharp.Formatting Contributions

Why would you contribute to a project when you still use the alternative? Well, time has changed - after wasting enough time with NuGet updates and other shortcomings I’m now a happy Paket user and contributor for quite some time now.

Why not “new” NuGet?

Personally, some things need to change before I even consider using NuGet again:

  • git diff needs to show which versions (including transitive packages) changed: This is a very good feature of Paket and helped several times to debug and find complicated version conflicts.
  • restore needs to restore exact version OR fail, nothing in between: How can you debug complicated conflicts when the versions you get are random?
  • update needs to update my transitive packages as far as they are allowed by the corresponding version constraints: Otherwise I always need to specify all transitives myself to get bugfixes - in no way better than packages.config

As you can see there is no point in going back - even after they redesigned their whole system.

Paket internals

Now let’s see how it works!

Warning2: Some internals are very hard to understand or to get right. So this post doesn’t demand correctness or completness.

Update

Update is the process of resolving your paket.dependencies file to an paket.lock file in a fully automated manner. This process happens in several steps:

  • Parse the paket.dependencies file
  • Find a solution for the dependencies riddle
  • Write paket.lock
  • Download and extract the packages
  • Analyse the package contents and figure out “relevant” files
  • Edit project files according to paket.references (internally called “Install”)
  • Show the final Report

Some of this stuff is pretty “primitive” and I will not look into it a lot (parsing, writing and extracting for example) other things like finding the solution have become so complex that I only understand parts of it.

Datastructures and Resolving (overview)

Framework restrictions

Because it helps understanding the resolver and makes explaining it a lot easier we start with a quite (if not the most) important concept in Paket: A framework restriction.

Let’s first go briefly to the terminology (from Paket’s view):

  • framework identifier: Basically everything besides portables
  • target profile or profile or platform: Either a framework identifier to represent a single platform or a list of identifiers to represent a portable profile.
  • framework (without identifier) often used as synonym for profile
  • tfm (target framework moniker) a string identifier specified by NuGet for a particular platform. Basically, “target profile” = “tfm”

It is a bit problematic that we (the paket developers) don’t always use exactly defined terms due to historical reasons - often you get the exact meaning only by context.

Now, you need to understand that the NuGet ecosystem provides packages for a lot of existing platforms. Those platforms are documented here. Therefore I simplified the FrameworkIdentifier type definition from the real one:

Generally I will simplify type definitions to make the point more clear. Often we store additional data in such datastructures for performance or UX reasons (for example to provide better warnings/errors at certain places).

type FrameworkIdentifier =
    | Net45
    | Net46
    //| ... lots of others

type TargetProfile =
    | SinglePlatform of FrameworkIdentifier
    | PortableProfile of FrameworkIdentifier list


type FrameworkRestrictionP =
    private
    | ExactlyP of TargetProfile
    | AtLeastP of TargetProfile
    // Means: Take all frameworks NOT given by the restriction
    | NotP of FrameworkRestrictionP
    | OrP of FrameworkRestrictionP list
    | AndP of FrameworkRestrictionP list
type FrameworkRestrictionLiteralI =
    | ExactlyL of TargetProfile
    | AtLeastL of TargetProfile
type FrameworkRestrictionLiteral =
    { LiteraL : FrameworkRestrictionLiteralI; IsNegated : bool }
type FrameworkRestrictionAndList =
    { Literals : FrameworkRestrictionLiteral list }
type FrameworkRestriction =
    private { OrFormulas : FrameworkRestrictionAndList list }
type FrameworkRestrictions =
    | ExplicitRestriction of FrameworkRestriction
    | AutoDetectFramework

So in simple words a framework restriction is a general formula which describes a set of TargetProfile in DNF. We decided to use DNF because in our domain they tend to be shorter and keeping them in DNF throughout the applications allows us to simplify formulas along the way with simple algorithms. Example of such formulas are >= net45 or OR (>= net45) (<netcoreapp1.0).

As briefly described above, each formula represents a set of profiles and this set is defined like this:

    member x.RepresentedFrameworks =
        match x with
        | FrameworkRestrictionP.ExactlyP r -> [ r ] |> Set.ofList
        | FrameworkRestrictionP.AtLeastP r -> r.PlatformsSupporting
        | FrameworkRestrictionP.NotP(fr) ->
            let notTaken = fr.RepresentedFrameworks
            Set.difference KnownTargetProfiles.AllProfiles notTaken
        | FrameworkRestrictionP.OrP (frl) ->
            frl
            |> Seq.map (fun fr -> fr.RepresentedFrameworks)
            |> Set.unionMany
        | FrameworkRestrictionP.AndP (frl) ->
            match frl with
            | h :: _ ->
                frl
                |> Seq.map (fun fr -> fr.RepresentedFrameworks)
                |> Set.intersectMany
            | [] -> 
                KnownTargetProfiles.AllProfiles

Basically “AtLeast” (>=) means “all profiles which are supporting the current profile”. “Supporting” in that sense means that if I have two profiles X and Y and create a new project targeting Y and I can reference packages with binaries build against X we say Y supports X. For example net46 supports net45 therefore net46 is part of the set >= net45. Some further examples:

  • net47 is in >= netstandard10
  • netcoreapp10 is in >= netstandard16
  • net45 is in < netstandard12 which is equivalent to NOT (>= netstandard12), because net45 is NOT in >= netstandard12
  • net45 is NOT in < netstandard13

It is confusing, even for me, who wrote this stuff. The important thing here is to get away from the thinking of “smaller” and “higher” because it has no real meaning. On the other hand “supports” has a well defined meaning. Also don’t try to give < tfm any meaning besides a particular set of frameworks. This makes reasoning a lot simpler (just see it as an intermediate value used for simplifications and calculations). Technically, you could see it as “all platforms not supporting a particular tfm”.

So, now we know that a framework restriction is a formula which represents a particular list of frameworks (which we can now calculate given the NuGet documentation from above). But why do we need them?

The answer is the resolver phase. Let’s compare with plain NuGet: In NuGet you have a project targeting a single platform. NuGet now goes hunting for compatible packages for this particular platform. So at resolution time it knows which dependencies to take and what files it needs to install from a package. You might say: But what about new NuGet? The answer is the principle is not different at all. In the new world they resolve for each platform separatly exactly as described. This - in addition to how they resolve package versions - makes the resolution phase dead simple.

Paket on the other hand has a different world view. We assume the following to be true:

  • Packages properly define their dependencies (Note: NuGet explicitely assumes the reverse)
  • You want to reach a unified view of your dependencies-tree. This means you accept different packages for different platforms but you only accept a single version of a package supporting all your target profiles.

This means we tell our resolver our acceptable range of dependencies and the list of frameworks (see what I did there?) we want to build for. Obviously in practice we use framework restrictions for this:


type PackageName = string
type SemVerInfo = string
type VersionRangeBound =
    | Excluding
    | Including
type VersionRange =
    | Minimum of SemVerInfo
    | GreaterThan of SemVerInfo
    | Maximum of SemVerInfo
    | LessThan of SemVerInfo
    | Specific of SemVerInfo
    | OverrideAll of SemVerInfo
    | Range of fromB : VersionRangeBound * from : SemVerInfo * _to : SemVerInfo * _toB : VersionRangeBound
type VersionRequirement = VersionRange

type InstallSettings = 
    { FrameworkRestrictions: FrameworkRestrictions }

type PackageRequirementSource =
| DependenciesFile of string
| Package of PackageName * SemVerInfo * PackageSource

type PackageRequirement =
    { Name : PackageName
      VersionRequirement : VersionRequirement
      Parent: PackageRequirementSource
      Graph: PackageRequirement Set
      Sources: PackageSource list
      Settings: InstallSettings }

type DependencySet = Set<PackageName * VersionRequirement * FrameworkRestrictions>

type ResolvedPackage = {
    Name                : PackageName
    Version             : SemVerInfo
    Dependencies        : DependencySet
    Unlisted            : bool
    IsRuntimeDependency : bool
    IsCliTool           : bool
    Settings            : InstallSettings
    Source              : PackageSource
} 

val Resolve : Set<PackageRequirement> -> Map<PackageName, ResolvedPackage>

As you can see we input a set of PackageRequirement where every requirement contains framework restrictions in its settings.

But what do we get? The answer is that we not only need to know the version and the name of a particular package but also on which list of frameworks we are having this dependency. Again this is part of the settings of the result.

Need an example? Consider package A:

  • For tfm-b it depends on B in version 1.0
  • For tfm-c it depends on C in version 1.0

These conditions are called “dependency groups”. Here we have two dependency groups, one for tfm-b and one for tfm-c

Now if we put into the resolver that we want to depend on A and build for all frameworks (= have no framework restrictions, note in this simplified scenario I could say we use the list OR (= tfm-b) (= tfm-c) - see framework restrictions are lists ;)). What do we want as result?

Well, we want Paket to tell us that B needs to be installed but only for the list of frameworks >= tfm-b and C for the list of frameworks >= tfm-c! Can you spot the error?

The error is that the answer is wrong and the correct one depends on how tfm-b and tfm-c relate to each other!

For example consider tfm-b supports tfm-c which means tfm-b is in >= tfm-c. Then the correct answer is that we need to install B for >= tfm-b and C for AND (>= tfm-c) (< tfm-b). (Think of tfm-b = net45 and tfm-c = net40). The reason for this is that we should always decide for a single “dependency group”.

Another interesting case is when they don’t directly relate to each other (ie none is supported by the other) but AND (>= tfm-c) (>= tfm-b) is not the empty set. For example consider tfm-c = netstandard10 and tfm-b = net35. Now the correct answer is kind of difficult. Because for the set AND (>= tfm-c) (>= tfm-b) there is no good answer. What paket does is it reuses it’s internal cost function to figure out if a random member of the AND set matches better to tfm-c or tfm-b and then assigns the remaining items to the result. Lets assume the missing list matches “better” to tfm-c then we get:

  • Install C when OR (>= tfm-c) (AND (>= tfm-c) (>= tfm-b)) which will be simplified to >= tfm-c
  • Install B when AND (>= tfm-b) (< tfm-c).

The above logic is encoded in this 51 line function which probably needs a bit time to read (it took quite a bit time to write “correctly”, so that’s probably fair).

Just when writing this blog post I noticed that there is a bug in the above logic. Please send a PR if you can figure out what the problem is ;)

Ok this is enough for now, more internals might follow…

Please ping me on twitter to tell me what you want to know next. Or open an issue on Paket :)

Having Fun with Computation Expressions

Or how I build a generic computation builder library.

Over the last days I build a F# API for google music by using gmusicapi and pythonnet (two awesome projects by the way). The Python C-API requires you to request the GIL (Global Interpreter Lock) before you can safely use the API. Because I knew I would forget to do this all over the place I decided to mark those places explicitly with the help of computation expressions. Doing this on a low level means I can safely use it on higher levels.

I decided to build the computation expression like this:

type PythonData<'a> =
  private { 
    Delayed : (unit -> 'a)
    mutable Cache : 'a option
  }
let pythonFunc f = { Delayed = f; Cache = None }
let internal unsafeExecute (f:PythonData<_>) =
  match f.Cache with
  | Some d -> d
  | None ->
    let res = f.Delayed()
    f.Cache <- Some res
    res
let private getPythonData = unsafeExecute
let runInPython f = 
  use __ = Python.Runtime.Py.GIL()
  f |> getPythonData

The builder is straightforward from there (see link above).

Of course now we need to interact with sequences and er need something like FSharp.Control.AsyncSeq. Basically all I had to do was copy the code from there and replace the builder.

Wait… What? We will look into this later.

Now I got really curious, I really only want to replace the ‘runInPython’ function and there is nothing specific about my python problem in the builders. Can we be more generic here? Just adding more run functions is not really practical as then users can just use the wrong one…

Let the fun begin… Lets first start with a general purpose delayed builder and lets see what we can do from there:


type Delayed<'a> =
  private { 
    Delayed : (unit -> 'a)
    mutable Cache : 'a option
  } 
  
module Delayed =
  let create f = { Delayed = f; Cache = None }
  let execute (f:Delayed<_>) =
    match f.Cache with
    | Some d -> d
    | None ->
      let res = f.Delayed()
      f.Cache <- Some res
      res
      
  let map f d =
    (fun () -> f (d |> execute)) |> create

type ConcreteDelayedBuilder() =
	let create f = Delayed.create f
	let execute e = Delayed.execute e
	member x.Bind(d, f) =
		(fun () -> 
			let r = d |> execute
			f r |> execute
			) |> create

	member x.Return(d) = 
		(fun () -> d) |> create
	member x.ReturnFrom (d) = d
	member x.Delay (f) = 
		(fun () -> f() |> execute) |> create
	member x.Combine (v, next) = x.Bind(v, fun () -> next)
	member x.Run (f) = f
	member x.Zero () = (fun () -> ()) |> create
	member x.TryWith (d, recover) =
		(fun () -> 
		try
			d |> execute
		with e -> recover e |> execute) |> create
	member x.TryFinally (d, final) =
		(fun () -> 
		try
			d |> execute
		finally final ()) |> create
	member x.While (condF, body) =
		(fun () -> 
		while condF() do
			body |> execute) |> create
	member x.Using (var, block) =
		(fun () -> 
		use v = var
		block v |> execute) |> create
	member x.For (seq, action) = 
		(fun () -> 
		for item in seq do
			action item |> execute) |> create

let delayed = ConcreteDelayedBuilder()

Ok looks good: We have a simple delayed builder. What we want now is some kind of converter to convert this Delayed<'T>' in a PythonData<’T>`

I would design the type like this:

  type PythonData<'T> = private { D : Delayed<'T> }
  let runInPython f = 
    use __ = Python.Runtime.Py.GIL()
    f.D |> Delayed.execute

Therefore callers cannot use the underlying Delayed object. But how do we generically get a computation builder and how would the result look like?

We would like to build a generic (computation expression builder) type with some kind of converter parameter which itself calls the regular delayed builder.

type IDelayedConverter<'b> =
	member ToDelayed : 'b<'a> -> Delayed<'a>
	member OfDelayed : Delayed<'a> -> 'b<'a>

Something like this is what we want, but sadly this is not possible (see uservoice). Can we work around this limitation? I decided to use a interface with marker classes for this. If you have a better idea let me know!

type IDelayed<'b, 'a> = interface end
type DefaultMarker = class end 
type Delayed<'a> =
  private { 
    Delayed : (unit -> 'a)
    mutable Cache : 'a option
  } with
  interface IDelayed<DefaultMarker, 'a>

/// Ideally we want 'b to be a type constructor and return 'b<'a>...
type IDelayedConverter<'b> =
  abstract ToDelayed : IDelayed<'b, 'a> -> Delayed<'a>
  abstract OfDelayed : Delayed<'a> -> IDelayed<'b, 'a>

Now we can change our computation builder to take an instance of a converter:

type ConcreteDelayedBuilder<'b>(conv : IDelayedConverter<'b>) =
    let execute a = a |> conv.ToDelayed |> Delayed.execute
    let create f = f |> Delayed.create |> conv.OfDelayed

	// .. Continue with the old code.

Which leads to our default instance like this:

  // Add to the Delayed module...
  let conv =
    { new IDelayedConverter<DefaultMarker> with
       member x.ToDelayed p = (p :?> Delayed<'a>)
       member x.OfDelayed d = d :> IDelayed<DefaultMarker, _> }


[<AutoOpen>]
module DelayedExtensions =
  
  let delayed = ConcreteDelayedBuilder(Delayed.conv)

Nice! Now we can create the python builder like this:

module Python =
  type PythonDataMarker = class end 
  type PythonData<'T> = private { D : Delayed<'T> } with
    interface IDelayed<PythonDataMarker, 'T>
  let internal pythonConv =
    { new IDelayedConverter<PythonDataMarker> with
       member x.ToDelayed p = (p :?> PythonData<'a>).D
       member x.OfDelayed d = { D = d } :> IDelayed<PythonDataMarker, _> }
  let runInPython f = 
    use __ = Python.Runtime.Py.GIL()
    pythonConv.ToDelayed f |> Delayed.execute
  
  let python = ConcreteDelayedBuilder(pythonConv)

A bit of setup but wow we almost made it. What we now want is the pythonSeq or delayedSeq computation builder. When we think about it we want a generic builder which takes the regular builder as parameter.

Oh that sounds like it will create a bunch of problems, but lets start to convert the AsyncSeq code. In theory all we need to do now is copy the AsyncSeq code and replace

  • AsyncSeq<'T> -> DelayedSeq<'b, 'T>
  • IAsyncEnumerator<'T> -> IDelayedEnumerator<'b, 'T>
  • Potentially add some type paramters to the helper classes.
  • replace the async builder with our parameter builder
  • Async<'T> -> IDelayed<'b, 'T>

First problem: We cannot use modules to define our functionality because we actually have a parameter (the underlying builder).

So lets start with the interfaces

type IDelayedEnumerator<'b, 'T> =
  abstract MoveNext : unit -> IDelayed<'b, 'T option>
  inherit System.IDisposable

type IDelayedEnumerable<'b, 'T> =
  abstract GetEnumerator : unit -> IDelayedEnumerator<'b, 'T>

type DelayedSeq<'b, 'T> = IDelayedEnumerable<'b, 'T>

This will do.

Lets start with empty (from here):

type DelayedSeqBuilder<'b>(builder : ConcreteDelayedBuilder<'b>) =
  //[<GeneralizableValue>]
  member x.empty<'T> () : DelayedSeq<'b, 'T> = 
        { new IDelayedEnumerable<'b, 'T> with 
              member x.GetEnumerator() = 
                  { new IDelayedEnumerator<'b, 'T> with 
                        member x.MoveNext() = builder { return None }
                        member x.Dispose() = () } }
 

Ok, it actually compiles. This is a good step forward. There we go: A computation builder as a parameter. The next special thing happens when they define helper types within their module. We cannot do this in a type. Therefore we will just move all the helpers above the DelayedSeqBuilder<'b> type and mark them as internal (see here).

Why did I name this type DelayedSeqBuilder<'b> and not like the corresponsing module? Because we cannot define the computation builder inside. Instead we will define all the functions here as members. This will later make the following possible:

  let seq =
    pythonSeq {
      for i in [1, 2, 3] do
        // Call Python API
        let! t = tf
        yield t + "test"
    }

  let first =
    seq
    |> pythonSeq.firstOrDefault "default"

But we are not there yet. So instead of defining the AsyncSeqBuilder inside the module we will just define everything in the builder itself. We are now here in AsyncSeq, or here with the port.

Now they do something which is not good for us. They define asyncSeq inside the module to define the higher level functionality as extension methods later. One example is the emitEnumerator function. We cannot create an instance, because we don’t know the paramter. But wait we already have an this (x) reference to ourself. What if we use that?

  member x.emitEnumerator (ie: IDelayedEnumerator<'b, 'T>) = x {
      let! moven = ie.MoveNext() 
      let b = ref moven 
      while b.Value.IsSome do
          yield b.Value.Value 
          let! moven = ie.MoveNext() 
          b := moven }

And again it compiles! This is crasy. With this (!) we can easily port the rest of the functionality.

Now we just need to extend the regular builder with the async for. But this is straightforward as well:

[<AutoOpen>]
module DelayedSeqExtensions =
  // Add asynchronous for loop to the 'async' computation builder
  type ConcreteDelayedBuilder<'b> with
    member internal x.For (seq:DelayedSeq<'b, 'T>, action:'T -> IDelayed<'b, unit>) =
      let seqBuilder = DelayedSeqBuilder(x)
      seq |> seqBuilder.iterDelayedData action 

We can define the final functionality by using both builders. But wait there is one more problem. When we define extension methods for the DelayedSeqBuilder<'b> type we cannot access the underlying builder parameter anymore. So lets add a property to access it:

type DelayedSeqBuilder<'b>(builder : ConcreteDelayedBuilder<'b>) =
  // ... 
  member x.Builder = builder
// ...
[<AutoOpen>]
module DelayedSeqExtensions =
  // ...
  type DelayedSeqBuilder<'b> with
    member x.tryLast (source : DelayedSeq<'b, 'T>) = x.Builder { 
        use ie = source.GetEnumerator() 
        let! v = ie.MoveNext()
        let b = ref v
        let res = ref None
        while b.Value.IsSome do
            res := b.Value
            let! moven = ie.MoveNext()
            b := moven
        return res.Value }

And we can finaly create the computation builder instances:

  let delayedSeq = new DelayedSeqBuilder<_>(delayed)

And for our python use case:

  let python = ConcreteDelayedBuilder(pythonConv)
  let pythonSeq = DelayedSeqBuilder(python)

What have we done here:

  • We created a library to create your own computation builders with minimal amount of code (by providing an interface implementation)
  • We worked around F# not supporting high order generics
  • We used a computation builder as parameter
  • We used the this reference as computation builder
  • We used a property as computation builder

It’s really sad that we cannot define the DelayedSeqBuilder more generically. I’m pretty sure that would be usable for some exting computation builders as well. Maybe there is something we can do with type providers here ;).

This is all for now :). You can use this in your code via nuget. Of course the code is on github.

Stream Amazon Prime to UPNP Devices via WLAN

Ok this is weird: I simply want to stream an Amazon Prime movie to our receiver supporting UPNP to be able to watch the film on the big TV screen and ideally use the notebook at the same time. Why is this so incredibly hard to realize and you need several software projects to realize it?

First I tried to use plugins for already existing software within our network. Namely:

  • Amazon Prime Plugin for Plex, which doesn’t exist apparently
  • The people from the plex thread talk about a plugin for XBMC/Kodi. The plugin wouldn’t even install on the device I wanted (older debian installation). But out of curiousity I tried with the latest version on Windows, installed the plugin and tadaaah it didn’t work Issue1 and Issue2. So the plugin is no longer usable…
  • Because we have an older linux device in place (exactly for watching stuff) I tried to just login and play the videos there, however firefox and chromium apparently get no love from amazon. I even installed the latest chrome, but amazon would tell me something about missing plugins :( (Note that this wasn’t my prefered solution anyway…)

Obviously it isn’t as simple as I thought initially. So how about a more generic solution. What if I just stream the whole desktop to the device?

If you start googleing about this it really looked like VLC is the way to go. I tried. I really tried. But whenever I tried to forward the desktop to a stream (http://, udp or whatever) VLC crashed. So while in theory VLC does exactly what we need it doesn’t work (at least it didn’t for me).

Now several hours later I’m still not ready to give up. How can such a simple thing not work? You know what? Gaming has been really successfull in streaming things via twitch.tv, so I guess I should look there for mature software and see how far I can get…

First I installed OBS the first software recommended by Twitch.tv and actually open source (so I thought it might be open enough to do other things than stream for twitch.tv). So now OBS is designed to stream to a streaming server and not to UPNP device so I need my own streaming server. After some more help from google it was clear that OBS itself provides the required documentation to do it. The only problem is that I’m using windows and had no intention of compiling anything, therefore I used a precompiled nginx version with rtmp support.

For recording I used the following trick:

  • Before starting chrome change the default audio device to a virtual one (or one that isn’t connected/unused): Screenshot Setup before starting chrome
  • Now I can add the device to OBS (and hear it later correctly synced on the UPNP device via stream)
  • Start chrome
  • Add the chrome windows to OBS as you like: Screenshot Setup after starting chrome

For nginx I basically used the exact configuration from the documentation above:

C:\Users\dragon\Downloads\nginx-rtmp-win32-master\conf:

worker_processes  1;

error_log  logs/error.log debug;

events {
    worker_connections  1024;
}

rtmp {
    server {
        listen 8089;
        #chunk_size 256;

        #wait_key on;
        #wait_video on;
		
        application live {
            live on;
            record off;

            #wait_key on;
            #interleave on;
            #publish_notify on;
            #sync 10ms;
            #wait_video on;
            #allow publish 127.0.0.1;
            #deny publish all;
            #allow play all;
        }
		
		#application hls {
		#	live on;
		#	hls on;  
		#	hls_path temp/hls;  
		#	hls_fragment 8s;  
		#}
    }
}

http {
    server {
        listen      8088;
		
        location / {
            root www;
        }
		
        location /stat {
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }

        location /stat.xsl {
            root www;
        }
		
		location /hls {  
           #server hls fragments  
			types{  
				application/vnd.apple.mpegurl m3u8;  
				video/mp2t ts;  
			}  
			alias temp/hls;  
			expires -1;  
        }  

    }
}

I like that the pre compiled nginx already has setup a page where I can directly what the stream if I want to.

After starting nginx in a console window (or by double clicking nginx.exe) your streaming server should be ready and you can finalize the OBS setup and start the stream:

  • First make sure you setup the “Stream” settings exactly the way you setup the nginx configuration. Note that the Stream key doesn’t matter (here I use “test”) but is used again later: Screenshot Setup 'Stream'

  • Then setup the output in a way suited to you (I only use an higher bitrate for better quality): Screenshot Setup 'Output'

  • Then setup the video in a way suited to your TV (change to the optimal resolution for your TV): Screenshot Setup 'Video'

Now the stream can be started successfully and we can even watch it via http://localhost:8088 by entering rtmp://127.0.0.1:8089/live/test in the box.

We are almost there, because we only need to bridge the gap between the rtmp stream and the UPNP device. Luckily serviio can close the gap:

Screenshot Setup 'Serviio'

Further information for this setup

  • There is definitely a high delay (several seconds) depending on your configuration as this is not meant to be ‘live’.

  • Note that you can even lock your laptop, the stream will continue to work!

  • You can however not ‘minimize’ chrome (move it to the edge of the screen)

  • This method is not limited to Amazon Prime at all, stream whatever you like!

  • If you don’t mind the delay you can use the UPNP device as second monitor:

    • First setup a fake display like this, that or use a HDMI-to-VGA adapter This will make windows think that a second monitor is attached.
    • Now you can setup OBS to stream this second monitor instead of the chrome window.

News replaced with blog

Just a short information that now the ‘news’ section has been replaced with a blog here on yaaf.de. At the end of this post I show all the code needed to include a basic markdown based blog to your website via FSharp.Formatting!

Some more features will be added soon:

  • Ability to comment blog posts.
  • Ability to filter posts by year and tag.

The blog was build with the lovely FSharp.Formatting library (the first time I actually used it as a regular library!). It’s a very simple in-memory implementation (which is fine for the low number of posts) and all posts are markup files in a folder which are processed to html by FSharp.Formatting. I added some trickery to allow embedding of title, author, date and tags into the template file (basically I read the first headline and remove it from the parsed markup file).

A blog entry file looks like this:

# Date: 2015-12-17; Title: News replaced with blog; Tags: blog,yaaf; Author: Matthias Dittrich

Just a short information that now the 'news' section has been replaced with a blog here on yaaf.de.
At the end of this post I show all the code needed to include a basic markdown based blog to your website via `FSharp.Formatting`!

Some more features will be added soon:

 - Ability to comment blog posts.
 - Ability to filter posts by year and tag.

... continue with markup ....

Of course while adding the blog I found a bug and fixed it… And because I was already at the FSF code I tried to help ademar with a PR which I want to merge a long time now: https://github.com/tpetricek/FSharp.Formatting/pull/331 (see related PR)

Edit 2015-12-18:

Of course I had to update some css scripts such that blog post links are properly wrapped and the embedded code is as well.

The following css does the trick for links:

#content .inbox a {
    /* Prevent Links from breaking the Layout (blogposts!) */
    display: inline-block;
    word-break: break-all;
}

The problem was that long automatically converted links would not wrap properly, so this tells the browser that I want to break links on every character.

Then I had to handle the regular pre tag (because I modified the FSF generation to be comaptible with prismjs):

#content .inbox {
	/* basically the same as margin above, but helps with pre tags */
	max-width: calc(100% - 50px);
}

It’s strange that the pre-tag seems to ignore the regular wrapping rule and must be forced to show the scroll-bar by setting the max-width property of the parent element. I could see in the browser that the setup was correct as it was floating ok up to the point where it had to show the scroll-bars (and hide/wrap text).

The third problem had to do with the tables FSF is generating for F# scripts (for F# I still use the FSF defaults):

/* Fix that F# code scrolls properly with the page (50px = 2 * Margin of the inbox) */
table.pre {
    table-layout: fixed;
    width: calc(100% - 50px);
}

table.pre pre {
  /* Show scrollbar when size is too small */
  overflow: auto;
}

table.pre td.lines {
  /* Align on top such that line numbers are at the correct place when the scrollbar is shown */
  vertical-align: top;
}

It seems to be the regular behavior that tables do not wrap out of the box, see this.

And finally here is the box with some F# code to test the css changes (Note: this is all the code I used to process the markdown files to html via FSF):

/// Simple in-memory database for my (quite limited number of) blogpost.
namespace Yaaf.Website.Blog
open System
/// Html content of a post
type Html = RawHtml of string
/// The title of a post
type Title = Title of string
/// The stripped title of a post
type StrippedTitle = StrippedTitle of string

type Post =
  { Date : DateTime
    Title : Title
    Content : Html
    Teaser : Html
    TipsHtml : Html
    Tags : string list
    Author: string }

open System.Collections.Generic
type PostDb = IDictionary<DateTime * StrippedTitle, Post>

module BlogDatabase =
  open System.IO
  open System.Web
  open FSharp.Markdown
  open FSharp.Literate
  

  let private formattingContext templateFile format generateAnchors replacements layoutRoots =
      { TemplateFile = templateFile 
        Replacements = defaultArg replacements []
        GenerateLineNumbers = true
        IncludeSource = false
        Prefix = "fs"
        OutputKind = defaultArg format OutputKind.Html
        GenerateHeaderAnchors = defaultArg generateAnchors false
        LayoutRoots = defaultArg layoutRoots [] }

  let rec private replaceCodeBlocks ctx = function
      | Matching.LiterateParagraph(special) -> 
          match special with
          | LanguageTaggedCode(lang, code) -> 
              let inlined = 
                match ctx.OutputKind with
                | OutputKind.Html ->
                    let code = HttpUtility.HtmlEncode code
                    let codeHtmlKey = sprintf "language-%s" lang
                    sprintf "<pre class=\"line-numbers %s\"><code class=\"%s\">%s</code></pre>" codeHtmlKey codeHtmlKey code
                | OutputKind.Latex ->
                    sprintf "\\begin{lstlisting}\n%s\n\\end{lstlisting}" code
              Some(InlineBlock(inlined))
          | _ -> Some (EmbedParagraphs special)
      | Matching.ParagraphNested(pn, nested) ->
          let nested = List.map (List.choose (replaceCodeBlocks ctx)) nested
          Some(Matching.ParagraphNested(pn, nested))
      | par -> Some par
      
  let private editLiterateDocument ctx (doc:LiterateDocument) =
    doc.With(paragraphs = List.choose (replaceCodeBlocks ctx) doc.Paragraphs)

  let parseRawDate (rawDate:string) = DateTime.ParseExact(rawDate, "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture)

  let parseRawTitle (rawTitle:string) =
    // 2015-12-17: Testpost with some long title
    let splitString = " - "
    let firstColon = rawTitle.IndexOf(splitString)
    if firstColon < 0 then failwithf "invalid title (expected instance of ' - ' to split date from title): '%s'" rawTitle
    let rawDate = rawTitle.Substring(0, firstColon)
    let realTitle = rawTitle.Substring(firstColon + splitString.Length)
    Title (realTitle.Trim()), parseRawDate rawDate

  let parseHeaderLine (line:string) =
    let splitString = ": "
    let firstColon = line.IndexOf(splitString)
    if firstColon < 0 then failwithf "invalid header line (expected instance of ': ' to split header key from value): '%s'" line
    let rawKey = line.Substring(0, firstColon)
    let rawValue = line.Substring(firstColon + splitString.Length)
    rawKey, rawValue


  let extractHeading (doc:LiterateDocument) =
    let filtered, heading =
      doc.Paragraphs
      |> Seq.fold (fun (collected, oldHeading) item ->
        let takeItem, heading =
          match oldHeading, item with
          | None, (Heading(1, text)) ->
            let doc = MarkdownDocument([Span(text)], dict [])
            false, Some(Formatting.format doc false OutputKind.Html)
          | None, _ -> true, None
          | _ -> true, oldHeading
        (if takeItem then item :: collected else collected), heading) ([], None)
    heading, doc.With(paragraphs = List.rev filtered)

  let evalutator = lazy (Some <| (FsiEvaluator() :> IFsiEvaluator))
  let readPost filePath =
    // parse the post markup file
    let doc = Literate.ParseMarkdownFile (filePath, ?fsiEvaluator = evalutator.Value)
    
    // generate html code from the markdown
    let ctx = formattingContext None (Some OutputKind.Html) (Some true) None None
    let doc =
      doc
      |> editLiterateDocument ctx
      |> Transformations.replaceLiterateParagraphs ctx
    let heading, doc = extractHeading doc
    let content = Formatting.format doc.MarkdownDocument ctx.GenerateHeaderAnchors ctx.OutputKind
    let rec getTeaser (currentTeaser:string) (paragraphs:MarkdownParagraphs) =
      if currentTeaser.Length > 150 then currentTeaser
      else
        match paragraphs with
        | p :: t ->
          let convert = Formatting.format (doc.With(paragraphs = [p]).MarkdownDocument) ctx.GenerateHeaderAnchors ctx.OutputKind
          getTeaser (currentTeaser + convert) t
        | _ -> currentTeaser

    let title, date, tags, author =
      match heading with
      | Some header ->
        let headerValues =
          header.TrimEnd().Split([|"; "|], StringSplitOptions.RemoveEmptyEntries)
          |> Seq.map parseHeaderLine
          |> dict
        
        Title headerValues.["Title"], parseRawDate headerValues.["Date"],
        (match headerValues.TryGetValue "Tags" with
        | true, tags -> tags.Split([|","|], StringSplitOptions.RemoveEmptyEntries)
        | _ -> [||]),
        match headerValues.TryGetValue "Author" with
        | true, author -> author
        | _ -> "Unknown"
      | None ->
        let name = Path.GetFileNameWithoutExtension filePath
        let title, date = parseRawTitle name
        title, date, [||], "Unknown"

    let tipsHtml = doc.FormattedTips
    { Date = date; Title = title; Content = RawHtml content; TipsHtml = RawHtml tipsHtml; 
      Tags = tags |> List.ofArray; Author = author; Teaser = RawHtml (getTeaser "" doc.Paragraphs) }

  let toStrippedTitle (Title title) =
    StrippedTitle (title.Substring(0, Math.Min(title.Length, 50)))

  let readDatabase path : PostDb =
    // Blogposts are *.md files within the given path
    Directory.EnumerateFiles(path, "*.md")
    |> Seq.map (readPost >> (fun p -> (p.Date, toStrippedTitle p.Title), p))
    |> dict

Unlock Android despite forgotten Pattern or Password

The Problem

A family member forgot the pattern setup in its android device.

  • The “forgot password” button would not appear to enter the password
  • The android device manager was setup but would show “lock already set the password you entered is not required”

Now usually all hope is lost and you need to factory reset your device (and lose all data). This however was not an option in my case.

The Situation

The situation for my case can be summarized like this:

  • Android 5.1.1 (others might work)
  • A second user without or with known Pattern/Password.
  • Sony Xperia Z Ultra (C6833), Version 14.6.A.0.368 (others probably work)

    • NO Sony bootloader unlock (otherwise there is probably a simpler way)
    • NO root
    • FACTORY Stock
    • NO Previous Backup via the Companion App (Otherwise you can just extract the data you need from the backup file!)
    • NO USB Debugging enabled
    • NO Developer Unlock

Because of this situation none of the methods posted on XDA are usable here and the internet is suggesting a factory reset. However as I was willing to dissassemble the device nothing is lost if I first try to dig deeper and try to get into the phone via software!

After some hours of trying to find a zero day exploit (as the version was already outdated at the time of writing), I came up with a simpler solution. I knew that there are a lot of attack vectors as I still had access to the guest user…

The Solution

So here are the steps to unlock the phone:

  • Install http://kingroot.net/ as the second user. The good part is the second user can even enable untrusted sources in options! Root the phone by clicking the button on the app.
  • Install a terminal app, for example https://play.google.com/store/apps/details?id=jackpal.androidterm&hl=en (Open the link with the “Play Store” App on the phone and login with your google account)
  • Open the terminal and type “su” followed by ‘Enter’</li>
  • If you get a notification that an app tries to get root you can accept the message and now have a root shell (= full access to the phone)
  • Now you can easily remove your pattern or password (reference):

    • Pattern: Type “rm /data/system/gesture.key”
    • Password: Type “rm /data/system/password.key”
  • Now restart the phone and if asked for a pattern or password just enter anything ;)

I think this is basically a bug/security issue in the android operating system, because guest users should not be able to select ‘Allow untrusted sources’ in the device options. On the other side I think android device manger should allow us to reset the pattern/password… Of course now its simple the backup the data and factory reset the phone (if you don’t trust the installed tools). Note however that factory reset might not delete everything in this case (as the phone was rooted), the safe choice would be to install a new firmware file.