<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<id>http://iangilham.com/</id>
<title>Ian Gilham</title>
<link type="application/atom+xml" href="http://iangilham.com/feed/feed.atom" rel="self"/>
<link href="http://iangilham.com/" rel="alternate" />
<updated>2023-07-30T09:47:39+00:00</updated>
<rights>Copyright (c) 2023 Ian Gilham</rights>

<entry>
<title type="text">Fixing Swapped Tilde Key on MacOS</title>
<link href="http://iangilham.com/2021/08/20/macos-fixing-swapped-tilde-key.html" rel="alternate"/>
<updated>2021-08-20T00:00:00+00:00</updated>
<id>http://iangilham.com/2021/08/20/macos-fixing-swapped-tilde-key.html</id>



<content type="html">&lt;p&gt;For the last few years I’ve been using an early 2015 MacBook Pro for work and have sometimes suffered from RSI due in part to the terrible ergonomics of the Magic Keyboard. I solved this by buying a Mac-compatible mechanical keyboard from &lt;a href=&quot;https://en.varmilo.com/keyboardproscenium/&quot;&gt;Varmilo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Unfortunately, MacOS has never correctly detected the layout of this keyboard. It thinks it’s ANSI layout (no extra key left of ‘z’) but it’s actually ISO layout (backtick/tidle left of z). The Mac’s default behaviour is to swap the section mark and plus-minus (§, ±) keys with the backtick/tilde key. It’s usable but annoying. Until recently I solved this by remapping the offending keys using &lt;a href=&quot;https://karabiner-elements.pqrs.org/&quot;&gt;Karabiner Elements&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Fast-forward a few years and I’ve got a newer MacBook Pro, circa 2019. No matter how many times I go through the setup, Karabiner Elements always fails to install its driver on this machine. I needed a new solution. Forunately, there’s a CLI for changing user keymappings on MacOS, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hidutil&lt;/code&gt;. I found some scripts on the &lt;a href=&quot;https://apple.stackexchange.com/a/353941&quot;&gt;Apple Stack Exchange&lt;/a&gt; and rewrote them into a shell utility to make it easier to use.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Adapted from https://apple.stackexchange.com/a/353941 under CC BY 4.0&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;PLIST&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/Library/LaunchDaemons/org.custom.tilde-switch.plist&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in
&lt;/span&gt;on&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  hidutil property &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{&quot;UserKeyMapping&quot;:[
    {
      &quot;HIDKeyboardModifierMappingSrc&quot;: 0x700000035,
      &quot;HIDKeyboardModifierMappingDst&quot;: 0x700000064
    },
    {
      &quot;HIDKeyboardModifierMappingSrc&quot;: 0x700000064,
      &quot;HIDKeyboardModifierMappingDst&quot;: 0x700000035
    }
  ]}&apos;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
off&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  hidutil property &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{&quot;UserKeyMapping&quot;:[]}&apos;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;sh &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;cat &amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PLIST&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&amp;gt;
&amp;lt;plist version=&quot;1.0&quot;&amp;gt;
  &amp;lt;dict&amp;gt;
    &amp;lt;key&amp;gt;Label&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;org.custom.tilde-switch&amp;lt;/string&amp;gt;
    &amp;lt;key&amp;gt;Program&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HOME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;/bin/switch-tilde-keys&amp;lt;/string&amp;gt;
    &amp;lt;key&amp;gt;ProgramArguments&amp;lt;/key&amp;gt;
      &amp;lt;array&amp;gt;
        &amp;lt;string&amp;gt;on&amp;lt;/string&amp;gt;
      &amp;lt;/array&amp;gt;
    &amp;lt;key&amp;gt;RunAtLoad&amp;lt;/key&amp;gt;
    &amp;lt;true/&amp;gt;
    &amp;lt;key&amp;gt;KeepAlive&amp;lt;/key&amp;gt;
    &amp;lt;false/&amp;gt;
  &amp;lt;/dict&amp;gt;
&amp;lt;/plist&amp;gt;
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF
&lt;/span&gt;  &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;launchctl load &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PLIST&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
uninstall&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;launchctl unload &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PLIST&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PLIST&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Usage: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; on|off|install|uninstall&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
  &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;1
  &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;esac&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The way this swaps keymaps, it fixes my external keyboard but also makes the same change to the MacBook’s internal keyboard, making that one wrong. For that reason it’s convenient to have the commands to disable the change or uninstall the PList file in case I’m traveling or my hardware changes. Thanks to the Covid situation, I haven’t been in the office for a year and a half but that may eventually change.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Simplifying the Jekyll site</title>
<link href="http://iangilham.com/2021/08/04/simplifying-the-site.html" rel="alternate"/>
<updated>2021-08-04T00:00:00+00:00</updated>
<id>http://iangilham.com/2021/08/04/simplifying-the-site.html</id>



<content type="html">&lt;p&gt;It has been a while since I last wrote anything for this blog but I think about it occasionally. I was planning to get back into writing but the thought of &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll’s&lt;/a&gt; slow build process put me off.&lt;/p&gt;

&lt;p&gt;To address the static site build time, I got most of the way through a port to &lt;a href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt; before I realised that many of Jekyll’s performance problems had been solved in the last year or two. I was also concerned that I might struggle to get some of the features to work correctly, since I use an esoteric plugin to build tag index pages.&lt;/p&gt;

&lt;p&gt;Well, the tag problem is easily solved - I have removed the plugin and the pages from the site, simplifying the build and reducing the number of things that can slow it down or break the site. This also seemed like a good opportunity to simplify article and post headers and I ended up fiddling with the colours a bit while I was playing around.&lt;/p&gt;

&lt;p&gt;In the past, I’ve used Google Analytics on this site but I’ve never really paid any attention to the data it produces. Since the value of the data to me is almost zero, I removed it quite some time ago to keep things as simple as possible.&lt;/p&gt;

&lt;p&gt;As for the Hugo port, I haven’t decided if I want to commit to it at this stage, but at least it should be easier without the extra weirdness of the tag plugin. I’ll stick with Jekyll for now, since my reasons to migrate have largely been mitigated.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Azure Functions Experience</title>
<link href="http://iangilham.com/2020/02/12/azure-functions-experience.html" rel="alternate"/>
<updated>2020-02-12T00:00:00+00:00</updated>
<id>http://iangilham.com/2020/02/12/azure-functions-experience.html</id>



<content type="html">&lt;p&gt;I’ve recently been working with Azure Functions, Microsoft’s functions-as-a-service (FAAS) platform. I’m already quite familiar with AWS Lambda so my perspective is coloured by that experience.&lt;/p&gt;

&lt;p&gt;First, the good. Functions Apps are pretty flexible. You can host a single entry point per app if you want but it is often more cost-effective to host several functions within the same app and share some resources. I’m using Javascript so the whole app shares a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; and a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node_modules&lt;/code&gt; directory etc. The app also has its own Storage Account, which can host blobs (like S3), queues (like SQS) and tables (similar to DynamoDB but works differently) etc.. These resources are easy to use from any function within the app, making it easy to send a message down a queue to model event-driven workflows and perform multiple actions with the same files or database records.&lt;/p&gt;

&lt;p&gt;The runtime of a function app environment is versioned separately from the language and language version. There is a &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/azure-functions/set-runtime-version&quot;&gt;list of supported languages and versions for each version of the runtime&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A Function App is connected to an App Service Plan, which defines the virtual machine billing model. There are options for consumption plans on Windows and Linux or you can reserve an auto-scaling pool of virtual machines. It’s fairly flexible but quite awkward to configure for Linux. The key when using Terraform or ARM is to make sure the instance is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reserved&lt;/code&gt;, as that seems to mean “use Linux”.&lt;/p&gt;

&lt;p&gt;The inputs and outputs of functions can be bound to HTTP requests/responses or tied directly to other Azure event sources, such as blobs, queues, tables etc. This allows you to avoid writing the code to send a message, write a row to a table or any number of other common integrations. This gives Functions a lot more flexibility than AWS Lambda functions, which only lets you bind the input event source.&lt;/p&gt;

&lt;p&gt;The documentation for Linux apps is largely missing and often useless. You have to dig pretty deep to discover that the &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/azure-functions/functions-app-settings#website_node_default_version&quot;&gt;setting for configuring the version of NodeJS&lt;/a&gt; you want only works on Windows instances. There is a &lt;a href=&quot;https://github.com/Azure/azure-functions-host/issues/4639&quot;&gt;hidden setting&lt;/a&gt; called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LinuxFxVersion&lt;/code&gt; in a different place (Site Config) that has no UI in the Azure Portal for configuring it on Linux. Fortunately &lt;a href=&quot;https://www.terraform.io/docs/providers/azurerm/r/function_app.html#linux_fx_version&quot;&gt;Terraform has a way&lt;/a&gt; to address this undocumented property. It appears in ARM as well but I haven’t found a way to edit it from the Azure Portal.&lt;/p&gt;

&lt;p&gt;I’ve seen various weird crashes when deploying and restarting function apps. There are at least 3 different undocumented things that can go wrong, leaving only a cryptic error message. Searching for these issues usually fails to yield any relevant results. I’ve seen more strange errors with version 3 of the functions app runtime than with version 2.&lt;/p&gt;

&lt;p&gt;Another frustration is the Azure CLI. The best case when deploying a function app is the message &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Operation failed with status: 200 Operation completed successfully&lt;/code&gt;. As amusing as that is, more often the tool simply fails with a HTTP 400 error: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bad Request&lt;/code&gt; with no explanation. Since the CLI hits the API about 8 times during deployment, there is no way to know how far you got or what state it left your app in. This completely breaks any kind of deployment automation. In production, you’ll have to pay somebody to hand-hold the build and make sure changes make it out to your customers.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Setting SNS String Array Message Attributes with the AWS Javascript SDK</title>
<link href="http://iangilham.com/2019/06/04/sns-string-array-message-attributes.html" rel="alternate"/>
<updated>2019-06-04T00:00:00+00:00</updated>
<id>http://iangilham.com/2019/06/04/sns-string-array-message-attributes.html</id>



<content type="html">&lt;p&gt;AWS Simple Notification Service is a great tool for broadcasting messages to a topic. Subscribers receive all messages by default, or can use a filter on the messagee’s attributes to receive only a subset of the messages sent to the topic.&lt;/p&gt;

&lt;p&gt;Message attributes have a few possible &lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html#SNSMessageAttributes.DataTypes&quot;&gt;data types&lt;/a&gt;. Unfortunately the &lt;a href=&quot;https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SNS.html#publish-property&quot;&gt;documentation&lt;/a&gt; for the Javascript SDK is pretty bad at the time of writing. It’s fairly obvious how to set an attribute of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt; but it says nothing about how to set an attribute of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String.Array&lt;/code&gt;. Fortunately, I guessed correctly when I gave it a try.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AWS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;aws-sdk&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;./config&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;AWS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;region&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;eu-west-1&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// or your region&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;aws&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;SNS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;notificationGroups&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;GroupA&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;GroupB&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sendMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;errorCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;params&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Something happened&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;TopicArn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;MessageAttributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;errorCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;DataType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;StringValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;errorCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;DataType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;String.Array&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;StringValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;notificationGroups&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;publish&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The trick is to call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JSON.stringify(someArray)&lt;/code&gt; and stuff it into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StringValue&lt;/code&gt; key in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageAttribute&lt;/code&gt; object.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Declaring required commands in bash scripts</title>
<link href="http://iangilham.com/2018/02/22/declaring-required-commands-in-bash-scripts.html" rel="alternate"/>
<updated>2018-02-22T00:00:00+00:00</updated>
<id>http://iangilham.com/2018/02/22/declaring-required-commands-in-bash-scripts.html</id>



<content type="html">&lt;p&gt;It’s funny how easy it is to overlook an obvious solution to a trivial problem and keep doing things the slow way for years at a time.&lt;/p&gt;

&lt;p&gt;While writing a short bash script today, it occurred to me that I’ve been handling requirements poorly for years. I’ve previously used long chains of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if !$(which COMMAND) &amp;amp;&amp;gt;/dev/null&lt;/code&gt; to declare and enforce requirements but it never occurred to me to wrap it in a simple function. This is what popped out of my head today:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/bin/bash
# Declare requirements in bash scripts

set -e

function requires() {
    if ! command -v $1 &amp;amp;&amp;gt;/dev/null; then
        echo &quot;Requires $1&quot;
        exit 1
    fi
}

requires &quot;jq&quot;
requires &quot;curl&quot;
# etc.

# ... rest of script
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This makes it easy to declare simple command requirements without repeating the basic &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if not found then fail&lt;/code&gt; logic over and over. In hindsight it should have been obvious to wrap this stuff in a function years ago, but at least I’ve caught up now.&lt;/p&gt;

&lt;p&gt;The requires function can of course be placed in a common file for inclusion into multiple scripts. I’ve shown it inline for simplicity.&lt;/p&gt;

&lt;p&gt;This snippet also available as &lt;a href=&quot;https://gist.github.com/igilham/bb3d01441f8d9d72960a9e742656079e&quot;&gt;a Gist&lt;/a&gt;.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Add security headers to an S3 static site with Lambda@Edge</title>
<link href="http://iangilham.com/2017/08/22/add-headers-with-lambda-edge.html" rel="alternate"/>
<updated>2017-08-22T00:00:00+00:00</updated>
<id>http://iangilham.com/2017/08/22/add-headers-with-lambda-edge.html</id>



<content type="html">&lt;p&gt;As the web continues to evolve, the selection of HTTP response headers a site is expected to support grows. Some of the security-related headers are now considered mandatory by various online publishers, including Google and Mozilla. If like me you run your site using an &lt;a href=&quot;https://www.google.co.uk/url?sa=t&amp;amp;rct=j&amp;amp;q=&amp;amp;esrc=s&amp;amp;source=web&amp;amp;cd=1&amp;amp;cad=rja&amp;amp;uact=8&amp;amp;ved=0ahUKEwj-suvf0-rVAhUFLcAKHcj3C88QFggzMAA&amp;amp;url=https%3A%2F%2Faws.amazon.com%2Fs3%2F&amp;amp;usg=AFQjCNGhdCJIuxhQCGpt9I04osRzuA_71Q&quot;&gt;S3 bucket&lt;/a&gt; of static files, it’s not easy to add the recommended headers and improve your site’s security scores in tools like &lt;a href=&quot;https://observatory.mozilla.org/&quot;&gt;Mozilla’s Observatory&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://aws.amazon.com/cloudfront/&quot;&gt;CloudFront&lt;/a&gt; and &lt;a href=&quot;https://aws.amazon.com/lambda/edge/&quot;&gt;Lambda@Edge&lt;/a&gt; can fix that. &lt;a href=&quot;https://aws.amazon.com/blogs/aws/lambdaedge-intelligent-processing-of-http-requests-at-the-edge/&quot;&gt;Others&lt;/a&gt; have detailed the process more fully than I can but beware that some features may have changed since the older posts were written. I suggest following the article linked previously if you want to implement this for your site.  I’ve listed some of the gotchas that slowed me down below.&lt;/p&gt;

&lt;h2 id=&quot;adding-the-right-permissions-to-the-lambda-iam-role&quot;&gt;Adding the right permissions to the Lambda IAM role&lt;/h2&gt;

&lt;p&gt;While creating the Lambda you will be asked to assign it a role. Make sure you add the &lt;strong&gt;Basic Edge Lambda&lt;/strong&gt; template to the role you create to allow the function trigger to be created. I missed this step the first time and it took me a few tries to figure it out.&lt;/p&gt;

&lt;h2 id=&quot;beware-of-replication&quot;&gt;Beware of replication&lt;/h2&gt;

&lt;p&gt;When you deploy the Lambda and attach the trigger, CloudFront will create replicas of the Lambda in various regions. If you then update your function, publish a new version and redeploy, it will create more replicas. The replicas of older versions are not automatically deleted and cannot be deleted by the user at this time so they will pollute your account with potentially large numbers of unused Lambda functions. Hopefully Amazon will fix this issue at some point.&lt;/p&gt;

&lt;h2 id=&quot;choose-your-trigger-wisely&quot;&gt;Choose your trigger wisely&lt;/h2&gt;

&lt;p&gt;CloudFront supports 4 triggers: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;origin-request&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;origin-response&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;viewer-request&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;viewer-response&lt;/code&gt;. The restrictions on run-time and memory size are different for different triggers so pay attention to the delays your functions introduce to the trafic flow.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;viewer&lt;/em&gt; triggers are run outside of CloudFront’s caching layer so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;viewer-request&lt;/code&gt; is triggered before the request hits the cache and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;viewer-response&lt;/code&gt; is triggered after the response has exited the cache.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;origin-response&lt;/code&gt; is triggered after CloudFront has found the resource but before it writes its response to its own cache. That means you can add headers and cache the result, reducing Lambda invokations and delays, keeping the cost down.&lt;/p&gt;

&lt;h2 id=&quot;headers-and-their-values&quot;&gt;Headers and their values&lt;/h2&gt;

&lt;p&gt;I’ve configured CloudFront to redirect HTTP requests to my site to use HTTPS but browsers like a header to make that even clearer. HSTS or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Strict-Host-Security&lt;/code&gt; does this job. Other than that, there’s a range of headers that help the browser to mitigate the risks of XSS (Cross-site scripting) vulnerabilities. These are well &lt;a href=&quot;https://wiki.mozilla.org/Security/Guidelines/Web_Security&quot;&gt;documented by Mozilla&lt;/a&gt; so I won’t rehash it all here.&lt;/p&gt;

&lt;p&gt;The interesting one is the CSP (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Security-Policy&lt;/code&gt;) header. There are a few versions of the syntax supported by different browsers and getting it right is a little tricky. The excellent &lt;a href=&quot;https://csp-evaluator.withgoogle.com/&quot;&gt;CSP Evaluator&lt;/a&gt; by Google is very helpful for testing wordings of the CSP. Tunine the policy to work properly with Google Analytics and allow inline stylesheets while disabling most other avenues of attack took a few attempts to get right but I’m happy with what I ended up with.&lt;/p&gt;

&lt;p&gt;I disabled everything by default with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default-src: &apos;none&apos;&lt;/code&gt; then added the permissions I needed for my site. I use a very small inline CSS stylesheet so I needed to enable that with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;style-src &apos;self&apos; &apos;unsafe-inline&apos;&lt;/code&gt;. I don’t make much use of images at present but if I do I’ll access them over HTTPS so I enabled that with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;img-src &apos;self&apos; https:&lt;/code&gt;. Opening up just the needed permissions for scripts was a bit more difficult but the CSP Evaluator helped a great deal. It recommends a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strict-dynamic&lt;/code&gt; policy for browsers that support it. I only use one script on my site for Google Analytics, so I had to extract the contents (including all whitespace) from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag, hash it with SHA256, then encode the hash with Base64 and add the result directly to the CSP policy. CSP Evaluator also recommends some fall-back options for browsers that do not yet support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strict-dynamic&lt;/code&gt; so I end up with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;script-src &apos;strict-dynamic&apos; &apos;sha256-my_script_hash&apos; &apos;unsafe-inline&apos; https:&lt;/code&gt;, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my_script_hash&lt;/code&gt; is the Base64-encoded SHA256 hash of the contents of my script. The complete example is in the below code.&lt;/p&gt;

&lt;h2 id=&quot;lambda-code-template&quot;&gt;Lambda code template&lt;/h2&gt;

&lt;p&gt;My basic Lambda template for adding custom headers to all HTTP responses on my site is shared below.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;use strict&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;v&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Records&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;headers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// hsts header at 2 years&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Strict-Transport-Security: max-age=63072000; includeSubDomains;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Strict-Transport-Security&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;max-age=63072000; includeSubDomains; preload&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Reduce XSS risks&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;X-Content-Type-Options&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;nosniff&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;X-XSS-Protection&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;1; mode=block&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;X-Frame-Options&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;DENY&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// TODO: fill in value of the sha256 hash&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;csp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;default-src &apos;none&apos;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
        &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;; frame-ancestors &apos;none&apos;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
        &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;; base-uri &apos;none&apos;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
        &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;; style-src &apos;self&apos; &apos;unsafe-inline&apos;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
        &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;; img-src &apos;self&apos; https:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
        &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;; script-src &apos;strict-dynamic&apos; &apos;sha256-my_script_hash&apos; &apos;unsafe-inline&apos; https:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Content-Security-Policy&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;csp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Response headers added&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;nf&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Preventing rpmbuild from stripping symbols using cpack</title>
<link href="http://iangilham.com/2016/12/08/preventing-rpmbuild-stripping-symbols-with-cpack.html" rel="alternate"/>
<updated>2016-12-08T00:00:00+00:00</updated>
<id>http://iangilham.com/2016/12/08/preventing-rpmbuild-stripping-symbols-with-cpack.html</id>



<content type="html">&lt;p&gt;I’ve been trying to analyse a core dump generated by a C++ application when it seg-faulted. I use CMake 3 to build it and create an RPM with CPack. This application is currently built in debug mode using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-DCMAKE_BUILD_TYPE=Debug&lt;/code&gt; on the command line that invokes CMake.&lt;/p&gt;

&lt;p&gt;The generated binaries have all their debug symbols as expected but the binaries in the RPM package do not. After some searching, I learned that rpmbuild strips binaries by default &lt;em&gt;on some distributions&lt;/em&gt;. This makes analysing a core dump way harder than it needs to be so I found a way to turn this feature off using CPack. The trick is to set a variable in the CMakeLists.txt file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# prevent rpmbuild from stripping binaries when in debug mode
if(CMAKE_BUILD_TYPE STREQUAL &quot;Debug&quot;)
  set(CPACK_RPM_SPEC_INSTALL_POST &quot;/bin/true&quot;)
endif()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now my debug packages retain their debug info after installation so it’s possible to get a lot more information out of gdb when looking at a core dump.&lt;/p&gt;

&lt;p&gt;This is &lt;a href=&quot;https://cmake.org/Wiki/CMake:CPackPackageGenerators#CPack_RPM_usage&quot;&gt;documented&lt;/a&gt; in a roundabout way online, but it took me a while to figure it out so I thought I’d write it up.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Getting a core dump out of CentOS 7.2</title>
<link href="http://iangilham.com/2016/12/08/core-dump-from-centos-7.html" rel="alternate"/>
<updated>2016-12-08T00:00:00+00:00</updated>
<id>http://iangilham.com/2016/12/08/core-dump-from-centos-7.html</id>



<content type="html">&lt;p&gt;Since &lt;a href=&quot;https://www.freedesktop.org/wiki/Software/systemd/&quot;&gt;Systemd&lt;/a&gt; took over as the main init system in Red Hat Linux and derrivatives like CentOS, it has become more difficult to get a core dump out of a daemon application. The traditional approach of running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ulimit -c unlimited&lt;/code&gt; before executing the binary works when running the application from the command line but does nothing for a daemon managed by Systemd’s unit files.&lt;/p&gt;

&lt;p&gt;There is a lot of misleading information online about how to solve this so I thought I’d add a correct solution to the mix in the hope that it’s helpful.&lt;/p&gt;

&lt;p&gt;The suggestions I found online include editing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/security/limits.conf&lt;/code&gt;, adding LimitCore=infinity to the Unit file, and messing around with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/systemd/coredump.conf&lt;/code&gt;. None of these methods work without customising the kernel configuration first.&lt;/p&gt;

&lt;p&gt;Systemd is not configured to handle core dumps by default on CentOS (and by extension RHEL) distributions. The default behaviour is to write to the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core&lt;/code&gt; in the process’s working directory, which for daemons is often the root directory.&lt;/p&gt;

&lt;p&gt;The obvious problem here is that the daemon probably doesn’t have write access to the root directory (if running as a non-root user). If is possible to change the working directory with the Systemd unit directive &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WorkingDirectory=/var/run/XXX&lt;/code&gt;. This is typically used with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RuntimeDirectory=XXX&lt;/code&gt;, which creates and manages the lifecycle of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/run/XXX&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/run&lt;/code&gt; is a symlink to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/run&lt;/code&gt;). Unfortunately, we can’t write the core file to a &lt;em&gt;RuntimeDirectory&lt;/em&gt; because it gets deleted when the application terminates.&lt;/p&gt;

&lt;p&gt;The simplest solution I found is to overwrite the kernel &lt;strong&gt;core_pattern&lt;/strong&gt; setting. This can be edited at runtime by echoing a new value into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/proc/sys/kernel/core_pattern&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; /tmp/core-%e-sig%s-user%u-group%g-pid%p-time%t &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /proc/sys/kernel/core_pattern
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will force the kernel to write all core files during the current OS uptime to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp&lt;/code&gt; with the filename pattern specified. The &lt;a href=&quot;http://man7.org/linux/man-pages/man5/core.5.html&quot;&gt;core manpage&lt;/a&gt; has more information on the syntax.&lt;/p&gt;

&lt;p&gt;This change will be lost when the machine reboots. To effect the change at kernel startup, you need to edit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/sysctl.conf&lt;/code&gt; or a file in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/sysctl.d/&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kernel.core_pattern&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/tmp/core-%e-sig%s-user%u-group%g-pid%p-time%t
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Our solution at work was to write a script to create a file in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/sysctl.d/&lt;/code&gt; at machine image creation time, so that the config is always there when we roll out to different environments (int, test, live etc.)&lt;/p&gt;

&lt;p&gt;It should go without saying that there is no particular reason to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp&lt;/code&gt;. The output can be redirected to any location the process has permission to write to. A network share may be more appropriate in some cases.&lt;/p&gt;

&lt;p&gt;There may be another solution using &lt;strong&gt;systemd-coredump&lt;/strong&gt;, but it is not part of this release of CentOS (7.2) and not in the yum repository at this time.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Azure Functions and Storage Tables</title>
<link href="http://iangilham.com/2016/04/08/Azure-functions-and-tables.html" rel="alternate"/>
<updated>2016-04-08T00:00:00+00:00</updated>
<id>http://iangilham.com/2016/04/08/Azure-functions-and-tables.html</id>



<content type="html">&lt;p&gt;I’ve written previously about how Amazon’s &lt;a href=&quot;/2016/01/26/AWS-Lambda-feels-like-the-future.html&quot;&gt;AWS Lambda feels like the future&lt;/a&gt;. I had a little time today to play with &lt;a href=&quot;https://azure.microsoft.com/en-us/services/functions/&quot;&gt;Azure Functions&lt;/a&gt;, Microsoft’s new competing service.&lt;/p&gt;

&lt;p&gt;As a preview, Azure Functions isn’t quite polished yet, but the basic building blocks are in place. You create a &lt;strong&gt;Function App&lt;/strong&gt; in the Azure Portal, much like you would create a Web or Mobile App, then add a few Functions in the Portal blade.&lt;/p&gt;

&lt;p&gt;Since the service is built on the mature &lt;a href=&quot;https://azure.microsoft.com/en-gb/documentation/articles/web-sites-create-web-jobs/&quot;&gt;WebJobs&lt;/a&gt; product, there is already strong language support. Azure Functions can be created with specialised C#, NodeJS, PHP, Python, Powershell, Windows Batch scripts (I know), or any standard Windows executable. The Portal UI leaves a lot to be desired for now. I did’t find any obvious way of using different languages or packaging up apps and dependencies, but did manage to get it working. The documentation implies that there are many more features than those exposed by the Portal blade.&lt;/p&gt;

&lt;p&gt;For the sake of a quick test, I created a small function to connect to the &lt;a href=&quot;https://azure.microsoft.com/en-gb/services/storage/&quot;&gt;Azure Storage&lt;/a&gt; account and create an empty Table. I had a little trouble setting up the connection string to the storage account but found a solution using magic environment variables &lt;a href=&quot;https://azure.microsoft.com/en-gb/blog/windows-azure-web-sites-how-application-strings-and-connection-strings-work/&quot;&gt;here&lt;/a&gt;. This may seem normal to regular dotNet and/or Azure developers but it was new to me. The documentation implied that I needed to use a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CloudConfigurationManager&lt;/code&gt; from &lt;a href=&quot;https://www.nuget.org/packages/Microsoft.WindowsAzure.ConfigurationManager/&quot;&gt;this NuGet package&lt;/a&gt; but I failed to figure out how to pull in the dependency and resolve the namespace. The solution is to copy a connection string from the Azure Storage account and paste it into the Functions App Service Settings blade’s Application Settings under “Connection Strings”. This effectively makes the string available to the Function in an environment variable at runtime. If our connection string is named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StorageConnectionString&lt;/code&gt;, and the type is “Custom”, then the value will be available in the environment variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CUSTOMCONNSTR_StorageConnectionString&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the code I ended up with as shown in the editor in the Azure Portal.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#r &quot;Microsoft.WindowsAzure.Storage&quot;

using System;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;

public static void Run(object trigger)
{
    var storage = CloudStorageAccount.Parse(
        Environment.GetEnvironmentVariable(
            &quot;CUSTOMCONNSTR_StorageConnectionString&quot;));
    var tableClient = storage.CreateCloudTableClient();
    var membersTable = tableClient
        .GetTableReference(&quot;MyTable&quot;);

    membersTable.CreateIfNotExists();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This file is a little weird because it is a csx file. There is some documentation in the &lt;a href=&quot;https://azure.microsoft.com/en-us/documentation/articles/functions-reference/&quot;&gt;Azure Functions Developer Reference&lt;/a&gt; but it’s essentially C# with embedded assembly references (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#r &quot;Microsoft.WindowsAzure.Storage&quot;&lt;/code&gt;) and a top-level &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public static void Run&lt;/code&gt; method. Any other classes etc. you need can be included inline in the file.&lt;/p&gt;

&lt;p&gt;With the code in place, you have to switch to the ‘integration’ tab to enable a trigger so that the function can be run. I did the minimum needed to test the function and just selected a manual trigger, changed the name to “trigger”, then switched back to the code view and hit the “Run” button at the bottom of the Function App blade. It took a few goes to get the code right, but with everything working, I was able to confirm that it worked by opening the storage account blade in the Azure Portal and looking at the list of Tables in the account. Sure enough, we have our shiny new table.&lt;/p&gt;

&lt;p&gt;While creating a table programmatically is about the simplest use case I could think of for testing a Function, I must admit that it feels a bit forced to have to write code for this at all. I prefer Amazon’s model of providing Console-based UIs for most of the core functionality, like creating tables and adding records. There are Storage Explorer tools for this on Azure, but it would be nice to be able to manage everything from the Portal.&lt;/p&gt;

&lt;p&gt;There’s a lot more ground to cover here: Function triggering, integration with other services, creating API endpoints and deployment automation are all considerations. I look forward to seeing how Azure Functions evolve in the future.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Triggering a Lambda from SNS using CloudFormation</title>
<link href="http://iangilham.com/2016/03/22/Sns-trigger-lambda-via-cloudformation.html" rel="alternate"/>
<updated>2016-03-22T00:00:00+00:00</updated>
<id>http://iangilham.com/2016/03/22/Sns-trigger-lambda-via-cloudformation.html</id>



<content type="html">&lt;p&gt;&lt;a href=&quot;https://aws.amazon.com/&quot;&gt;Amazon Web Services&lt;/a&gt; (AWS) provides many building blocks you can use to create just about anything in the world of web-connected services. A lot of the skill in using this toolkit is in figuring out how to make the various services work together. &lt;a href=&quot;https://aws.amazon.com/cloudformation/&quot;&gt;CloudFormation&lt;/a&gt; is critical to this effort, as it let’s you write a config file that can be used to automate the creation of all the infrastructure you need to deliver your product. The big win from using CloudFormation is reproducibility. It let’s you define your whole infrastructure requirement, put it in version control, and reproduce the same setup in a production environment without manually recreating everything.&lt;/p&gt;

&lt;p&gt;CloudFormation is not without its problems, however. The Syntax is overly verbose and awkward to author. Some of the services it can create cannot be edited, and it is easy to get into circular reference hell with more complex configurations involving the interactions between multiple products. There are reams of documentation but most of it is useless noise without meaningful explanation. The emerging best-practices are to work in another format (like &lt;a href=&quot;https://en.wikipedia.org/wiki/YAML&quot;&gt;YAML&lt;/a&gt;) and convert it to CloudFormation’s preferred format mechanically, or to pay a third party for their cloud automation tools.&lt;/p&gt;

&lt;p&gt;I’ve been struggling to get an &lt;a href=&quot;https://aws.amazon.com/sns/&quot;&gt;SNS&lt;/a&gt; topic to trigger a &lt;a href=&quot;https://aws.amazon.com/lambda/&quot;&gt;Lambda&lt;/a&gt; this week. This is really easy using the AWS console because it automates many of the tricky and barely documented steps required to get it working. Wiring it up in CloudFormation is another hell entirely. You need a few different pieces in the right order to make this work so I’ll go through each one in turn. Each of the below can be pasted into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Resources&lt;/code&gt; section of a CloudFormation template.&lt;/p&gt;

&lt;p&gt;For completeness, I’ve included a basic template skeleton here.&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;blah blah&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Parameters&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Outputs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Resources&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;lambda-execution-role&quot;&gt;Lambda Execution Role&lt;/h3&gt;

&lt;p&gt;Before you can build a Lambda Function, you need to create some permissions for it to assume at runtime. Here I present a fairly minimal role suitable for a basic Lambda Function with no external integration points. Additional permissions (e.g. reading from an S3 Bucket) can be added to the list of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Statement&lt;/code&gt;s in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PolicyDocument&lt;/code&gt;. This part is actually documented reasonably well.&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ExecutionRole&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;AWS::IAM::Role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Path&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Policies&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;PolicyName&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;CloudwatchLogs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;PolicyDocument&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Statement&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Action&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;logs:CreateLogGroup&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;logs:CreateLogStream&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;logs:GetLogEvents&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                  &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;logs:PutLogEvents&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Resource&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;arn:aws:logs:*:*:*&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Effect&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Allow&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;AssumeRolePolicyDocument&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Statement&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Action&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sts:AssumeRole&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Effect&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Allow&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Principal&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Service&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;lambda.amazonaws.com&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;lambda-function&quot;&gt;Lambda Function&lt;/h3&gt;

&lt;p&gt;The Lambda Function itself is quite easy to set up. I’ve hard-coded placeholders for the &lt;a href=&quot;https://aws.amazon.com/s3/&quot;&gt;S3&lt;/a&gt; Bucket and path to the zip file containing the code. It doesn’t matter what the code is for the purpose of this article.&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Lambda&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;AWS::Lambda::Function&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Code&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;S3Bucket&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;my-personal-bucket&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;S3Key&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;lambdas/test/my-lambda.zip&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Some Lambda Function&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;MemorySize&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Handler&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;LambdaHandler&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Fn::GetAtt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ExecutionRole&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Arn&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Timeout&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Runtime&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;python2.7&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;DependsOn&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ExecutionRole&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;sns-topic&quot;&gt;SNS Topic&lt;/h3&gt;

&lt;p&gt;The SNS Topic is very easy to create but it cannot be modified using CloudFormation after it has been created. You also have to create all the subscriptions at the same time, so if you use CloudFormation for reproducibility, you can never change the subscriptions of a running event pipeline that relies on SNS. This is a major drawback of SNS and CloudFormation and should be considered with care before you rely too heavily on this set of tools.&lt;/p&gt;

&lt;p&gt;The unmodifiable nature of SNS Topics created this way won’t be a problem if you’re creating subscriptions via an API at runtime, but it limits how flexible SNS can be for some workflows, like fanning out to &lt;a href=&quot;https://aws.amazon.com/sqs/&quot;&gt;SQS&lt;/a&gt; Queues or triggering Lambda Functions.&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Topic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;AWS::SNS::Topic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Subscription&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Endpoint&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Fn::GetAtt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Lambda&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Arn&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Protocol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;lambda&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;DependsOn&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Lambda&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;permission-for-the-topic-to-invoke-the-lambda&quot;&gt;Permission for the Topic to invoke the Lambda&lt;/h3&gt;

&lt;p&gt;Unfortunately, creating all the pieces isn’t enough. We still need to grant our SNS topic permission to invoke the Lambda Function directly. This is really important and the documentation is almost completely useless so I’m putting a working example here.&lt;/p&gt;

&lt;p&gt;It is absolutely critical to have the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SourceArn&lt;/code&gt; property refer to the Topic we created earlier. Without this, the Lambda Console will give you inexplicable errors, while the SNS Console claims that everything is correct and working. It can be very frustrating trying to get this right.&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;LambdaInvokePermission&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;AWS::Lambda::Permission&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Action&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;lambda:InvokeFunction&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Principal&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sns.amazonaws.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;SourceArn&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Topic&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;FunctionName&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Fn::GetAtt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Lambda&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Arn&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href=&quot;https://www.linkedin.com/in/colin-mcgrath-41974253&quot;&gt;An observant reader&lt;/a&gt; spotted a bug in the above CloudFormation. I originally had a reference to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SourceAccount&lt;/code&gt; in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Properties&lt;/code&gt; block:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;SourceAccount&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;AWS::AccountId&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This was incorrect. It works after removing that line.&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;That should be enough to get it all working. There are some serious holes in the capabilities of CloudFormation for working with SNS, and the permission model is a poorly documented mess. The only thing I haven’t covered is how to get the Lambda itself to run, but that’s a topic for another day.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">AWS Lambda feels like the future of software development</title>
<link href="http://iangilham.com/2016/01/26/AWS-Lambda-feels-like-the-future.html" rel="alternate"/>
<updated>2016-01-26T00:00:00+00:00</updated>
<id>http://iangilham.com/2016/01/26/AWS-Lambda-feels-like-the-future.html</id>



<content type="html">&lt;p&gt;Every now and then we find a technology that feels like the future, letting you achieve what you want to without getting in the way. Automatic and dual-clutch (semi-automatic) transmissions fall into this category, and some programmers occasionally get the bug from the latest experimental programming language or when rediscovering functional programming.&lt;/p&gt;

&lt;p&gt;I’m getting that next-big-thing feeling from Amazon’s &lt;a href=&quot;https://aws.amazon.com/lambda/&quot;&gt;AWS Lambda&lt;/a&gt; service. I’ve been building enterprise data munging applications in Java and C++ for years and have done the usual little glue scripts in Python, Ruby, Bash, CMD just like most other software developers. As we all know, the code is the fun part that takes very little time compared to the brain-numbing effort of messing around with operating systems, deployment, scaling considerations, TLS (SSL) termination, fiddling with &lt;a href=&quot;https://en.wikipedia.org/wiki/Cross-origin_resource_sharing&quot;&gt;CORS&lt;/a&gt; settings etc.&lt;/p&gt;

&lt;p&gt;When you move to cloud-rented servers, the configuration only gets worse, as the dev team has to micromanage details traditionally dealt with by operations staff running a data centre. At this level of abstraction you need to cake care of monitoring, availability and fault-tollerance while taking account of how to scale up and down with the load. And you always end up paying to leave at least one idle server sitting there waiting for something to do.&lt;/p&gt;

&lt;p&gt;The beauty of Lambda is that it does most of the boring infrastructure stuff for you magically. You don’t have to think about how many hosts might be running and how to scale them up and down. You don’t have to pay for a running host when the application is sitting idle. You don’t even have to fiddle with the half-working settings of a Java Servlvet Container or the massive weight of the &lt;a href=&quot;https://spring.io/&quot;&gt;Spring framework&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All you have to do with Lambda is write a single-purpose application (currently in Java, Python or NodeJS), deploy it and trigger it to run. It can be given an endpoint with &lt;a href=&quot;https://aws.amazon.com/api-gateway/&quot;&gt;API Gateway&lt;/a&gt; or receive notifications from other Amazon services or from any SNS topic. You only pay for executing runtime and reserved memory capacity during execution.&lt;/p&gt;

&lt;p&gt;The trade-off is obvious. Sacrifice some flexibility in exchange for a simpler life in which you can spend more of your time working on the code and delivering value. The biggest gain from adopting Lambda is the cost of developers’ time. The business saves money by paying developers to think about, design and write code full-time, not spend hours trying to wrap our heads around complex, multi-faceted configuration for a fleet of servers we don’t even need half the time. Configuration which inevitably contains faults and goes wrong in production at inconvenient times.&lt;/p&gt;

&lt;p&gt;AWS Lambda isn’t best suited to monolithic applications. It works best if you build many small, single-purpose applications. This might mean each endpoint of your traditional monolith has a separate codebase, perhaps sharing a small library of common abstractions. The composable, single-purpose model encourages a scripting-like mindset, so complex frameworks become a hindrance. Even a basic &lt;a href=&quot;https://en.wikipedia.org/wiki/Create,_read,_update_and_delete&quot;&gt;CRUD&lt;/a&gt; application quickly decomposes into 4 or 5 tiny scripts. The Python and NodeJS support are ideal for supporting this approach, but it’s easy enough to extract functionality from existing Java monoliths as well.&lt;/p&gt;

&lt;p&gt;In summary, AWS Lambda feels like the future of software development in ways that promising new programming languages don’t. It provides a great deal of flexibility within the problem domain while taking away most of the undifferentiated wastes of time in the software development process (internal corporate noise excepted). It encourages keeping delivered software very small and single-purpose, which makes it easy to keep the quality bar fairly high through peer reviews. I’m pretty excited to see how Lambda evolves over the next few years and what the competitors do to up their game.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Building Unity's space shooter tutorial</title>
<link href="http://iangilham.com/2015/12/11/unity3d-space-shooter-tutorial.html" rel="alternate"/>
<updated>2015-12-11T00:00:00+00:00</updated>
<id>http://iangilham.com/2015/12/11/unity3d-space-shooter-tutorial.html</id>



<content type="html">&lt;p&gt;This weekend I found time to continue learning about the &lt;a href=&quot;http://www.unity3d.com/&quot;&gt;Unity&lt;/a&gt; game engine and development environment. The &lt;a href=&quot;http://unity3d.com/learn/tutorials/projects/space-shooter-tutorial&quot;&gt;second tutorial&lt;/a&gt; is a simple vertical scrolling space shooter game. My implementation of the project is &lt;a href=&quot;https://github.com/igilham/unity3d-tutorial-space-shooter&quot;&gt;on Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Space Shooter is a lot more complex than the &lt;a href=&quot;/2015/11/13/starting-out-with-unity3d.html&quot;&gt;Rollerball&lt;/a&gt; game so it’s a good introduction into game making. Rollerball was a great way to learn how to use the Unity editor and think about game objects. Space Shooter comes with some pre-built assets including models, materials and music useful for wiring something more complete together.&lt;/p&gt;

&lt;p&gt;I was initially a little surprised to learn that the essentially 2D game was built with 3D models using a fixed camera. This made it easy rotate and tilt the on-screen objects and make the most of Unity’s lighting system. It would be possible to achieve many similar effects with the editor in 2D mode, with considerably more work animating sprites, but the 3D approach is easy and fairly intuitive.&lt;/p&gt;

&lt;p&gt;The game is implemented as a fixed camera, a player-controlled ship object which can only move within a predefined area, and a background. Asteroids then appear and move from the top of the screen to the bottom and serve as the primary hazzard.&lt;/p&gt;

&lt;p&gt;The tutorial spends some time explaining how to build the prefabricated game objects from the supplied assets then goes on to cover how to add behaviour one piece at a time. The basic input control is similar to that found in Rollerball. It gets more interesting when you start setting up collision detection, spawning hazzards, destroying objects when they’re off-screen or have expired. Adding the ability to shoot and handling collisions between the shot and the hazzards added another dimension to the game. Adding a scoring mechanism and simple restart function rounded out the basic playable experience.&lt;/p&gt;

&lt;p&gt;Once the game is in a functional state, there are a few more extensions to make the player experience a little better. Getting the background texture to scroll creates the illusion of movement. Adding a particle effect over the background enhances the effect. Adding more variety to the hazzards and makes the game feel more natural. After all that, we add an enemy ship type to the hazzards and give it the ability to shoot and perform simple manoeuvers.&lt;/p&gt;

&lt;p&gt;At this point we have a complete little game that my non-technical partner found equal parts fun and frustrating for a few minutes. It’s easy to imagine how the game could be expanded further with power-ups, a hitpoints/damage system, extra lives and more levels with different challenges to overcome.&lt;/p&gt;

&lt;p&gt;I’m having a lot of fun playing with Unity. I’ll look at the next tutorial when I can.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Starting out with the Unity game engine</title>
<link href="http://iangilham.com/2015/11/13/starting-out-with-unity3d.html" rel="alternate"/>
<updated>2015-11-13T00:00:00+00:00</updated>
<id>http://iangilham.com/2015/11/13/starting-out-with-unity3d.html</id>



<content type="html">&lt;p&gt;&lt;strong&gt;Update (2012-12-11):&lt;/strong&gt; I’ve put the project &lt;a href=&quot;https://github.com/igilham/unity3d-tutorial-rollerball&quot;&gt;on Github&lt;/a&gt;. I don’t know the correct license to use, but it is safe to say it is a derivative work of &lt;a href=&quot;http://unity3d.com/learn/tutorials/projects/roll-ball-tutorial&quot;&gt;this project by Unity Technologies&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’ve had an interest in computer games for many years. Since I’m in the software trade, I’ve often thought about building a simple game as a way to learn how the technology works. I finally decided to have a go a couple of weeks ago and started looking into the technology.&lt;/p&gt;

&lt;p&gt;The first engine that came to mind was &lt;a href=&quot;http://www.unity3d.com/&quot;&gt;Unity&lt;/a&gt;, a large cross-platform toolkit for building games. I considered a couple of other options but Unity seemed to be the easiest and most beginner-friendly tool to get something really simple off the ground.&lt;/p&gt;

&lt;p&gt;I didn’t really know what to expect from Unity or games toolkits/engines in general. Unity, it turns out, provides a tool like an IDE with a level editor, property editors, animations tools, shader tweaking tools, and support for ‘scripts’ written in C# (amongst other things). I have since learned that some other game engines just provide a pile of small utility programs and libraries, and there is just about everything in between available. I’m used to working with IDEs so Unity felt pretty comfortable to get started in.&lt;/p&gt;

&lt;p&gt;Over the course of a few evenings I’ve gone through the &lt;a href=&quot;http://unity3d.com/learn/tutorials/projects/roll-ball-tutorial&quot;&gt;first tutorial&lt;/a&gt;, a simple game with a rolling ball and pick-ups to collect. Despite having no experience with games, I found the tutorials really easy to follow. The explanations helped me to understand the terminology and dig into the basic functionality of the engine.&lt;/p&gt;

&lt;p&gt;I was surprised how little code I had to write to glue the game together. I think it was around 10 or 20 lines of C# in total. Loads more code than that ends up in the distribution of course, this is a complete interactive 3D gaming engine after all, but most of the basic building blocks are either visual tools or built in and configured with easy-to-use menus.&lt;/p&gt;

&lt;p&gt;So far I’ve been really impressed with the ease-of-use and quality tutorials and documentation. Unity is obviously a very powerful toolkit. I’m looking forward to digging a little deeper with the &lt;a href=&quot;http://unity3d.com/learn/tutorials/projects/space-shooter-tutorial&quot;&gt;next tutorial project&lt;/a&gt; when I have a bit more time.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">A Tour of the Liberate Cable Platform</title>
<link href="http://iangilham.com/2015/08/03/liberate-cable-tour.html" rel="alternate"/>
<updated>2015-08-03T00:00:00+00:00</updated>
<id>http://iangilham.com/2015/08/03/liberate-cable-tour.html</id>



<content type="html">&lt;p&gt;Now that Glastonbury and Wimbledon are over with no major technical failures, it feels like a good time to talk about the interactive TV application I built for the events. For the last few years the BBC has been fielding an application that allows the audience to switch between different hidden video streams on broadcast TV. We always aimed to equally support all the broadcast digital platforms (terrestrial, satellite and cable) but for operational reasons this is the first time we’ve had a complete offering on the cable platform. I’d like to share some of what I learned developing software for cable TV in the UK.&lt;/p&gt;

&lt;p&gt;For the last few months I’ve been working on a client application for the UK’s aging cable television platform. For the purpose of this article, I’m talking about the older boxes operated by &lt;a href=&quot;http://virginmedia.com/&quot;&gt;Virgin Media&lt;/a&gt;, not the TiVo branded boxes. These set-top boxes run the Liberate TV Navigator middleware, which is essentially just a really old web browser with a few TV-specific extensions.&lt;/p&gt;

&lt;p&gt;The set-top box browser supports a variant of HTML 3.2 and a very early JavaScript interpreter. It is largely based on &lt;a href=&quot;http://en.wikipedia.org/wiki/Netscape_(web_browser)&quot;&gt;Netscape Communicator&lt;/a&gt; 4.76 and was never updated to more modern web standards. The Liberate middleware (now owned by &lt;a href=&quot;http://www.schange.com/&quot;&gt;SeaChange&lt;/a&gt; did see at least a few revisions, but these never made it into consumer products in the UK.&lt;/p&gt;

&lt;p&gt;There are a number of challenges to working with older browsers like this. Here’s a brief list of some of the things the browser cannot do:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;CSS&lt;/li&gt;
  &lt;li&gt;JavaScript object literal syntax (JSON)&lt;/li&gt;
  &lt;li&gt;JavaScript function literal syntax (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var f = function() { return &quot;foo&quot;; }&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;DOM API&lt;/li&gt;
  &lt;li&gt;The switch statement&lt;/li&gt;
  &lt;li&gt;Document scrolling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The document is a fixed-size rectangle of 720 by 576 pixels. The web page can embed and scale the TV’s video stream, but the complete document must be statically sized to fit within those dimensions. Since there are no advanced layout controls, the design is restricted to hard-coded HTML tables with fixed size rows and columns. The tables can’t be nested more than a few layers deep either, as that leads to serious performance issues on most of the older devices.&lt;/p&gt;

&lt;p&gt;JavaScript can be used to get a reference to tables and fish out their elements. There is some limited ability to modify the contents by changing text, foreground and background colours (including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transparent&lt;/code&gt; to hide them completely), but there is no way to dynamically add elements to the DOM or resize existing table cells, so each document is restricted to showing and hiding elements defined statically, and changing foreground and background colours.&lt;/p&gt;

&lt;p&gt;The absence of object and function literals in JavaScript makes writing object-oriented code tricky. The only mechanism that works in the Liberate browser is to add named functions as methods on a constructor function’s prototype. This is more complete than functional programming support however, which has too many missing features to be workable.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var tblMain = document.tblMain;

function Foo() {
	this.name = &quot;foo&quot;;
}

function foo_hello() {
	tblMain.rows[0].cells[0].write(&quot;Hello, &quot; + this.name);
}
Foo.prototype.hello = foo_hello;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The above example assumes a document containing a table element with the attribute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name=&quot;tblMain&quot;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The limited syntax support creates issues when assembling a content pipeline for the website as well. Typical minification tools like &lt;a href=&quot;https://github.com/lautis/uglifier&quot;&gt;uglifier&lt;/a&gt; and &lt;a href=&quot;https://developers.google.com/closure/compiler/&quot;&gt;Closure Compiler&lt;/a&gt; tend to change object and array declarations to use object literals (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;= new Array()&lt;/code&gt; vs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=[]&lt;/code&gt;), so they have to be used carefully to avoid breaking the scripts in the browser.&lt;/p&gt;

&lt;p&gt;The browser can fetch resources from a &lt;a href=&quot;http://en.wikipedia.org/wiki/Data_and_object_Carousel&quot;&gt;broadcast carousel&lt;/a&gt; file system (known as in-band data) or via HTTP over the &lt;a href=&quot;http://en.wikipedia.org/wiki/DOCSIS&quot;&gt;DOCSIS&lt;/a&gt; return path (out-of-band). The Cable operator places restrictions on what URLs can be retrieved for safety, so the network can be thought of as an Intranet, though out-of-band data is not immune to man-in-the-middle attacks.&lt;/p&gt;

&lt;h2 id=&quot;drawing-a-user-interface&quot;&gt;Drawing a user interface&lt;/h2&gt;

&lt;p&gt;A simple user interface can be drawn with basic HTML 3.2 tables.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;html&amp;gt;
	&amp;lt;head&amp;gt;
		&amp;lt;title&amp;gt;test application&amp;lt;/title&amp;gt;
		&amp;lt;script&amp;gt;
		// your scripts here
		&amp;lt;/script&amp;gt;
	&amp;lt;/head&amp;gt;
	&amp;lt;body onload=&quot;onLoad()&quot; onunload=&quot;onUnload()&quot; background=&quot;tv://&quot;&amp;gt;
		&amp;lt;table name=&quot;uiRoot&quot;
				width=&quot;720&quot; height=&quot;576&quot;
				cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; border=&quot;0&quot;&amp;gt;
			&amp;lt;!-- header row with borders --&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;td width=&quot;50&quot; height=&quot;30&quot;&amp;gt;&amp;lt;/td&amp;gt;
				&amp;lt;td width=&quot;620&quot;&amp;gt;&amp;lt;/td&amp;gt;
				&amp;lt;td width=&quot;50&quot;&amp;gt;&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
			&amp;lt;!-- content row with borders --&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;td width=&quot;50&quot; height=&quot;30&quot;&amp;gt;&amp;lt;/td&amp;gt;
				&amp;lt;!-- content area --&amp;gt;
				&amp;lt;td width=&quot;620&quot; bgcolor=&quot;white&quot;&amp;gt;
					&amp;lt;font size=&quot;5&quot; color=&quot;black&quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/font&amp;gt;
				&amp;lt;/td&amp;gt;
				&amp;lt;td width=&quot;50&quot;&amp;gt;&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
		&amp;lt;/table&amp;gt;
	&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this example, the content area is a table cell containing text. The cell can be manipulated as in the following code.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;function hideContent() {
	window.uiRoot.rows[1].cells[1].bgcolor = &quot;transparent&quot;;
	window.uiRoot.rows[1].cells[1].write(true, &quot;&quot;);
}

function showContent() {
	window.uiRoot.rows[1].cells[1].bgcolor = &quot;white&quot;;
	window.uiRoot.rows[1].cells[1].write(true, &quot;Hello world!&quot;);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Similar methods are used to implement a navigable menu, with a highlight colour for the current row’s background. This would require the hard-coded HTML table to contain enough rows to represent the full menu, and some functions to navigate up and down, and highlight, show or hide each row.&lt;/p&gt;

&lt;p&gt;When making multiple UI changes, it can be beneficial to lock the UI layer then allow the changes to draw when finished. This can be done at the level of the table or sub-table element in the HTML layer.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// lock UI
window.uiRoot.drawingDisabled = true;

// make some UI changes

// unlock UI
window.uiRoot.drawingDisabled = false;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;handling-user-input&quot;&gt;Handling user input&lt;/h2&gt;

&lt;p&gt;Input handling is old-school on Liberate. Input events call the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;window.onkeyout&lt;/code&gt; function and provide the opportunity to decode &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;navigator.input.curKey&lt;/code&gt; and run any required behaviours. Keys are represented by raw numbers, so a map of names to key codes can be useful.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;function KeyMap() {
	this.HELP = 779;
	this.INFO = 775;
	this.RED = 2048;
	this.GREEN = 2049;
	this.YELLOW = 2050;
	this.BLUE = 2051;
	this.TV = 2053;
	this.PAGEUP = 1284;
	this.PAGEDOWN = 1285;
	this.VOLUP = 1026;
	this.VOLDOWN = 1027;
	this.MUTE = 1036;
	this.OK = 13;
	this.UP = 1280;
	this.DOWN = 1281;
	this.LEFT = 1282;
	this.RIGHT = 1283;
	this.BACK = 1288;
	this.N0 = 48;
	this.N1 = 49;
	this.N2 = 50;
	this.N3 = 51;
	this.N4 = 52;
	this.N5 = 53;
	this.N6 = 54;
	this.N7 = 55;
	this.N8 = 56;
	this.N9 = 57;
}
var K = new KeyMap();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The basic layout of an input handler function is below. This follows the previous example, toggling display of the UI’s ‘hello world’ box.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;function doKeyout() {
	var key = navigator.input.curKey;

	// let the user alter volume/mute
	if (key ==K.VOLUP || key == K.VOLDOWN || key == K.MUTE) {
		return true; // invokes STB default behaviour
	}

	// handle application input
	if (key == K.OK) {
		// togle the UI content
		if (window.uiRoot.rows[1].cells[1].bgcolor == &quot;transparent&quot;) {
			showContent();
		} else {
			hideContent();
		}
	}
	return false;
}
window.onkeyout = doKeyout;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;fetching-resources-with-netrequest&quot;&gt;Fetching resources with NetRequest&lt;/h2&gt;

&lt;p&gt;While the Liberate TV Navigator browser can’t parse JSON, it can fetch an in-band JavaScript file and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval&lt;/code&gt; it. This enables applications to use a configuration file in the programming language or to be fed a declaration of a string to be parsed. A common practice is to broadcast the basic application in-band and have it look up any changeable configuration data from either a separate ‘dynamic’ carousel (updating whenever the content changes) or over the network. Fortunately, both methods of fetching a file are modeled by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NetRequest&lt;/code&gt; object in the JavaScript API. In the below example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;configNROnStart&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;configNROnCancel&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;configNROnError&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;configNROnLoad&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;configNROnDone&lt;/code&gt; are functions called as event handlers.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;function loadConfig() {
	configNR = new NetRequest();
	configNR.url = &quot;http://www.example.com/config.js&quot;;
	configNR.cache = false;
	configNR.onstart = configNROnStart;
	configNR.oncancel = configNROnCancel;
	configNR.onerror = configNROnError;
	configNR.onload = configNROnLoad; // do something with response body
	configNR.ondone = configNROnDone;

	menuDataNR.fetch();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;dynamically-updating-resources-at-runtime&quot;&gt;Dynamically updating resources at runtime&lt;/h2&gt;

&lt;p&gt;Another useful feature is timers. These work like in any older browser – calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var t = setTimeout(&quot;doSomething()&quot;, 5000);&lt;/code&gt; will trigger the string &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;doSomething()&lt;/code&gt; to be evaluated asynchronously after 5 seconds. Calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clearTimeout(t)&lt;/code&gt; cancels it. The only caveat with timers is that the first argument must be a string to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval&lt;/code&gt;; it does not accept a function.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var world = new World();
var t = setTimout(&quot;world.hello()&quot;, 5000);
clearTimeout(t);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Together, NetRequests and Timers enable us to poll for an updating resource on an interval.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var configNROnloadCallback;

function configNROnLoad(event) {
	configNROnloadCallback(event.textData);
}

function loadConfig(callback) {
	configNROnloadCallback = callback;
	configNR = new NetRequest();
	configNR.url = &quot;http://example.com/config.js&quot;;
	configNR.cache = false;
	configNR.onstart = configNROnStart;
	configNR.oncancel = configNROnCancel;
	configNR.onerror = configNROnError;
	configNR.onload = configNROnLoad;
	configNR.ondone = configNROnDone;

	menuDataNR.fetch();
}

var configReloadTimer = setTimeout(
	&quot;reloadConfig();&quot;, 15000);

function reloadConfig() {
	loadConfig(loadConfig);
}

function loadConfig(config) {
	// TODO: do something with config

	// reset the timer
	configReloadTimer = setTimeout(
		&quot;reloadConfig();&quot;, 15000);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;That concludes our whirlwind tour of the Liberate platform. I have demonstrated the major interactive software building blocks on non-Tivo cable TV boxes in the UK. We’re now doing more complex things with the platform, such as tuning to TV channels and switching out alternative audio tracks, while periodically fetching configuration updates and updating on-screen assets.&lt;/p&gt;

&lt;p&gt;I deliberately haven’t discussed much of the back-end infrastructure that bridges the gap from a web server to the broadcast transport stream. There is a large stack of legacy proprietary software behind the Liberate platform, compiling resources into transport streams and generating announcements so the set-top-box knows what content to run and make available to applications. The exact nature of the back-end is a bit more sensitive than the software environment and capabilities described above.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Spring Annoyances and the Trouble with Big Frameworks</title>
<link href="http://iangilham.com/2015/07/21/spring-annoyance.html" rel="alternate"/>
<updated>2015-07-21T00:00:00+00:00</updated>
<id>http://iangilham.com/2015/07/21/spring-annoyance.html</id>



<content type="html">&lt;p&gt;I’m going to pick on Spring a lot in this post because it has caused me the most frustration in the last few months, but the same arguments can be applied to many large and ungainly frameworks/libraries. This rant was sparked by trying to upgrade a production application from &lt;a href=&quot;http://projects.spring.io/spring-boot/&quot;&gt;Spring Boot&lt;/a&gt; 1.1 to 1.2. It didn’t work; it didn’t tell me anything useful about why it didn’t work; and the &lt;a href=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.2-Release-Notes&quot;&gt;upgrade notes&lt;/a&gt; said nothing about the parts of the framework which are now completely broken (hint: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ErrorController&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;There are many frameworks from massive to micro in the land of Java development. Spring is perhaps the largest and most mature of these. It provides libraries for just about everything these days with the promise that the many layers of magic should work together without too much developer pain.&lt;/p&gt;

&lt;p&gt;But therein lies the problem. Spring is so large and fragmented that trying to use a few different Spring libraries together often exposes obscure compatibility problems. Sometimes things just work, but often the developer has to micro-manage the exact combination of specific library versions of their various dependencies in order to avoid bugs and rage-inducing compatibility errors.&lt;/p&gt;

&lt;p&gt;Spring Boot steps in to solve this problem, repackaging many layers of Spring libraries and their dependencies as a single curated collection that works together, at least in theory. For the most part, Spring boot saves a lot of pain, but it is still subject to the same murderous upgrade path as the rest of Spring. The drill goes as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Change the dependency version in the build file.&lt;/li&gt;
  &lt;li&gt;Compile and run all the tests.&lt;/li&gt;
  &lt;li&gt;Swear loudly when it all blows up.&lt;/li&gt;
  &lt;li&gt;Scour the release notes for the problem. Find nothing useful.&lt;/li&gt;
  &lt;li&gt;Scream bloody murder at the Spring maintainers for breaking the world without documenting it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With time and effort, these backwards compatibility issues can always be worked around, but there comes a point when I have to ask if it is worth the trouble. The JDK, such as it is, always maintains backward compatibility and all the parts work together in the same release. Spring’s backward compatibility is shoddy at best and it can take a week to get two simple component libraries to work together.&lt;/p&gt;

&lt;p&gt;Despite its merits, Spring Boot only seems to put lipstick on the pig while failing to address the underlying problems with Spring’s many interdependent and frequently unusable libraries. I appreciate that the project tries to make Spring usable again. The frustration comes from it getting close enough to build a product with but not close enough to maintain said product without considerable effort.&lt;/p&gt;

&lt;p&gt;In my own travels I’m starting to appreciate more the way JavaScript frameworks are going, building mini libraries for different tasks and letting developers pick and choose between them. Spring was once supposed to offer something similar, but has since grown into a many-headed hydra of cyclically interdependent magic boxes with inconsistent documentation and a ‘throw it away and start again’ upgrade path. Good application design will attempt to separate most of what the app does from the technology used to build it, but there is only so far this can go before the level of abstraction gets silly. Spring Boot can both help and hinder here, depending on how heavily it is relied upon and which layer of APIs the developer uses.&lt;/p&gt;

&lt;p&gt;I look forward to the day when upgrading the technologies underlying an application is as simple as changing the dependency version numbers. For anything built with a big, complex framework that day has not yet come.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Using Rubygems to Build RPM Packages</title>
<link href="http://iangilham.com/2015/01/19/using-rubygems-to-build-rpm-packages.html" rel="alternate"/>
<updated>2015-01-19T00:00:00+00:00</updated>
<id>http://iangilham.com/2015/01/19/using-rubygems-to-build-rpm-packages.html</id>



<content type="html">&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The examples in this post were ripped out of a real production project, simplified and renamed
where appropriate. I have not tested them in their current state.&lt;/p&gt;

&lt;p&gt;I recently did a bit of work to package a simple static website as an RPM to make it easier to manage
versions and deploy automatically. The site is built with &lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; and &lt;a href=&quot;https://rubygems.org/&quot;&gt;gem&lt;/a&gt; dependency
management is handled by &lt;a href=&quot;http://bundler.io/&quot;&gt;bundler&lt;/a&gt;. I ran into a few challenges using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundler&lt;/code&gt; from the
specfile so it seemed like a good idea to document the process here.&lt;/p&gt;

&lt;p&gt;The basic project layout looks like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root/
    webapp/
        _includes/
            app.js
        _layouts/
            main.html
        _config.yml
        Gemfile
        index.html
    Makefile
    webapp.spec
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The build process for the Jekyll site is as follows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd webapp
gem install bundler
bundle install
bundle exec jekyll build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I used a Makefile to drive the build. Here’s a simplified version of it sufficient for building
the Jekyll site:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;NAME = webapp

# important files and directories
WEBAPPDIR = webapp
SITEDIR = $(WEBAPPDIR)/target
SPECFILE = $(NAME).spec

.PHONY: default all site clean

default: site
all: site

site: $(SITEDIR)

clean:
	@echo &quot;==== making clean&quot;
	rm -rf $(WEBAPPDIR)/target
	rm -f $(WEBAPPDIR)/Gemfile.lock
	@echo &quot;==== making clean done&quot;

$(SITEDIR):
	@echo &quot;==== making jekyll site&quot;
	cd $(WEBAPPDIR) &amp;amp;&amp;amp; bundle install
	cd $(WEBAPPDIR) &amp;amp;&amp;amp; bundle exec jekyll build
	@echo &quot;==== making jekyll site done&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;building-the-rpm&quot;&gt;Building the RPM&lt;/h3&gt;

&lt;p&gt;I used the Makefile to create an RPM build root and copy the appropriate files in. This requires a few more
targets to generate the intermediate files and the final package. I also added the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VERSION&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RELEASE&lt;/code&gt;
variables to pass into rpmbuild later, making it a little simpler to control versioning from one
file in the project root.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;NAME = webapp
VERSION = 1.0
RELEASE = 1

# important files and directories
WEBAPPDIR = webapp
SITEDIR = $(WEBAPPDIR)/target
SPECFILE = $(NAME).spec
RPMBUILDDIR = $(CURDIR)/rpmbuild
SPECSDIR = $(RPMBUILDDIR)/SPECS
SOURCESDIR = $(RPMBUILDDIR)/SOURCES
BUILDDIR = $(RPMBUILDDIR)/BUILD
SRPMSDIR = $(RPMBUILDDIR)/SRPMS
RPMSDIR = $(RPMBUILDDIR)/RPMS/noarch
SPEC = $(SPECSDIR)/$(SPECFILE)
TARBALL = $(SOURCESDIR)/$(NAME).tgz
BUILDDIRS= $(SPECSDIR) $(SOURCESDIR) $(BUILDDIR) $(SRPMSDIR) $(RPMSDIR)

RPM_BASENAME = $(NAME)-$(VERSION)-$(RELEASE)
RPM = $(RPMSDIR)/$(RPM_BASENAME).rpm

.PHONY: default all site clean siteclean dist

default: dist
all: dist

site: $(SITEDIR)

clean: siteclean
	@echo &quot;==== making clean&quot;
	rm -rf $(RPMBUILDDIR)
	@echo &quot;==== making clean done&quot;

siteclean:
	@echo &quot;==== making siteclean&quot;
	rm -rf $(WEBAPPDIR)/target
	rm -f $(WEBAPPDIR)/Gemfile.lock
	@echo &quot;==== making siteclean done&quot;

dist: $(RPM)

$(SITEDIR):
	@echo &quot;==== making jekyll site&quot;
	cd $(WEBAPPDIR) &amp;amp;&amp;amp; bundle install
	cd $(WEBAPPDIR) &amp;amp;&amp;amp; bundle exec jekyll build
	@echo &quot;==== making jekyll site done&quot;

$(RPM): $(TARBALL) $(SPEC) $(BUILDDIRS)
	rpmbuild -v -ba $(SPEC) \
	  --define=&quot;_topdir $(RPMBUILDDIR)&quot; \
	  --define=&quot;_version $(VERSION)&quot; \
	  --define=&quot;_release $(RELEASE)&quot;

$(SPEC): $(SPECSDIR) $(SPECFILE)
	@echo &quot;==== making specfile&quot;
	cp $(SPECFILE) $@
	@echo &quot;==== making specfile done&quot;

$(TARBALL): $(SOURCESDIR)
	@echo &quot;==== making tarball&quot;
	tar -czf $@ $(WEBAPPDIR)
	@echo &quot;==== making tarball done&quot;

$(BUILDDIRS): $(RPMBUILDDIR)
	mkdir -p $@

$(RPMBUILDDIR):
	mkdir -p $@
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That should be enough to get rpmbuild to run. The hard part was getting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundler&lt;/code&gt; to run in the context
of the specfile. Fortunately, the package &lt;strong&gt;rubygems-devel&lt;/strong&gt; provides the necessary macros to support this
use case:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;%global bundler bundler-1.7.11
%global url_bundler https://rubygems.org/downloads/%{bundler}.gem

Name: webapp
Summary: Example webapp
Version: %{?_version}
Release: %{?_release}
Group: Applications/Internet
Vendor: Ian Gilham
License: CC BY 3.0 (http://creativecommons.org/licenses/by/3.0/)
Buildarch: noarch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
Source0: %{name}.tgz
BuildRequires: ruby
BuildRequires: ruby-devel
BuildRequires: rubygems
BuildRequires: rubygems-devel
BuildRequires: gcc
BuildRequires: gcc-c++
BuildRequires: wget

%description
Example web app

%prep
%setup -n webapp

%build
wget %{url_bundler}
%gem_install -n %{bundler}.gem

export PATH=$PATH:./usr/bin
export GEM_PATH=./usr/lib/ruby/gems/1.8/
export GEM_HOME=$GEM_PATH
bundle install
bundle exec jekyll build

%install
INSTALL_PATH=&quot;home/server/webapp&quot;
mkdir -p &quot;%{buildroot}/${INSTALL_PATH}&quot;
cp _site/index.html &quot;%{buildroot}/${INSTALL_PATH}/&quot;

%files
%defattr(644,dcabwww,dcabwww,755)
 &quot;/home/server/webapp/index.html&quot;

%clean
rm -rf %{buildroot}

%post
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuildRequires&lt;/code&gt; dependencies had to be explicit to work in a chroot environment. ruby-devel, gcc and
gcc-c++ are required to build Ruby native gems. wget is used to download a gem for local installation
during RPM build. rubygems-devel provides a few useful rpmbuild macros needed to glue the build system
together.&lt;/p&gt;

&lt;p&gt;I knew from the &lt;a href=&quot;https://fedoraproject.org/wiki/Packaging:Ruby?rd=Packaging/Ruby&quot;&gt;Fedora Project Documentation&lt;/a&gt; that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%gem_install&lt;/code&gt; macro would allow me to
install the prerequisite bundler gem locally, but it took a few attempts to figure out where it was installed
and how to set up the local Ruby environment to use it correctly. This is particularly important when
considering how to run the build in &lt;a href=&quot;http://fedoraproject.org/wiki/Projects/Mock&quot;&gt;mock&lt;/a&gt;. In the end this was accomplished with the following
snippet:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export PATH=$PATH:./usr/bin
export GEM_PATH=./usr/lib/ruby/gems/1.8/
export GEM_HOME=$GEM_PATH
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;using-mock-to-isolate-rpmbuild-from-the-host-environment&quot;&gt;Using mock to isolate rpmbuild from the host environment&lt;/h3&gt;

&lt;p&gt;At this point I had a workable build system, so the last step was to run it in our continuous integration
environment without polluting the build agent. I used mock to isolate the package build-time dependencies
from the host machine by running the RPM build inside a chroot jail.&lt;/p&gt;

&lt;p&gt;With a working build, it is fairly easy to get mock working by adding a few things to the Makefile:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SRPM = $(SRPMSDIR)/$(RPM_BASENAME).src.rpm

# executables and their options
MOCK = mock
MOCK_OPTS = -q -D &quot;_version $(VERSION)&quot; -D &quot;_release $(RELEASE)&quot;
RPMBUILD_OPTS = --define=&quot;_topdir $(RPMBUILDDIR)&quot; \
  --define=&quot;_version $(VERSION)&quot; \
  --define=&quot;_release $(RELEASE)&quot;

# ... skipped

clean: siteclean
	@echo &quot;==== making clean&quot;
	rm -rf $(RPMBUILDDIR)
	mock -q --clean
	@echo &quot;==== making clean done&quot;

# ... skipped

$(SRPM): $(TARBALL) $(SPEC) $(BUILDDIRS) siteclean
	@echo &quot;==== making source rpm&quot;
	rpmbuild -bs $(SPEC) $(RPMBUILD_OPTS)
	@echo &quot;==== making source rpm done&quot;

$(RPM): $(SRPM)
	@echo &quot;==== making binary rpm&quot;
	$(MOCK) $(MOCK_OPTS) --init
	$(MOCK) $(MOCK_OPTS) --installdeps $&amp;lt;
	$(MOCK) $(MOCK_OPTS) --offline --resultdir $(RPMSDIR) --rebuild $&amp;lt;
	@echo &quot;==== making binary rpm done&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On the continuous integration server, I configured the build to run
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make RELEASE=$BUILD_NUMBER clean dist&lt;/code&gt; to make it easy to see where each version of the package came
from. The top-level package version is edited manually in the Makefile and corresponds to our own
tagging and versioning conventions.&lt;/p&gt;

&lt;p&gt;The final complete Makefile follows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;NAME = webapp
VERSION = 1.0
RELEASE = 1

# important files and directories
WEBAPPDIR = webapp
SITEDIR = $(WEBAPPDIR)/target
SPECFILE = $(NAME).spec
RPMBUILDDIR = $(CURDIR)/rpmbuild
SPECSDIR = $(RPMBUILDDIR)/SPECS
SOURCESDIR = $(RPMBUILDDIR)/SOURCES
BUILDDIR = $(RPMBUILDDIR)/BUILD
SRPMSDIR = $(RPMBUILDDIR)/SRPMS
RPMSDIR = $(RPMBUILDDIR)/RPMS/noarch
SPEC = $(SPECSDIR)/$(SPECFILE)
TARBALL = $(SOURCESDIR)/$(NAME).tgz
BUILDDIRS= $(SPECSDIR) $(SOURCESDIR) $(BUILDDIR) $(SRPMSDIR) $(RPMSDIR)

RPM_BASENAME = $(NAME)-$(VERSION)-$(RELEASE)
SRPM = $(SRPMSDIR)/$(RPM_BASENAME).src.rpm
RPM = $(RPMSDIR)/$(RPM_BASENAME).rpm

# executables and their options
MOCK = mock
MOCK_OPTS = -q -D &quot;_version $(VERSION)&quot; -D &quot;_release $(RELEASE)&quot;
RPMBUILD_OPTS = --define=&quot;_topdir $(RPMBUILDDIR)&quot; \
  --define=&quot;_version $(VERSION)&quot; \
  --define=&quot;_release $(RELEASE)&quot;

.PHONY: default all site clean siteclean dist

default: dist
all: dist

site: $(SITEDIR)

clean: siteclean
	@echo &quot;==== making clean&quot;
	rm -rf $(RPMBUILDDIR)
	mock -q --clean
	@echo &quot;==== making clean done&quot;

siteclean:
	@echo &quot;==== making siteclean&quot;
	rm -rf $(WEBAPPDIR)/target
    rm -f $(WEBAPPDIR)/Gemfile.lock
	@echo &quot;==== making siteclean done&quot;

dist: $(RPM)

$(SITEDIR):
	@echo &quot;==== making jekyll site&quot;
	cd $(WEBAPPDIR) &amp;amp;&amp;amp; bundle install
	cd $(WEBAPPDIR) &amp;amp;&amp;amp; bundle exec jekyll build
	@echo &quot;==== making jekyll site done&quot;

$(SRPM): $(TARBALL) $(SPEC) $(BUILDDIRS) siteclean
	@echo &quot;==== making source rpm&quot;
	rpmbuild -bs $(SPEC) $(RPMBUILD_OPTS)
	@echo &quot;==== making source rpm done&quot;

$(RPM): $(SRPM)
	@echo &quot;==== making binary rpm&quot;
	$(MOCK) $(MOCK_OPTS) --init
	$(MOCK) $(MOCK_OPTS) --installdeps $&amp;lt;
	$(MOCK) $(MOCK_OPTS) --offline --resultdir $(RPMSDIR) --rebuild $&amp;lt;
	@echo &quot;==== making binary rpm done&quot;

$(SPEC): $(SPECSDIR) $(SPECFILE)
	@echo &quot;==== making specfile&quot;
	cp $(SPECFILE) $@
	@echo &quot;==== making specfile done&quot;

$(TARBALL): $(SOURCESDIR)
	@echo &quot;==== making tarball&quot;
	tar -czf $@ $(WEBAPPDIR)
	@echo &quot;==== making tarball done&quot;

$(BUILDDIRS): $(RPMBUILDDIR)
	mkdir -p $@

$(RPMBUILDDIR):
	mkdir -p $@
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Spring Boot Web MVC Testing</title>
<link href="http://iangilham.com/2014/12/11/spring-boot-mvc-testing.html" rel="alternate"/>
<updated>2014-12-11T00:00:00+00:00</updated>
<id>http://iangilham.com/2014/12/11/spring-boot-mvc-testing.html</id>



<content type="html">&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: All the code here is licensed under the
&lt;a href=&quot;http://www.apache.org/licenses/LICENSE-2.0&quot;&gt;Apache License version 2.0&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: The information and in this post has been adapted back into the &lt;a href=&quot;http://spring.io/guides/gs/spring-boot/&quot;&gt;Getting Started Guide&lt;/a&gt;. I recommend reading the guide, as it is more complete and easier to follow.&lt;/p&gt;

&lt;p&gt;For the last few weeks I’ve been using &lt;a href=&quot;http://projects.spring.io/spring-boot/&quot;&gt;Spring Boot&lt;/a&gt; to build a
&lt;a href=&quot;http://en.wikipedia.org/wiki/Representational_state_transfer&quot;&gt;REST&lt;/a&gt; application for an internal service. I started with the
&lt;a href=&quot;http://spring.io/guides/gs/spring-boot/&quot;&gt;Getting Started Guide&lt;/a&gt; and built it up from there. Once I
got the application in the guide working, I started to look at how to write
tests for such an application to drive further development.&lt;/p&gt;

&lt;p&gt;I started by forking the &lt;a href=&quot;https://github.com/spring-guides/gs-spring-boot&quot;&gt;guide’s source code&lt;/a&gt; sample
&lt;a href=&quot;https://github.com/igilham/gs-spring-boot&quot;&gt;on GitHub&lt;/a&gt; and creating the requisite test source directories
following the usual Maven conventions.&lt;/p&gt;

&lt;p&gt;For reference, the web endpoint in the sample application can be found in class
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HelloController&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;package hello;

// imports

@RestController
public class HelloController {

    @RequestMapping(&quot;/hello&quot;)
    public String index() {
        return &quot;Greetings from Spring Boot!&quot;;
    }

}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The application just returns a document containing a plain string when clients
request the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/hello&lt;/code&gt; endpoint.&lt;/p&gt;

&lt;h2 id=&quot;unit-testing&quot;&gt;Unit testing&lt;/h2&gt;

&lt;p&gt;Getting set up for testing requires a
dependency to be added to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pom.xml&lt;/code&gt; as follows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;spring-boot-starter-test&amp;lt;/artifactId&amp;gt;
    &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This gives us JUnit and some other stuff useful for working with Spring
applications.&lt;/p&gt;

&lt;p&gt;For the test itself, we can hit the web endpoint defined by the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HelloController&lt;/code&gt; class without spinning up a Servlet container and the rest
of the application. This allows us to mock out any dependencies not under
test (none for the example application) and verify the behaviour of the
controller.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;package hello;

// imports

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@ContextConfiguration(classes = MockServletContext.class)
@WebAppConfiguration
public class HelloControllerTest {
    private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        mvc = MockMvcBuilders.standaloneSetup(
                new HelloController())
            .build();
    }

    @Test
    public void getHello() throws Exception {
        mvc.perform(MockMvcRequestBuilders
            .get(&quot;/hello&quot;)
            .accept(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andExpect(content().string(
                is(&quot;Greetings from Spring Boot!&quot;)));
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The annotations on the test class orchestrate the setup of the application
context here. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@SpringApplicationConfiguration&lt;/code&gt; tells Spring to load the
application context from the application’s normal entry point, building any
required beans etc. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@WebAppConfiguration&lt;/code&gt; sets up some machinery required to
enable testing of web endpoints. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ContextConfiguration&lt;/code&gt; adds a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Configuration&lt;/code&gt;
class to the context to enable some more beans, in this case to provide a mock
Java Servlet container.&lt;/p&gt;

&lt;p&gt;The test itself just uses Spring’s testing library to call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET /hello&lt;/code&gt; and
verifies that the returned value is what was expected. There are more complex
ways to assert on the result of hitting an endpoint but this is sufficient for
the sample application.&lt;/p&gt;

&lt;h2 id=&quot;integration-testing&quot;&gt;Integration testing&lt;/h2&gt;

&lt;p&gt;Maven does not enable the integration testing build phase by default so we have
to add the failsafe plugin to make it work:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-failsafe-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.18&amp;lt;/version&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;integration-test&amp;lt;/goal&amp;gt;
                &amp;lt;goal&amp;gt;verify&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With the failsafe plugin in place, maven will run our integration test.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;package hello;

// imports

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@IntegrationTest({&quot;server.port=9090&quot;})
public class HelloControllerIT {
    private String base;
    private RestTemplate template;

    @Before
    public void setUp() throws Exception {
        this.base = &quot;http://localhost:9090/hello&quot;;
        template = new TestRestTemplate();
    }

    @Test
    public void getHello() throws Exception {
        ResponseEntity&amp;lt;String&amp;gt; response =
            template.getForEntity(base, String.class);
        assertThat(response.getBody(),
            is(&quot;Greetings from Spring Boot!&quot;));
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The integration test is very similar to the unit test but it has a different
runtime lifecycle. This time, the application will be run in an embedded Servlet
container with all its dependencies before the test code is called. The
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@IntegrationTest&lt;/code&gt; annotation tells Spring to run the full application stack.&lt;/p&gt;

&lt;p&gt;Integration testing like this is unnecessary for this simple application but it
can be useful when a black-box test of the entire application is required. I
have found this method particularly useful for tests that touch a database
tier, as it is possible to customise the beans in play for each integration test
class, enabling database compatibility testing where more than one vendor is
supported, or enabling the tests to run against a local instance of a
distributed NoSQL database.&lt;/p&gt;

&lt;p&gt;My code can be found &lt;a href=&quot;https://github.com/igilham/gs-spring-boot&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">A simple interactive TV slate in MHEG</title>
<link href="http://iangilham.com/2014/03/27/mheg-slate.html" rel="alternate"/>
<updated>2014-03-27T00:00:00+00:00</updated>
<id>http://iangilham.com/2014/03/27/mheg-slate.html</id>



<content type="html">&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; All code examples in this post are licensed under a
&lt;a href=&quot;http://github.com/igilham/mheg-slate/LICENSE&quot;&gt;BSD style license&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are a few players in interactive television in the UK, each using different technology to
build interactive experiences. Freeview and Freesat both use profiles of
&lt;a href=&quot;http://en.wikipedia.org/wiki/MHEG-5&quot;&gt;MHEG-5&lt;/a&gt; as the programming language and runtime environment.
MHEG-5 is a fairly unusual language in that it uses an event-based programming model, with all state
declared outside the scope of the events.&lt;/p&gt;

&lt;p&gt;As far as programming languages go, MHEG-5 makes a developer’s life difficult. There are no symbolic
names so we have to refer to everything by an integer object ID. There are no data structures, so
arrays have to be implemented manually by iterating on the object IDs and being very careful about
where to stop. Links, the functional blocks of imperative code, can fire asynchronously and have no
local state so care must be taken to avoid race conditions. There are only a few basic library
calls, referred to as “resident programs”, which enable basic string manipulation and limited interaction
with the set-top-box. There isn’t even an &lt;strong&gt;if&lt;/strong&gt; statement, so conditional behaviour has to be
implemented as a convoluted &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Test&lt;/code&gt; instruction which then fires one of two &lt;em&gt;links&lt;/em&gt; for the &lt;em&gt;true&lt;/em&gt; and
&lt;em&gt;false&lt;/em&gt; cases. To program MHEG-5 is to live in &lt;em&gt;interesting times&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Fortunately, there are some useful tools for developers. The main one I use is
&lt;a href=&quot;http://sourceforge.net/projects/mheg-plus/&quot;&gt;MHEG Plus&lt;/a&gt;. MHEG Plus includes a compiler for a
superset of the core language which allows developers to write better code faster. There are a lot
of useful tools in MHEG Plus, like symbolic variable names, conditional statements, loops, macros,
and simplified syntax. The compiler also has some useful error messages for when mistakes are made
that helps to speed up the development-test cycle considerably. The project also includes an
emulator that implements an MHEG-5 runtime engine as a Java GUI application. It isn’t perfectly
accurate but it’s a lot quicker to get off the ground with an emulator than by having to construct a
&lt;a href=&quot;http://en.wikipedia.org/wiki/DSMCC&quot;&gt;DSMCC carousel&lt;/a&gt;, multiplex it into a DVB transport stream, then modulate it and play it into a set-top-box for testing.&lt;/p&gt;

&lt;p&gt;For this post, I have written a simple &lt;strong&gt;Hello World&lt;/strong&gt; application in MHEG Plus. MHEG plus gives us
the ability to import headers containing macros and constants, so let’s first define some useful
constants:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// src/constants.h.mheg+
{:IntegerConst SCREEN_WIDTH :ConstValue 720}
{:IntegerConst SCREEN_HEIGHT :ConstValue 576}

{:OctetStringConst FONT_ATTR_HEADING :ConstValue &quot;plain.36.42.0&quot;}
{:OctetStringConst FONT_ATTR_BODY :ConstValue &quot;plain.26.32.0&quot;}

{:OctetStringConst COLOUR_BLACK :ConstValue &apos;=00=00=00=00&apos;}
{:OctetStringConst COLOUR_WHITE :ConstValue &apos;=FF=FF=FF=00&apos;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;MHEG-5 applications begin with a file containing the definition of the application object. This file
sits in the root of the carousel (the service gateway) and is either called &lt;em&gt;startup&lt;/em&gt; or simply &lt;em&gt;a&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// src/a
// application startup file
// application startup file

import(constants.h.mheg+)

{:Application
	( &apos;/a&apos; 0 )
	:Items (
		{:Link lnkMain
			:EventSource 0          // Check this application...
			:EventType IsRunning    // ... for the IsRunning event
			:LinkEffect (
				:TransitionTo(( &apos;~/slate.asn&apos; 0 ) )
			)
		}
	)
	// basic defaults
	:BackgroundColour COLOUR_BLACK
	:TextCHook 10
	:TextColour COLOUR_WHITE
	:Font &quot;rec://font/uk1&quot;
	:FontAttributes FONT_ATTR_BODY
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The application object contains some default style values and at least a basic link, listening for
the application’s &lt;strong&gt;IsRunning&lt;/strong&gt; event. This link will be fired when you tune to a channel
with this application mapped in its DVB Service Information, and the set-top-box has finished
loading and parsing the code. There is only one statement in the body of this link, an instruction
to transition to the slate scene. So let’s define a slate scene:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// src/slate.mheg+
import(constants.h.mheg+)

{:Scene
	( &quot;~/slate.asn&quot; 0 )
	:Items
	(
		{:Rectangle rectBackground
			:OrigBoxSize SCREEN_WIDTH SCREEN_HEIGHT
			:OrigPosition 0 0
			:OrigRefLineColour COLOUR_BLACK
			:OrigRefFillColour COLOUR_BLACK
		}

		{:Text txtHeading
			:OrigContent &quot;Hello World!&quot;
			:OrigBoxSize SCREEN_WIDTH 50
			:OrigPosition 0 [SCREEN_HEIGHT / 3]
			:FontAttributes FONT_ATTR_HEADING
			:TextColour COLOUR_WHITE
			:HJustification centre
		}
		
		{:Text txtExit
			:OrigContent &quot;Press RED to exit&quot;
			:OrigBoxSize SCREEN_WIDTH 30
			:OrigPosition 0 [(SCREEN_HEIGHT / 3) + 60]
			:FontAttributes FONT_ATTR_BODY
			:TextColour COLOUR_WHITE
			:HJustification centre
		}

		// Press RED to quit
		{:Link
			lnkKeyBlue
			:EventSource 0
			:EventType UserInput
			:EventData KeyRed
			:LinkEffect (
				:Quit()
			)
		}
	)
	:InputEventReg 3
	:SceneCS SCREEN_WIDTH SCREEN_HEIGHT
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There is a bit more going on in the slate scene. First we import the symbolic constants as before.
Next we define a scene, give it a name, and populate it with some &lt;strong&gt;items&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This scene declares a &lt;em&gt;Rectangle&lt;/em&gt; to fill with the background colour and two &lt;em&gt;Text&lt;/em&gt; objects
containing hard-coded strings. That would be enough for a &lt;strong&gt;Hello world&lt;/strong&gt; example, but for
completeness I have also included a link listening for the Red key on the remote control,
which simply causes the application to exit. Strictly speaking, a slate should not have exit
behaviour, as that would defeat its purpose of hiding any video decoded by the receiver, but it’s
a good example of how to enable basic user interaction via the remote control.&lt;/p&gt;

&lt;p&gt;The complete code, documentation, build system and license are
&lt;a href=&quot;https://github.com/igilham/mheg-slate/&quot;&gt;available on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Exploring Software Architecture with OpenCaster and Golang</title>
<link href="http://iangilham.com/2013/10/13/Exploring-software-architecture-with-OpenCaster-and-Golang.html" rel="alternate"/>
<updated>2013-10-13T00:00:00+00:00</updated>
<id>http://iangilham.com/2013/10/13/Exploring-software-architecture-with-OpenCaster-and-Golang.html</id>



<content type="html">&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; All code examples in this post are licensed under the &lt;a href=&quot;http://www.gnu.org/licenses/gpl-2.0.html&quot;&gt;GPL version 2&lt;/a&gt; (or later). My code is a derivative work of OpenCaster.&lt;/p&gt;

&lt;p&gt;Playing out MPEG transport streams is a fairly complex affair. At the office, we have our own in-house solution comprising SI generators, a software multiplexer and DSMCC carousel playout tools etc. covering the four major boradcast television platforms in the UK. In an effort to understand how all the moving parts slot together, I’ve been reading through some of the code and exploring some tools from the open source world as well. One open source tool, &lt;a href=&quot;http://www.avalpa.com/the-key-values/15-free-software/33-opencaster&quot;&gt;OpenCaster&lt;/a&gt;, has caught my attention for its simple, old-school software architecture.&lt;/p&gt;

&lt;p&gt;OpenCaster is distributed as a collection of small utilities written in C. I haven’t dug into what they all do yet, but the idea is pretty simple. Each tool has one job and does it well. Communication between tools occurs via pipes, typically named FIFOs.&lt;/p&gt;

&lt;p&gt;As an example, let’s say you want to broadcast a looped audio/video/data transport stream from a file on disk. We create a named pipe to pump the looped packets into and use a tool named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tsloop&lt;/code&gt; to read packets from the source file, write them into the pipe, and loop when it runs out of input.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# given sample.ts
mkfifo loop.ts
tsloop sample.ts &amp;gt; loop.ts &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We might want to correct the &lt;abbr title=&quot;Program Clock Reference&quot;&gt;PCR&lt;/abbr&gt; timestamp in the transport stream, so we use another tool to read from our pipe, correct the PCR, then write out to another pipe.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mkfifo corrected-pcr.ts
tsstamp loop.ts 13271000 &amp;gt; corrected-pcr.ts &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If we assume that we have done enough for the stream to be correctly decoded by a set top box (or &lt;a href=&quot;http://www.videolan.org/&quot;&gt;VLC Media Player&lt;/a&gt;), we can now hook up a third tool to broadcast the PCR-corrected looped transport stream over a supported connection. OpenCaster supplies a few different broadcast tools so I’ll just rip an example from their user manual. This tool sends the stream out over a supported RF card.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tsrfsend myfirstfifo.ts -mt OFDM -mC QAM16 -mG 1/4 -mc 2/3 -mf 578
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we have seen enough of the OpenCaster toolset to get the gist of how the software architecture works. Each tool filters a stream read from a file (really a named pipe), performs some modification, then writes it out for the next step in the chain to deal with. This is a perfect example of the Unix philosophy of building small, composable tools. The only thing that makes OpenCaster’s architecture unusual is that the tools filter MPEG transport stream packets rather than text strings, but the result is much the same.&lt;/p&gt;

&lt;h2 id=&quot;enter-go&quot;&gt;Enter Go&lt;/h2&gt;

&lt;p&gt;For a while now I’ve had a fascination with Google’s &lt;a href=&quot;http://golang.org/&quot;&gt;Go programming language&lt;/a&gt;. It’s like C but easier to write, more type-safe, more modular, and in some ways even simpler, although it does make some of C’s more (potentially) dangerous features much harder to use.&lt;/p&gt;

&lt;p&gt;I thought it might be a fun little challenge to reimplement some of OpenCaster in Go and see how the Go version differed from the C original. I have started with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tsloop&lt;/code&gt;, a relatively simple application for looping a file-based transport stream into a pipe.&lt;/p&gt;

&lt;p&gt;OpenCaster’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tsloop&lt;/code&gt; program is just a great big main function in C with no headers. It uses a couple of standard and POSIX library functions but is otherwise self-contained. While this may be efficient, I find it annoying to read through a giant wall of code with various duplicated bits that could be factored out easily.&lt;/p&gt;

&lt;p&gt;I started by writing a straight port of the C code, changing to Go idioms where it made sense but keeping true to the original for the most part.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;package main

import (
	&quot;bytes&quot;
	&quot;encoding/binary&quot;
	&quot;flag&quot;
	&quot;fmt&quot;
	&quot;os&quot;
	&quot;syscall&quot;
)

const (
	tsPacketSize = 188
	maxPid       = 8192
)

// PID table for the continuity counter of the TS packets
type ccTable [maxPid]byte

var (
	pidCcTable      ccTable
	previousCcTable ccTable
	openFile        = 0
)

func main() {
	flag.Parse()
	if flag.NArg() &amp;gt;= 1 {
		openFile = 1
		if tsFile, err := os.Open(flag.Arg(openFile)); err == nil {
			processFile(tsFile)
		} else {
			fmt.Fprintf(os.Stderr,
				&quot;tsloop: unable to open file %s\n&quot;,
				flag.Arg(1))
			os.Exit(1)
		}
	} else {
		fmt.Fprintf(os.Stderr,
			&quot;Usage: &apos;tsloop filename1.ts filename2.ts ... filenameN.ts&apos;\n&quot;)
		os.Exit(1)
	}
}

func initTable(table ccTable) {
	for i, _ := range table {
		table[i] = 0x10
	}
}

func processFile(tsFile *os.File) {
	// initialize tables
	initTable(pidCcTable)
	initTable(previousCcTable)
	packet := make([]byte, tsPacketSize)
	// main loop
	for {
		// read packets
		count, err := tsFile.Read(packet)
		// handle short packet
		if count &amp;lt; tsPacketSize {
			openFile %= flag.NArg()
			openFile += 1
			tsFile.Close()
			initTable(previousCcTable)
			tsFile, err = os.Open(flag.Arg(openFile))
			if err != nil {
				fmt.Fprintf(os.Stderr,
					&quot;Can&apos;t open file %s\n&quot;,
					flag.Arg(openFile))
				os.Exit(1)
			}
			count, err := tsFile.Read(packet)
			if count &amp;lt;= 0 || err != nil {
				os.Exit(1)
			}
		}

		// check packet cc
		buf := bytes.NewBuffer(packet[1:3])
		var pid uint16
		binary.Read(buf, binary.LittleEndian, &amp;amp;pid)
		
		pid = syscall.Ntohs(pid)
		pid = pid &amp;amp; 0x1fff
		if pid &amp;lt; maxPid {
			if pidCcTable[pid] == 0x10 {
				fmt.Fprintf(os.Stderr,
					&quot;new pid entry %d\n&quot;, pid)
				// new stream to track cc
				pidCcTable[pid] = packet[3] &amp;amp; 0x0f
				previousCcTable[pid] = packet[3] &amp;amp; 0x0f
			} else {
				adaptationField := (packet[3] &amp;amp; 0x30) &amp;gt;&amp;gt; 4
				if adaptationField == 0x0 || adaptationField == 0x2 {
					// reserved, no increment
					packet[3] = (pidCcTable[pid] | (packet[3] &amp;amp; 0xf0))
				} else if (adaptationField == 0x1) &amp;amp;&amp;amp;
						((packet[3] &amp;amp; 0x0f) == previousCcTable[pid]) {
					// double packet accepted only once
					packet[3] = (pidCcTable[pid] | (packet[3] &amp;amp; 0xf0))
					previousCcTable[pid] = 0x10
				} else if (adaptationField == 0x3) &amp;amp;&amp;amp; 
						((packet[3] &amp;amp; 0x0f) == previousCcTable[pid]) {
					// double packet accepted only once
					packet[3] = (pidCcTable[pid] | (packet[3] &amp;amp; 0xf0))
					previousCcTable[pid] = 0x10
				} else {
					// increase the cc and restamp
					previousCcTable[pid] = 
						packet[3] &amp;amp; 0x0f
					pidCcTable[pid] = 
						(pidCcTable[pid] + 1) % 0x10
					packet[3] = 
						(pidCcTable[pid] | (packet[3] &amp;amp; 0xf0))
				}
			}
		}

		// write packet
		os.Stdout.Write(packet)
	}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After I had the basic code structure compiling, I sought to simplify by refactoring distinct pieces of behaviour to separate functions, and generally making it easier to read and maintain.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;package main

import (
	&quot;bytes&quot;
	&quot;encoding/binary&quot;
	&quot;flag&quot;
	&quot;fmt&quot;
	&quot;io&quot;
	&quot;os&quot;
	&quot;syscall&quot;
)

const (
	tsPacketSize = 188
	maxPid       = 8192
)

type ccTable [maxPid]byte

var (
	pidCcTable      ccTable
	previousCcTable ccTable
	openFile        = 0
	packet          = make([]byte, tsPacketSize)
)

func main() {
	flag.Parse()
	if flag.NArg() &amp;gt;= 1 {
		if tsFile, err := os.Open(flag.Arg(openFile)); err == nil {
			initTable(pidCcTable)
			initTable(previousCcTable)
			for {
				readPacket(tsFile)
				checkPacketCc()
				os.Stdout.Write(packet)
			}
		} else {
			fmt.Fprintf(os.Stderr,
				&quot;tsloop: unable to open file %s\n&quot;, flag.Arg(1))
			os.Exit(1)
		}
	} else {
		fmt.Fprintf(os.Stderr,
			&quot;Usage: &apos;tsloop filename1.ts filename2.ts ... filenameN.ts&apos;\n&quot;)
		os.Exit(1)
	}
}

// initialize a cc table
func initTable(table ccTable) {
	for i, _ := range table {
		table[i] = 0x10
	}
}

// read a packet from the file(s) provided
// loops onto the next available file on EOF
func readPacket(tsFile *os.File) {
	count, err := tsFile.Read(packet)
	// handle short packet
	if count &amp;lt; tsPacketSize || err == io.EOF {
		openFile %= flag.NArg()
		openFile += 1
		tsFile.Close()
		initTable(previousCcTable)
		tsFile, err = os.Open(flag.Arg(openFile))
		if err != nil {
			fmt.Fprintf(os.Stderr,
				&quot;Can&apos;t open file %s\n&quot;, flag.Arg(openFile))
			os.Exit(1)
		}
		count, err := tsFile.Read(packet)
		if count &amp;lt;= 0 || err != nil {
			os.Exit(1)
		}
	}
}

// extract the 16 bit PID from 2 bytes of the packet.
// Performs some binary magic to make it conform to the correct format.
// Example:
//     pid := extractPid(packet[1:3])
func extractPid(s []byte) (uint16) {
	buf := bytes.NewBuffer(s)
	var pid uint16
	binary.Read(buf, binary.LittleEndian, &amp;amp;pid)
	pid = syscall.Ntohs(pid)
	pid = pid &amp;amp; 0x1fff
	return pid
}

func checkPacketCc() {
	pid := extractPid(packet[1:3])
	if pid &amp;lt; maxPid {
		if pidCcTable[pid] == 0x10 {
			fmt.Fprintf(os.Stderr,
				&quot;new pid entry %d\n&quot;, pid)
			// new stream to track cc
			pidCcTable[pid] = packet[3] &amp;amp; 0x0f
			previousCcTable[pid] = packet[3] &amp;amp; 0x0f
		} else {
			adaptationField := (packet[3] &amp;amp; 0x30) &amp;gt;&amp;gt; 4
			if adaptationField == 0x0 || adaptationField == 0x2 {
				// reserved, no increment
				packet[3] = (pidCcTable[pid] | (packet[3] &amp;amp; 0xf0))
			} else if (adaptationField == 0x1) &amp;amp;&amp;amp; 
					((packet[3] &amp;amp; 0x0f) == previousCcTable[pid]) {
				// double packet accepted only once
				packet[3] = (pidCcTable[pid] | (packet[3] &amp;amp; 0xf0))
				previousCcTable[pid] = 0x10
			} else if (adaptationField == 0x3) &amp;amp;&amp;amp; 
					((packet[3] &amp;amp; 0x0f) == previousCcTable[pid]) {
				// double packet accepted only once
				packet[3] = (pidCcTable[pid] | (packet[3] &amp;amp; 0xf0))
				previousCcTable[pid] = 0x10
			} else {
				// increase the cc and restamp
				previousCcTable[pid] = packet[3] &amp;amp; 0x0f
				pidCcTable[pid] = (pidCcTable[pid] + 1) % 0x10
				packet[3] = (pidCcTable[pid] | (packet[3] &amp;amp; 0xf0))
			}
		}
	}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After some very basic testing, I started to look at how the architecture might be improved. Specifically, I looked at how I might turn a collection of these filter applications into a reusable library of functionality, where a chain of filters could be built up in one process by reading a config file and assembling all the required pieces for broadcast. Obviously, I don’t have all the pieces yet, but it often pays to think about architecture early.&lt;/p&gt;

&lt;p&gt;Go has native support for communicating synchronous processes (CSP) known as &lt;em&gt;goroutines&lt;/em&gt; communicating over &lt;em&gt;channels&lt;/em&gt;, which can be used much like the OpenCaster tools use FIFOs. An MPEG packet is an array (or slice) of 188 bytes. We can easily send a slice of bytes down a channel, so this communication mechanism should suffice nicely.&lt;/p&gt;

&lt;p&gt;In the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tsloop&lt;/code&gt; application, we can fire up a goroutine to read packets from a file (and loop at the end), sending each packet synchronously down a channel. We can then fire up another goroutine to read from that channel, perform some filtering, and send the resulting packet down another channel. The result of the final channel can be fed into another filter or written to standard output for redirection to a file or named pipe as before. Converting the architecture to send data over channels in this way, we end up with something like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;package main

// ... imports, declarations etc.

func main() {
	flag.Parse()
	if flag.NArg() &amp;gt;= 1 {
		if tsFile, err := os.Open(flag.Arg(openFile)); err == nil {
			initTable(pidCcTable)
			initTable(previousCcTable)
			input := make(chan []byte)
			output := make(chan []byte)
			quit := make(chan bool)
			nGoroutines := 3
			go readPackets(tsFile, input, quit)
			go checkPacketsCc(input, output, quit)
			go writePackets(output, quit)
			for i := 0; i &amp;lt; nGoroutines; i++ {
				&amp;lt;- quit
			}
		} else {
			fmt.Fprintf(os.Stderr,
				&quot;tsloop: unable to open file %s\n&quot;, flag.Arg(1))
			os.Exit(1)
		}
	} else {
		fmt.Fprintf(os.Stderr,
			&quot;Usage: &apos;tsloop filename1.ts filename2.ts ... filenameN.ts&apos;\n&quot;)
		os.Exit(1)
	}
}

// ... functions elided to avoid duplication

// read a packet from the file(s) provided
// loops onto the next available file on EOF
func readPackets(tsFile *os.File, input chan []byte, quit chan bool) {
	packet := make([]byte, tsPacketSize)
	for {
		// content of readPacket(*os.File), above
		input &amp;lt;- packet
	}
	quit &amp;lt;- true
}

func checkPacketsCc(input chan []byte, output chan []byte, quit chan bool) {
	for {
		packet := &amp;lt;-input
		// contents of checkPacketCc(), above
		output &amp;lt;- packet
	}
	quit &amp;lt;- true
}

func writePackets(c chan []byte, quit chan bool) {
	for {
		packet := &amp;lt;-c
		os.Stdout.Write(packet)
	}
	quit &amp;lt;- true
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In porting an existing application to a new language, we have had the opportunity to practice refactoring and to think more in-depth about software architecture. The Unix philosophy of simple, composable tools is alive and well, but we can make the idea work harder for us by composing the tools at a finer level of granularity and exposing their components via library calls. Getting the API design right requires further refactoring. Here is a starting point:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// src/gomux/util/tsloop.go
package util

import (
	&quot;bytes&quot;
	&quot;encoding/binary&quot;
	&quot;fmt&quot;
	&quot;io&quot;
	&quot;os&quot;
	&quot;syscall&quot;
)

const (
	TsPacketSize = 188
	MaxPid       = 8192
)

// PID table for the continuity counter of the TS packets
type CcTable [MaxPid]byte

var (
	previousCcTable CcTable
)

// read a packet from the file(s) provided
// loops onto the next available file on EOF
func ReadPackets(filenames []string, openFile int, tsFile *os.File,
		input chan []byte, quit chan bool) {
	packet := make([]byte, TsPacketSize)
	for {
		count, err := tsFile.Read(packet)
		// handle short packet
		if count &amp;lt; TsPacketSize || err == io.EOF {
			openFile %= len(filenames)
			openFile += 1
			tsFile.Close()
			InitCcTable(previousCcTable)
			tsFile, err = os.Open(filenames[openFile])
			if err != nil {
				fmt.Fprintf(os.Stderr,
					&quot;Can&apos;t open file %s\n&quot;, filenames[openFile])
				os.Exit(1)
			}
			count, err := tsFile.Read(packet)
			if count &amp;lt;= 0 || err != nil {
				os.Exit(1)
			}
		}
		input &amp;lt;- packet
	}
	quit &amp;lt;- true
}

// initialize a cc table
func InitCcTable(table CcTable) {
	for i, _ := range table {
		table[i] = 0x10
	}
}

// extract the PID from 2 bytes of the packet.
// Performs some binary magic to make it conform to the correct format.
// Example:
//     pid := extractPid(packet[1:3])
func ExtractPid(s []byte) uint16 {
	buf := bytes.NewBuffer(s)
	var pid uint16
	binary.Read(buf, binary.LittleEndian, &amp;amp;pid)
	pid = syscall.Ntohs(pid)
	pid = pid &amp;amp; 0x1fff
	return pid
}

func CheckPacketsCc(input chan []byte, output chan []byte, quit chan bool) {
	var pidCcTable CcTable
	InitCcTable(pidCcTable)
	InitCcTable(previousCcTable)
	for {
		packet := &amp;lt;-input
		pid := ExtractPid(packet[1:3])
		if pid &amp;lt; MaxPid {
			if pidCcTable[pid] == 0x10 {
				fmt.Fprintf(os.Stderr,
					&quot;new pid entry %d\n&quot;, pid)
				// new stream to track cc
				pidCcTable[pid] = packet[3] &amp;amp; 0x0f
				previousCcTable[pid] = packet[3] &amp;amp; 0x0f
			} else {
				adaptationField := (packet[3] &amp;amp; 0x30) &amp;gt;&amp;gt; 4
				if adaptationField == 0x0 || adaptationField == 0x2 {
					// reserved, no increment
					packet[3] = (pidCcTable[pid] | (packet[3] &amp;amp; 0xf0))
				} else if (adaptationField == 0x1) &amp;amp;&amp;amp;
						((packet[3] &amp;amp; 0x0f) == previousCcTable[pid]) {
					// double packet accepted only once
					packet[3] = (pidCcTable[pid] | (packet[3] &amp;amp; 0xf0))
					previousCcTable[pid] = 0x10
				} else if (adaptationField == 0x3) &amp;amp;&amp;amp;
						((packet[3] &amp;amp; 0x0f) == previousCcTable[pid]) {
					// double packet accepted only once
					packet[3] = (pidCcTable[pid] | (packet[3] &amp;amp; 0xf0))
					previousCcTable[pid] = 0x10
				} else {
					// increase the cc and restamp
					previousCcTable[pid] = packet[3] &amp;amp; 0x0f
					pidCcTable[pid] = (pidCcTable[pid] + 1) % 0x10
					packet[3] = (pidCcTable[pid] | (packet[3] &amp;amp; 0xf0))
				}
			}
		}
		output &amp;lt;- packet
	}
	quit &amp;lt;- true
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This library can be called from the main program below:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Write packets to standard out
func WritePackets(c chan []byte, quit chan bool) {
	for {
		packet := &amp;lt;-c
		os.Stdout.Write(packet)
	}
	quit &amp;lt;- true
}

// src/tsloop/tsloop.go
package main

import (
	&quot;flag&quot;
	&quot;fmt&quot;
	&quot;gomux/util&quot;
	&quot;os&quot;
)

func main() {
	flag.Parse()
	if flag.NArg() &amp;gt;= 1 {
		if tsFile, err := os.Open(flag.Arg(0)); err == nil {
			input := make(chan []byte)
			output := make(chan []byte)
			quit := make(chan bool)
			nGoroutines := 3
			go util.ReadPackets(flag.Args(), 0, tsFile, input, quit)
			go util.CheckPacketsCc(input, output, quit)
			go util.WritePackets(output, quit)
			for i := 0; i &amp;lt; nGoroutines; i++ {
				&amp;lt;-quit
			}
		} else {
			fmt.Fprintf(os.Stderr,
				&quot;tsloop: unable to open file %s\n&quot;, flag.Arg(1))
			os.Exit(1)
		}
	} else {
		fmt.Fprintf(os.Stderr,
			&quot;Usage: &apos;tsloop filename1.ts filename2.ts ... filenameN.ts&apos;\n&quot;)
		os.Exit(1)
	}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Replacing code with XML using Spring Integration</title>
<link href="http://iangilham.com/2013/07/20/Replacing-code-with-XML-using-Spring-Integration.html" rel="alternate"/>
<updated>2013-07-20T00:00:00+00:00</updated>
<id>http://iangilham.com/2013/07/20/Replacing-code-with-XML-using-Spring-Integration.html</id>



<content type="html">&lt;p&gt;A few weeks ago I had a go at implementing a familiar kind of application using some new tools. The basic structure should
be well known to most developers:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Receive something to process&lt;/li&gt;
  &lt;li&gt;Do something with it&lt;/li&gt;
  &lt;li&gt;Send the result somewhere&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This basic structure pervades the software industry and naturally, there is a vast swathe of reinvented wheels for
managing the control flow, often multiple implementations in the same company.&lt;/p&gt;

&lt;p&gt;I was building a new application with this structure in Java to consolidate a process that used two similar
applications down to just one, reducing complexity along the way. The existing apps implement file system polling
for input and FTP and SOAP calls for output. As I was doing exploratory work, I had the opportunity to look at
different ways of doing things.&lt;/p&gt;

&lt;p&gt;I started by bringing the existing code into our new application, rewriting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; method and control flow
boilerplate code, and reusing the input and output code from previous projects. Once the basic structure was in place,
I started looking for opportunities to replace some of the hard-to-test boilerplate code with library usage. Since
Spring is used extensively on new projects at the office, we looked into what tools were available in the Spring
framework that might meet our needs. That’s where we came across Spring Integration.&lt;/p&gt;

&lt;p&gt;Using Spring Integration we were able to reduce the main method to 2 lines and completely remove all the boilerplate
code that wired up the file system listener to a processing step and then to the output system. Ultimately, we had
just a few lines of XML orchestrating the entire process.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
     xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
     xmlns:context=&quot;http://www.springframework.org/schema/context&quot;
     xmlns:int=&quot;http://www.springframework.org/schema/integration&quot;
     xmlns:int-file=&quot;http://www.springframework.org/schema/integration/file&quot;
     xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/integration
        http://www.springframework.org/schema/integration/spring-integration.xsd
        http://www.springframework.org/schema/integration/file
        http://www.springframework.org/schema/integration/file/spring-integration-file.xsd&quot;&amp;gt;

    &amp;lt;context:property-placeholder location=&quot;classpath*:config.properties&quot;/&amp;gt;
    &amp;lt;!--Define channels for message-passing--&amp;gt;
    &amp;lt;int:channel id=&quot;input&quot; datatype=&quot;java.io.File&quot;/&amp;gt;
    &amp;lt;int:channel id=&quot;output&quot; datatype=&quot;com.example.myapp.OutputType&quot;/&amp;gt;

    &amp;lt;!--Feed the input from a file system monitor--&amp;gt;
    &amp;lt;int-file:inbound-channel-adapter channel=&quot;input&quot;
                                      directory=&quot;file:${inputDirectory}&quot;
                                      filename-pattern=&quot;*${updExtension}&quot;
                                      auto-create-directory=&quot;false&quot;
                                      auto-startup=&quot;true&quot;&amp;gt;
        &amp;lt;int:poller fixed-delay=&quot;${pollingFrequency}&quot;/&amp;gt;
    &amp;lt;/int-file:inbound-channel-adapter&amp;gt;

    &amp;lt;!--Transform input format to output format - the business logic--&amp;gt;
    &amp;lt;int:transformer method=&quot;transform&quot; input-channel=&quot;input&quot; output-channel=&quot;output&quot;&amp;gt;
        &amp;lt;bean class=&quot;com.example.myapp.Input2OutputTypeTransformer&quot;/&amp;gt;
    &amp;lt;/int:transformer&amp;gt;

    &amp;lt;!--Publish output over our own interface--&amp;gt;
    &amp;lt;int:outbound-channel-adapter id=&quot;out&quot; method=&quot;publish&quot;&amp;gt;
        &amp;lt;bean class=&quot;com.example.myapp.WebServicePublisher&quot;/&amp;gt;
    &amp;lt;/int:outbound-channel-adapter&amp;gt;
&amp;lt;/beans&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This Spring XML config defines an application which polls the file system for files with a particular extension
(FTP’d in by an upstream process), performs some process with those files, then sends the resulting OutputType over a
WebServicePublisher interface.&lt;/p&gt;

&lt;p&gt;Since all the wiring is in Spring, we can expect it to be well tested. This allows us to focus on testing our business
logic and delete our own boilerplate code, reducing the risk of it being rubbish.&lt;/p&gt;

&lt;p&gt;To get the application to run, you just need a very simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; method:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public static void main(String[] args) {
    try {
        final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
            new String[]{&quot;beans.xml&quot;});
        context.registerShutdownHook();
    } catch (BeansException e) {
        LOG.fatal(&quot;Beans Exception caught. Exiting...&quot;, e);
        System.exit(-1);
    }
    LOG.info(&quot;End of main method, other threads continue...&quot;);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The only gotcha here is that after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main()&lt;/code&gt; exits, the file system poller will continue to run and keep the
application alive. That being said, this is a rather nice way to make the simple things easy and avoid having to
maintain a code to poll the file system and pass the objects between components in the chain.&lt;/p&gt;

&lt;p&gt;Not shown here are the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Input2OutputTypeTransformer&lt;/code&gt; which accepts a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File&lt;/code&gt; and returns an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OutputType&lt;/code&gt;, and the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WebServicePublisher&lt;/code&gt; for sending the transformer’s output to a web service. All the glue for running the input file
through the transformer and sending the output to where it needs to go are handled by the framework and a few lines
of configuraiton.&lt;/p&gt;

&lt;p&gt;What I really like about this approach is that not only do I not need to maintain code for passing messages around,
I can also change the method of receiving and sending messages without doing any work on the remaining code. It is
flexible and allows me to be avoid unnecessary work.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">VS2003 compiler bug - 64 bit enum truncation</title>
<link href="http://iangilham.com/2012/09/22/VS2003-compiler-bug-64bit-enum-truncation.html" rel="alternate"/>
<updated>2012-09-22T00:00:00+00:00</updated>
<id>http://iangilham.com/2012/09/22/VS2003-compiler-bug-64bit-enum-truncation.html</id>



<content type="html">&lt;p&gt;I’ve written before about the &lt;a href=&quot;http://iangilham.com/2012/07/08/VS2003-Compiler-Bug-in-Managed-Cpp-false-positive-warning.html&quot;&gt;compiler bug in managed C++ 7.1&lt;/a&gt;. From the information I had available, it looked like the compiler warning was merely a false-positive. Unfortunately, it looks like the problem goes deeper than that.&lt;/p&gt;

&lt;p&gt;Consider this test application:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Managed C++ legacy syntax for .Net 1.0

#include &quot;stdafx.h&quot;

#using &amp;lt;mscorlib.dll&amp;gt;

using namespace System;
using namespace System::Collections;

// commented the FlagsAttribute to simplify printout
//[FlagsAttribute]
__value enum MyEnum : Int64 {
    None = 0,
    Flag0 = 1i64 &amp;lt;&amp;lt; 0,
    Flag1 = 1i64 &amp;lt;&amp;lt; 1,
    Flag2 = 1i64 &amp;lt;&amp;lt; 2,
    Flag3 = 1i64 &amp;lt;&amp;lt; 3,
    Flag4 = 1i64 &amp;lt;&amp;lt; 4,
    Flag5 = 1i64 &amp;lt;&amp;lt; 5,
    Flag6 = 1i64 &amp;lt;&amp;lt; 6,
    Flag7 = 1i64 &amp;lt;&amp;lt; 7,
    Flag8 = 1i64 &amp;lt;&amp;lt; 8,
    Flag9 = 1i64 &amp;lt;&amp;lt; 9,
    Flag10 = 1i64 &amp;lt;&amp;lt; 10,
    Flag11 = 1i64 &amp;lt;&amp;lt; 11,
    Flag12 = 1i64 &amp;lt;&amp;lt; 12,
    Flag13 = 1i64 &amp;lt;&amp;lt; 13,
    Flag14 = 1i64 &amp;lt;&amp;lt; 14,
    Flag15 = 1i64 &amp;lt;&amp;lt; 15,
    Flag16 = 1i64 &amp;lt;&amp;lt; 16,
    Flag17 = 1i64 &amp;lt;&amp;lt; 17,
    Flag18 = 1i64 &amp;lt;&amp;lt; 18,
    Flag19 = 1i64 &amp;lt;&amp;lt; 19,
    Flag20 = 1i64 &amp;lt;&amp;lt; 20,
    Flag21 = 1i64 &amp;lt;&amp;lt; 21,
    Flag22 = 1i64 &amp;lt;&amp;lt; 22,
    Flag23 = 1i64 &amp;lt;&amp;lt; 23,
    Flag24 = 1i64 &amp;lt;&amp;lt; 24,
    Flag25 = 1i64 &amp;lt;&amp;lt; 25,
    Flag26 = 1i64 &amp;lt;&amp;lt; 26,
    Flag27 = 1i64 &amp;lt;&amp;lt; 27,
    Flag28 = 1i64 &amp;lt;&amp;lt; 28,
    Flag29 = 1i64 &amp;lt;&amp;lt; 29,
    Flag30 = 1i64 &amp;lt;&amp;lt; 30,
    Flag31 = 1i64 &amp;lt;&amp;lt; 31,
    Flag32 = 1i64 &amp;lt;&amp;lt; 32,
    Flag33 = 1i64 &amp;lt;&amp;lt; 33,
    Flag34 = 1i64 &amp;lt;&amp;lt; 34,
    Flag35 = 1i64 &amp;lt;&amp;lt; 35,
    Flag36 = 1i64 &amp;lt;&amp;lt; 36,
    Flag37 = 1i64 &amp;lt;&amp;lt; 37,
    Flag38 = 1i64 &amp;lt;&amp;lt; 38,
    Flag39 = 1i64 &amp;lt;&amp;lt; 39,
    Flag40 = 1i64 &amp;lt;&amp;lt; 40,
    Flag41 = 1i64 &amp;lt;&amp;lt; 41,
    Flag42 = 1i64 &amp;lt;&amp;lt; 42,
    Flag43 = 1i64 &amp;lt;&amp;lt; 43,
    Flag44 = 1i64 &amp;lt;&amp;lt; 44,
    Flag45 = 1i64 &amp;lt;&amp;lt; 45,
    Flag46 = 1i64 &amp;lt;&amp;lt; 46,
    Flag47 = 1i64 &amp;lt;&amp;lt; 47,
    Flag48 = 1i64 &amp;lt;&amp;lt; 48,
    Flag49 = 1i64 &amp;lt;&amp;lt; 49,
    Flag50 = 1i64 &amp;lt;&amp;lt; 50,
    Flag51 = 1i64 &amp;lt;&amp;lt; 51,
    Flag52 = 1i64 &amp;lt;&amp;lt; 52,
    Flag53 = 1i64 &amp;lt;&amp;lt; 53,
    Flag54 = 1i64 &amp;lt;&amp;lt; 54,
    Flag55 = 1i64 &amp;lt;&amp;lt; 55,
    Flag56 = 1i64 &amp;lt;&amp;lt; 56,
    Flag57 = 1i64 &amp;lt;&amp;lt; 57,
    Flag58 = 1i64 &amp;lt;&amp;lt; 58,
    Flag59 = 1i64 &amp;lt;&amp;lt; 59,
    Flag60 = 1i64 &amp;lt;&amp;lt; 60,
    Flag61 = 1i64 &amp;lt;&amp;lt; 61,
    Flag62 = 1i64 &amp;lt;&amp;lt; 62,
    Flag63 = 1i64 &amp;lt;&amp;lt; 63,
    All = Int64::MaxValue
};

int _tmain()
{
    Console::WriteLine(S&quot;Testing enum range&quot;);
    Array* values = Enum::GetValues(__typeof(MyEnum));
    for(Int32 i = 0; i &amp;lt; values-&amp;gt;Length; ++i) {
        Object* o = values-&amp;gt;GetValue(i);
        Console::WriteLine(&quot;{0} = {1}&quot;,
            Enum::Format(__typeof(MyEnum), o, &quot;G&quot;),
            Enum::Format(__typeof(MyEnum), o, &quot;D&quot;));
    }
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you build that as a Managed C++ project in Visual Studio .Net 2003, you will see the telltale signs of compiler integer truncation:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Testing enum range
Flag33 = 0
Flag33 = 0
...
Flag0 = 1
Flag1 = 2
Flag2 = 4
...
Flag31 = 2147483648
All = 4294967295
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is what the dreaded compiler warning was telling us about in the first place, and sure enough, we got the warning while compiling this code: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;warning C4309: &apos;initializing&apos; : truncation of constant value&lt;/code&gt;. We seem to have come full circle, verifying that despite being told to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int64&lt;/code&gt; to back the enum, the compiler decided to use an Int32 anyway and made a mess of things.&lt;/p&gt;

&lt;p&gt;It gets stranger than that. I revisited this problem because I received a bug report where the enum has been opened up, and found to contain silly values like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x102000000L&lt;/code&gt; as well as duplicates. The strange ones are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;All&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;None = 0x100000000L,
All = 0x1ffffffffL,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A 64-bit integer is clearly being used for the storage backing of the enum, but the values are wrong and only the first 32 bits seem to be read when reading values in code. The only sane conclusion is that using a 64 bit integer to back a managed enum in Managed C++ invoked undefined behaviour in the Visual C++ 7.1 compiler.&lt;/p&gt;

&lt;p&gt;This issue is fixed in VC8 using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/clr:oldSyntax&lt;/code&gt; to compile the same code. I’d love to be able to tell all my clients to upgrade, but in order to keep everyone happy without requiring too much client code to change, I’ll have to settle for using static constants inside a little class:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public class EnumConstantFlags {
public:
    static const Int64 None = 0;
    static const Int64 Flag0 = 1i64 &amp;lt;&amp;lt; 0;
    static const Int64 Flag1 = 1i64 &amp;lt;&amp;lt; 1;
    // ...
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These constants can still be used as a bitfield, so the damage is minimal and it will work on all versions of the compiler and CLR.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Nesting parentheses in a Windows batch script</title>
<link href="http://iangilham.com/2012/09/17/Nesting-parentheses-Windows-batch-script.html" rel="alternate"/>
<updated>2012-09-17T00:00:00+00:00</updated>
<id>http://iangilham.com/2012/09/17/Nesting-parentheses-Windows-batch-script.html</id>



<content type="html">&lt;p&gt;My project at work has historically been a small component in a much larger pile of APIs and applications all tied to the same build system, a Windows scheduled task and a pile of incoherent batch scripts. Since then, we have grown up into our own small pile of APIs and connected applications and the time to divorce the parent project has finally come.&lt;/p&gt;

&lt;p&gt;In order to make the transition as clean as possible, I’ve been removing dependencies, reorganising the project structure and cleaning up our build scripts. Our Linux builds have always been isolated from the rest of the system so getting that to work in isolation was easy. The Windows builds on the other hand, took a lot more work.&lt;/p&gt;

&lt;p&gt;I needed to write a new script to build the Visual Studio solutions on a new continuous integration server. This is largely because the server can’t really handle Visual Studio 2003 without a little help. The script started out simple enough, using the command line arguments to set a few variables, select a version of Visual Studio and a build configuration, then eventually calling devenv with the required parameters. The batch language is primitive and buggy so it took a few goes to get this right. Eventually, I got it working on my machine, so I commited the script and watched it die on the CI server.&lt;/p&gt;

&lt;p&gt;The Visual Studio installation wasn’t found in Program Files. Well, this is a 64 bit server, so I queried &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%PROCESSOR_ARCHITECTURE%&lt;/code&gt; and had an alternate path on the 64 bit machine. Searching around the topic, you will sometimes see people checking specifically for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%ProgramFiles(x86)%&lt;/code&gt; or even if the raw path &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C:\Program Files (x86)&lt;/code&gt; exists. I did something like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rem select program files directory
if /I &quot;%PROCESSOR_ARCHITECTURE%&quot; EQU &quot;AMD64&quot; (
  echo building on 64-bit Windows
  set _VS7DIR_=&quot;C:\Program Files (x86)\Microsoft Visual Studio .NET 7.1\Common7\IDE&quot;
  set _VS8DIR_=&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\Common7\IDE&quot;
) else (
  echo building on 32-bit Windows
  set _VS7DIR_=&quot;C:\Program Files\Microsoft Visual Studio .NET 7.1\Common7\IDE&quot;
  set _VS8DIR_=&quot;C:\Program Files\Microsoft Visual Studio 8\Common7\IDE&quot;
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This threw up errors in the script parser, saying things like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;\Microsoft&apos; not expected at this time&lt;/code&gt;. After a bit of searching around, I found that the parser was interpreting the closing parenthesis in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Program Files (x86)&lt;/code&gt; as the end of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IF&lt;/code&gt; statement. This behaviour is obviously crazy, but nobody is ever going to update such an ancient and terrible scripting language, so we just have to accept that nesting parentheses are never going to work properly in a batch file and work around it.&lt;/p&gt;

&lt;p&gt;In the end, the mighty &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;goto&lt;/code&gt; solved the problem:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rem select program files directory
if /I &quot;%PROCESSOR_ARCHITECTURE%&quot; EQU &quot;AMD64&quot; goto progfiles_win64
:progfiles_win32
echo building on 32-bit Windows
set _VS7DIR_=&quot;C:\Program Files\Microsoft Visual Studio .NET 7.1\Common7\IDE&quot;
set _VS8DIR_=&quot;C:\Program Files\Microsoft Visual Studio 8\Common7\IDE&quot;
goto progfiles_done

:progfiles_win64
echo building on 64-bit Windows
set _VS7DIR_=&quot;C:\Program Files (x86)\Microsoft Visual Studio .NET 7.1\Common7\IDE&quot;
set _VS8DIR_=&quot;C:\Program Files (x86)\Microsoft Visual Studio 8\Common7\IDE&quot;
goto progfiles_done

:progfiles_done
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Parsing command line options to correctly handle VC7 and VC8 was much the same, but more complicated:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rem establish paths and defaults
set _VS7DIR_=%_VS7DIR_:&quot;=&quot;&quot;&quot;%
set _VS8DIR_=%_VS8DIR_:&quot;=&quot;&quot;&quot;%
set _VSDIR_=%_VS7DIR_%
set _VC7SLN_=MyProject_71.sln
set _VC8SLN_=MyProject_80.sln
set _SLN_=%_VC7SLN_%
set _OPTS_=/Build
set _MODE_=Debug

rem command line option parsing
:begin_opts
if /I &quot;%1&quot; EQU &quot;&quot; goto done_opts
if /I &quot;%1&quot; EQU &quot;clean&quot; (set _OPTS_=/Clean) &amp;amp;&amp;amp; goto next_opts
if /I &quot;%1&quot; EQU &quot;build&quot; (set _OPTS_=/Build) &amp;amp;&amp;amp; goto next_opts
if /I &quot;%1&quot; EQU &quot;rebuild&quot; (set _OPTS_=/Rebuild) &amp;amp;&amp;amp; goto next_opts
if /I &quot;%1&quot; EQU &quot;release&quot; (set _MODE_=Release) &amp;amp;&amp;amp; goto next_opts
if /I &quot;%1&quot; EQU &quot;debug&quot; (set _MODE_=Debug) &amp;amp;&amp;amp; goto next_opts

rem find the visual studio installation
rem forgive the spaghetti, Windows cannot parse parentheses in IF, FOR, etc.
rem when we might have (x86) in the path
if /I &quot;%1&quot; EQU &quot;VC7&quot; goto vc7_opts
if /I &quot;%1&quot; EQU &quot;VC8&quot; goto vc8_opts

rem catch-all for unknown options
echo unknown option &apos;%1&apos; - clean, build, release or debug expected &amp;gt;&amp;amp;2
goto :failed_opts

:next_opts
shift
goto begin_opts

:vc7_opts
echo VC7 selected
set _SLN_=%_VC7SLN_%
if exist %_VS7DIR_% goto vc7_exist_opts
goto vc7_failed_opts

:vc7_exist_opts
echo using Visual Studio from %_VS7DIR_:&quot;&quot;&quot;=&apos;%
set _VSDIR_=%_VS7DIR_%
goto next_opts

:vc8_opts
echo VC8 selected
set _SLN_=%_VC8SLN_%
if exist %_VS8DIR_% goto vc8_exist_opts
goto vc8_failed_opts

:vc8_exist_opts
echo using Visual Studio from %_VS8DIR_:&quot;&quot;&quot;=&apos;%
set _VSDIR_=%_VS8DIR_%
goto next_opts

:done_opts

:vc7_failed_opts
echo Visual Studio 7 not found &amp;gt;&amp;amp;2
goto failed_opts

:vc8_failed_opts
echo Visual Studio 8 not found &amp;gt;&amp;amp;2
goto failed_opts

:failed_opts
echo option parsing failed &amp;gt;&amp;amp;2
goto 2&amp;gt;nul:
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I hope this is useful to anyone suffering under the tyranny of the Windows batch scripting language. Where possible it is probably better to use Powershell or a third party scripting language like Python, Ruby, Perl, etc. In my situation I had to hit the lowest common denominator across various editions of Windows.&lt;/p&gt;
</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Haiku - Lovers embrace</title>
<link href="http://iangilham.com/2012/09/08/Haiku-lovers-embrace.html" rel="alternate"/>
<updated>2012-09-08T00:00:00+00:00</updated>
<id>http://iangilham.com/2012/09/08/Haiku-lovers-embrace.html</id>



<content type="html">&lt;p&gt;I came up with this on the beach in Bournemouth. It breaks a few too many rules to be a proper haiku, but I like it.&lt;/p&gt;

&lt;blockquote&gt;
Waves lapping,
the star lit beach;
Lovers embrace
&lt;/blockquote&gt;
</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Visual Studio 2003 compiler bug in Managed C++ - false positive warning</title>
<link href="http://iangilham.com/2012/07/08/VS2003-Compiler-Bug-in-Managed-Cpp-false-positive-warning.html" rel="alternate"/>
<updated>2012-07-08T00:00:00+00:00</updated>
<id>http://iangilham.com/2012/07/08/VS2003-Compiler-Bug-in-Managed-Cpp-false-positive-warning.html</id>



<content type="html">&lt;p&gt;I found a compiler bug at work yesterday while adding a large bitfield enum to
the .Net interop layer of a project. The main project is a set of native C++
DLLs built primarily with Visual Studio 2003. We have other targets but as the
lowest common denominator, everything has to work on the legacy compiler.
The .Net layer is a mixed assembly built with Managed C++ (now known
as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/clr:oldSyntax&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;There is a large enum used as a bitfield in the data API of this project.
Unfortunately it has grown to 46 distinct values, so an enum based on a 32-bit
integer is no longer appropriate. Adding the new values and changing the
underlying type of the enum to Int64 causes the compiler to complain:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[FlagsAttribute]
__value enum eLongChangedFlags : Int64
{
    None = 0,
    Foo = 1 &amp;lt;&amp;lt; 0,
    Bar = 1 &amp;lt;&amp;lt; 1,
    // ...
    Scary = 1 &amp;lt;&amp;lt; 44
    // warning C4309: &apos;initializing&apos; : truncation of constant value
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is counter-intuitive at first, but it is essentially saying that a large
number like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1 &amp;lt;&amp;lt; 44&lt;/code&gt; (17,592,186,044,416) is out of range of the possible
values that the underlying number type can represent. This is incorrect,
so we have to assume the compiler still thinks we are dealing with a 32-bit
integer or worse.&lt;/p&gt;

&lt;p&gt;There wasn’t a lot of information about this error on the internet but there
are a few related known bugs in the old compiler. Tellingly, compiling this
in Visual Studio 2005 did not give me the same warning. To verify if the
enum values have in fact been truncated, we need a test application. I found
&lt;a href=&quot;http://stackoverflow.com/a/2292564&quot;&gt;some code on StackOverflow&lt;/a&gt; that suited my purpose and just debugged into
it to see what value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scary&lt;/code&gt; ultimately represented. It was correct, not
truncated and not overflowing into negative figures. The compiler warning
is wrong.&lt;/p&gt;

&lt;p&gt;To silence the warning I added a couple of pragmas to the original code:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#if _MSC_VER &amp;lt;= 1310
// Disable false positive warning on VS2003 compiler.
// The code has been verified to work, despite the scary warning.
// warning C4309: &apos;initializing&apos; : truncation of constant value
#pragma warning(disable:4309)
#endif
[FlagsAttribute]
__value enum eLongChangedFlags : Int64
{
    None = 0,
    Foo = 1 &amp;lt;&amp;lt; 0,
    Bar = 1 &amp;lt;&amp;lt; 1,
    // ...
    Scary = 1 &amp;lt;&amp;lt; 44,
};
#if _MSC_VER &amp;lt;= 1310
// re-enable compiler warning in case of further issues elsewhere
#pragma warning(default:4309)
#endif
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Using video to improve your own performance</title>
<link href="http://iangilham.com/2012/07/08/Using-video-to-improve-your-own-performance.html" rel="alternate"/>
<updated>2012-07-08T00:00:00+00:00</updated>
<id>http://iangilham.com/2012/07/08/Using-video-to-improve-your-own-performance.html</id>



<content type="html">&lt;p&gt;I’ve been working on one of my kung fu forms consistently for the last few
weeks. At first I was a little sloppy from not having practiced it in a long
time. I worked on it a little every day and got used to the movements again,
gradually making it flow better and with greater power.&lt;/p&gt;

&lt;p&gt;After about a week of this, I received a challenge to make a video of myself
performing. I recorded my form in a nearby field and had a quick look. It
wasn’t pretty. I rushed sections of the form and lost my balance. My hands
were all over the place in some of the techniques and the alignment of my
stances made power delivery impossible in a few places.&lt;/p&gt;

&lt;p&gt;Disappointed with myself, I had another go. This time I took care not to rush
and to concentrate on the movements and applications of the techniques. The
resulting video was much better. Everything was much more crisp and tidy. The
remaining errors are indicative of flaws in my form rather than just bad habits
and sloppy performance. They will take more considered practice to correct, but
it is at least a lot easier to work on the problems when you are aware of what
they are.&lt;/p&gt;

&lt;p&gt;There are lessons to be learned here. Practising the same thing without
feedback entrenches bad habits and allows improvement to slow to a halt.
In the absense of an instructor to make corrections, video and self criticism
can provide enough feedback to keep you honest and maintain your level of
performance. It can also help to highlight any other flaws if you know what
you are looking for. Video is good. I exspect it can be used in other sports
and activities to hasten improvement and prevent bad habits from creeping in.&lt;/p&gt;
</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Fitness - mind and body awesomeness</title>
<link href="http://iangilham.com/2012/02/26/Fitness-mind-and-body-awesomeness.html" rel="alternate"/>
<updated>2012-02-26T00:00:00+00:00</updated>
<id>http://iangilham.com/2012/02/26/Fitness-mind-and-body-awesomeness.html</id>



<content type="html">&lt;p&gt;I’ve been in the &lt;a href=&quot;/category/martial-arts/&quot;&gt;martial arts&lt;/a&gt; for about 8 years now, through college, university, and employment. While I haven’t always been consistent, I did learn early on that the brain works much better when you give the body something difficult to do. This was especially obvious in my university years, when I had time for 4 classes per week, plus the occasional seminar. Despite my high level of physical activity, I found myself smarter, more energized and better rested during that time than ever before.&lt;/p&gt;

&lt;p&gt;Now that I work full time and have other responsibilities it is impossible to train quite so much, but I still go to class twice a week and enjoy the many benefits. Since attending any more classes would prevent me from getting enough sleep at the moment, I’ve been finding other ways to get some decent exercise in on the days I don’t have kung fu. I’m working on balancing out my left and right sides to start with and will progress to lifting heavier things as time goes on.&lt;/p&gt;

&lt;p&gt;I’m starting pretty slow, with simple bodyweight and kettlebell workouts, usually no more than 10 minutes a time, so I can focus on other things of an evening. I’m also running home after work when I don’t want to wait around for the bus. The recent sub-zero temperature was a great motivatior for not standing around outside for 20 minutes at a time. I’ve been enjoying the run, so I see no reason to stop doing it.&lt;/p&gt;

&lt;p&gt;The other side of the coin is to clean up my diet. I’ve long been a lover of cheese and bread and a number of other unnatural foods, and I’m slowly reducing and eliminating the worst offenders. Since I like watching numbers change, I’m tracking a few basic measurements and statistics in a spreadsheet. The timeline chart in Google Spereadsheets is especially good for this.&lt;/p&gt;

&lt;p&gt;I still have a long way to go but it’s a fun journey, inspired by websites like &lt;a href=&quot;http://nerdfitness.com/&quot;&gt;Nerd Fitness&lt;/a&gt; and authors like &lt;a href=&quot;http://fourhourbody.com/&quot; title=&quot;Tim Ferriss&apos; Four Hour Body&quot;&gt;Tim Ferris&lt;/a&gt;. Good times.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Resolving Linux shared library dependencies</title>
<link href="http://iangilham.com/2012/01/22/Resolving-Linux-shared-library-dependencies.html" rel="alternate"/>
<updated>2012-01-22T00:00:00+00:00</updated>
<id>http://iangilham.com/2012/01/22/Resolving-Linux-shared-library-dependencies.html</id>



<content type="html">&lt;p&gt;Sometimes when you try to launch an application on Linux, typically one you have built yourself, you might get an error like this:&lt;/p&gt;

&lt;p&gt;./myapp: error while loading shared libraries: libpq.so.5: cannot open shared object file: No such file or directory&lt;/p&gt;

&lt;p&gt;When this happens, it is up to you to figure out what the problem is. Fortunately, you have a tool called &lt;em&gt;ldd&lt;/em&gt; to help.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# using which to get the full path to the executable
ldd $(which sh)
    linux-vdso.so.1 =&amp;gt; (0x00007fff44fff000)
    libtinfo.so.5 =&amp;gt; /lib64/libtinfo.so.5
    ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If any of the shared (dynamic) libraries are not found, you will have to locate them and add them to your LD_LIBRARY_PATH environment variable. something like the following should do the trick:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/missing/library
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Haiku - Autumn on the wharf</title>
<link href="http://iangilham.com/2012/01/03/Haiku-autumn-on-the-wharf.html" rel="alternate"/>
<updated>2012-01-03T00:00:00+00:00</updated>
<id>http://iangilham.com/2012/01/03/Haiku-autumn-on-the-wharf.html</id>



<content type="html">&lt;p&gt;I wrote this little poem while sitting by the bridge on the South side of Canary Wharf in the Autumn.&lt;/p&gt;

&lt;blockquote&gt;
The late sun gleams;
wings beat on the surface,
of glowing water
&lt;/blockquote&gt;
</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Fighting the holiday fat</title>
<link href="http://iangilham.com/2012/01/03/Fighting-the-holiday-fat.html" rel="alternate"/>
<updated>2012-01-03T00:00:00+00:00</updated>
<id>http://iangilham.com/2012/01/03/Fighting-the-holiday-fat.html</id>



<content type="html">&lt;p&gt;My priviledged position as an IT consultant brings with it the possibility that a client may decide to send me home for a couple of weeks to trim their end of year budget. That’s fair enough, but should I really be allowed to bum around at home with such massive quantities of food around? All the &lt;del&gt;good&lt;/del&gt; bad things… I think not!&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Feeling fat
time for exercise-
Pretty tree&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’ve got another week off work, so when better to clear out some of the bad things and get some proper exercise? I like to keep things simple, so I’m working on a few core areas only for now. Diet is another thing and pretty easy to keep a handle on when the house isn’t full of cake and other gorgeously evil delicacies.&lt;/p&gt;

&lt;h3 id=&quot;core-stability-lower-back&quot;&gt;Core stability/ lower back&lt;/h3&gt;

&lt;p&gt;My Achilles’ heel if ever there was one and the day job really doesn’t help. I have always had a weak lower back, and it atrophies quickly, so this is the most important thing I need to rebuild. I’m mainly doing simple body-weight exercises like push-ups and sit-ups, and a few swings and deadlifts with my 24kg (53lb) kettlebell.&lt;/p&gt;

&lt;h3 id=&quot;arse&quot;&gt;Arse&lt;/h3&gt;

&lt;p&gt;Yes, I have a big one, as my girlfriend keeps reminding me. It has reasonably well developed muscles from years of martial arts, but it still carries a little more heft than I would like. The kettlebell swings seem to help tighten up its squishiness and a run through the local forest helps burn off the flab with side benefits to the heart, lungs and pretty much everything else. Death to the massive arse!&lt;/p&gt;
</content>
<author><name>Ian Gilham</name></author>
</entry>

<entry>
<title type="text">Displaying text on networked HP printers</title>
<link href="http://iangilham.com/2011/12/05/Displaying-text-on-networked-HP-printers.html" rel="alternate"/>
<updated>2011-12-05T00:00:00+00:00</updated>
<id>http://iangilham.com/2011/12/05/Displaying-text-on-networked-HP-printers.html</id>



<content type="html">&lt;p&gt;I &lt;a href=&quot;http://odetocode.com/humor/68.aspx&quot;&gt;stumbled across&lt;/a&gt; a fun little way to put arbirary text on the display screen of HP network printers today. The original code is in C# from the days of .NET 1.0–1.1, so I decided to bring it up to date to the current framework. The program uses HP’s &lt;a href=&quot;http://en.wikipedia.org/wiki/Printer_Job_Language&quot;&gt;Printer Job Language&lt;/a&gt; to communicate with the printer. This will probably work with some other printers as well as most manufacturers have some support for PJL, according to Wikipedia.&lt;/p&gt;

&lt;p&gt;Why would I want to mess with the printer’s display? For fun. If a printer that ‘feels fat today’ can put a smile on someone’s face then it has all been worthwhile.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// hptalk.cs
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace hptalk
{
    /// make HP network printers talk
    /// code taken from odetocode.com and updated to C# 4.0
    /// ref: http://odetocode.com/humor/68.aspx
    class HpTalk
    {
        static int Main(string[] args)
        {
            if (!ParseArgs(args))
            {
                return -1;
            }
            Console.WriteLine(&quot;Host: {0}, Message: {1}&quot;, args[0], message);
            try
            {
                var ipEndPoint = new IPEndPoint(
                    Dns.GetHostEntry(args[0]).AddressList[0],
                    PJL_PORT);
                Console.WriteLine(&quot;Host IP is {0}&quot;, ipEndPoint.ToString());
                using (var socket = new Socket(
                    AddressFamily.InterNetwork,
                    SocketType.Stream,
                    ProtocolType.Tcp))
                {
                    socket.Connect(ipEndPoint);
                    var sendString = String.Format(
                        &quot;\x1B%-12345X@PJL RDYMSG DISPLAY = \&quot;{0}\&quot;\r\n\x1B%-12345X\r\n&quot;,
                        message);
                    var sendData = Encoding.ASCII.GetBytes(sendString);
                    var result = socket.Send(sendData, sendData.Length, 0);
                    if (result == 0)
                    {
                        Console.Error.WriteLine(&quot;hptalk: socjket error&quot;);
                    }
                }
            }
            catch (SocketException ex)
            {
                Console.Error.WriteLine(ex);
                return -1;
            }
            return 0;
        }

        protected static bool ParseArgs(string[] args)
        {
            if (args.Length == 2)
            {
                if (args[1].Length &amp;gt; 16)
                {
                    Console.Error.WriteLine(
                        &quot;hptalk: message must be &amp;lt;= 16 characters&quot;);
                    return false;
                }
                else
                {
                    message = args[1];
                }
            }
            else if (args.Length == 1)
            {
                message = GetRandomMessage();
            }
            else
            {
                Console.Error.WriteLine(&quot;usage: hptalk printername [message]&quot;);
                return false;
            }
            return true;
        }


        public static string GetRandomMessage()
        {
            string[] Messages = {
                            &quot;TOUCH ME&quot;,
                            &quot;STEP AWAY&quot;,
                            &quot;PAT EATS MICE&quot;,
                            &quot;FEED ME&quot;,
                            &quot;BE GENTLE&quot;,
                            &quot;INSERT COIN&quot;,
                            &quot;I FEEL FAT&quot; // etc...
     };

            return Messages[random.Next() % Messages.Length];
        }

        private static Random random = new Random();

        protected const int PJL_PORT = 9100;
        protected static string message = GetRandomMessage();
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The comparison shows off a few of the changes to the language over the years. C# has obviously come a long way. Most of it is irrelevant to the tiny toy program, but even here, the line count has gone down, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt; statement takes care of resource cleanup and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var&lt;/code&gt; keyword avoids excessive typing.&lt;/p&gt;

</content>
<author><name>Ian Gilham</name></author>
</entry>


</feed>
