scalatra/scalatra — pull request #327 by jgrowl (2013-10-17 18:24:54+00:00)
Title: Distributed redis broadcaster client filters

These changes make client filtering a little more sane when using the redis atmosphere plugin. The main idea is that it does not make sense to try to filter clients before dropping the message onto redis. Instead we need to do filtering after the message is picked up from redis.

In order to do this though, we need to have context of who send the message. This is why I created new classes out of the different filters and included a uuid member. Now when broadcasting, the message will get wrapped in an object and serialized before getting put into redis.

To clean things up a bit, I moved the code dealing with ClientFilters out of the AtmosphereClient and put them into a new AtmosphereClientFilters trait.

To demonstrate what these changes do, you can use redis-cli and PSUBSCRIBE to see what is going on:

```
$ redis-cli
redis 127.0.0.1:6379> PSUBSCRIBE *
```

When a message is broadcasted, this is an example of what will get dropped onto redis:
```
1) "pmessage"
2) "*"
3) "/signal/*"
4) "{\"msg\":\"{\\\"type\\\":\\\"answer\\\",\\\"data\\\":\\\"{\\\\\\\"type\\\\\\\":\\\\\\\"answer\\\\\\\",\\\\\\\"sdp\\\\\\\":\\\\\\\"v=0\\\\\\\\r\\\\\\\\no=- 924777116337037287 2 IN IP4 127.0.0.1\\\\\\\\r\\\\\\\\ns=-\\\\\\\\r\\\\\\\\nt=0 0\\\\\\\\r\\\\\\\\na=group:BUNDLE audio video\\\\\\\\r\\\\\\\\na=msid-semantic: WMS\\\\\\\\r\\\\\\\\nm=audio 1 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126\\\\\\\\r\\\\\\\\nc=IN IP4 0.0.0.0\\\\\\\\r\\\\\\\\na=rtcp:1 IN IP4 0.0.0.0\\\\\\\\r\\\\\\\\na=ice-ufrag:ughkaJ0q4jwqxnia\\\\\\\\r\\\\\\\\na=ice-pwd:supersecreticepassword\\\\\\\\r\\\\\\\\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\\\\\\\\r\\\\\\\\na=sendonly\\\\\\\\r\\\\\\\\na=mid:audio\\\\\\\\r\\\\\\\\na=rtcp-mux\\\\\\\\r\\\\\\\\na=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:3hSogaOKksz4nIqPGPcjeEghKLQr80Gw50fZrtHy\\\\\\\\r\\\\\\\\na=rtpmap:111 opus/48000/2\\\\\\\\r\\\\\\\\na=fmtp:111 minptime=10\\\\\\\\r\\\\\\\\na=rtpmap:103 ISAC/16000\\\\\\\\r\\\\\\\\na=rtpmap:104 ISAC/32000\\\\\\\\r\\\\\\\\na=rtpmap:0 PCMU/8000\\\\\\\\r\\\\\\\\na=rtpmap:8 PCMA/8000\\\\\\\\r\\\\\\\\na=rtpmap:107 CN/48000\\\\\\\\r\\\\\\\\na=rtpmap:106 CN/32000\\\\\\\\r\\\\\\\\na=rtpmap:105 CN/16000\\\\\\\\r\\\\\\\\na=rtpmap:13 CN/8000\\\\\\\\r\\\\\\\\na=rtpmap:126 telephone-event/8000\\\\\\\\r\\\\\\\\na=maxptime:60\\\\\\\\r\\\\\\\\nm=video 1 RTP/SAVPF 100 116 117\\\\\\\\r\\\\\\\\nc=IN IP4 0.0.0.0\\\\\\\\r\\\\\\\\na=rtcp:1 IN IP4 0.0.0.0\\\\\\\\r\\\\\\\\na=ice-ufrag:ughkaJ0q4jwqxnia\\\\\\\\r\\\\\\\\na=ice-pwd:supersecreticepassword\\\\\\\\r\\\\\\\\na=extmap:2 urn:ietf:params:rtp-hdrext:toffset\\\\\\\\r\\\\\\\\na=sendonly\\\\\\\\r\\\\\\\\na=mid:video\\\\\\\\r\\\\\\\\na=rtcp-mux\\\\\\\\r\\\\\\\\na=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:3hSogaOKksz4nIqPGPcjeEghKLQr80Gw50fZrtHy\\\\\\\\r\\\\\\\\na=rtpmap:100 VP8/90000\\\\\\\\r\\\\\\\\na=rtcp-fb:100 ccm fir\\\\\\\\r\\\\\\\\na=rtcp-fb:100 nack \\\\\\\\r\\\\\\\\na=rtcp-fb:100 goog-remb \\\\\\\\r\\\\\\\\na=rtpmap:116 red/90000\\\\\\\\r\\\\\\\\na=rtpmap:117 ulpfec/90000\\\\\\\\r\\\\\\\\n\\\\\\\"}\\\"}\",\"clientFilter\":{\"jsonClass\":\"package$OnlySelf\",\"uuid\":\"d5e9956b-7026-4224-99e1-8e74e4e7e164\"}}"
```
The section: `{\"jsonClass\":\"package$OnlySelf\",\"uuid\":\"d5e9956b-7026-4224-99e1-8e74e4e7e164\"}` is the serialized ClientFilter. From this section we can determine that the resource `d5e9956b-7026-4224-99e1-8e74e4e7e164` is sending a message to `OnlySelf`.

Please note that the example message itself has an embedded serialized message so there is a lot of escaping going on.