<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0"
        xmlns:atom="http://www.w3.org/2005/Atom"
        xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>(Ashbysoft *)</title>
    <link>https://www.ashbysoft.com/</link>
    <description>Recent content on (Ashbysoft *)</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 03 Apr 2026 08:13:15 +0000</lastBuildDate><atom:link href="https://www.ashbysoft.com/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>County Holidays</title>
      <link>https://www.ashbysoft.com/articles/countyhols/</link>
      <pubDate>Fri, 03 Apr 2026 08:13:15 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/countyhols/</guid>
      <description>Holidays in UK/Eire counties - the status page!</description>
      <content:encoded>&lt;p&gt;For a number of years, Angela &amp;amp; Phil have been working through all the UK/Eire counties
taking a holiday, this is where we have got to so far (check the article date ^^up there)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;./Holidays_in_UK_Eire_Counties.png&#34;&gt;&lt;figure&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/countyhols/Holidays_in_UK_Eire_Counties-small.png&#34; width=&#34;953&#34; height=&#34;1324&#34;&gt;
&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Map generated with the excellent &lt;a href=&#34;https://www.mapchart.net/uk.html&#34;&gt;MapChart&lt;/a&gt;.&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>SSO Yak Shaving</title>
      <link>https://www.ashbysoft.com/posts/sso_yak_shaving/</link>
      <pubDate>Mon, 02 Feb 2026 00:00:00 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/sso_yak_shaving/</guid>
      <description>How many rabbit holes can we fall down as we setup a &#39;basic&#39; self-service, single sign on system for our homelab? You know, just like Google has. One login, one password, and 2FA&amp;hellip;</description>
      <content:encoded>&lt;h1 id=&#34;yak-shaving-our-sso&#34;&gt;Yak shaving our SSO&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Yes, that is a thing!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Well folks, the time had come to make a decent job of supporting our family on our homelab, and move away from big G. Having already sorted out basic observability with replicated logging and monitoring, plus cross site backup, it was time to put consistent user services in place.&lt;/p&gt;
&lt;p&gt;Other articles will (probably) explain our setup for redundant email, calendar &amp;amp; contacts. We have alternate solutions for photos and music - Phil went minimal and just went for NAS shared to each player and added home brew face recognition. Stu was later to the party and went for immich &amp;amp; jellyfin respectively, (after using miniDLNA for several years.) Stu also has a home automation package called &lt;a href=&#34;https://domoticz.com/&#34;&gt;Domoticz&lt;/a&gt; which is quite widely used (just not as loudly trumpeted as Home Assistant!)&lt;/p&gt;
&lt;p&gt;Of course, each service needs user authentication. To reduce friction with the family, we would really like to offer common credentials across all services, with single sign on for relevant services. Plus a password change UI. Hmm.&lt;/p&gt;
&lt;h2 id=&#34;how-hard-can-it-be&#34;&gt;How hard can it be&lt;/h2&gt;
&lt;p&gt;We started with just chucking the relevant lines from /etc/passwd &amp;amp; /etc/shadow in git as we keep a shared repo in sync nightly between our two servers. This is ok for manual synchronisation, but leaves a potential big time gap in password sync if a user changes their credentials and neither of us are around to cut/paste the files! Also if we fat finger this operation we are in trouble&amp;hellip; Finally, although our email software (courier-imap, exim4) can use OS authentication, other more &#39;cloudy&#39; packages can&amp;rsquo;t access this so easily it seems.&lt;/p&gt;
&lt;p&gt;So - time to put something more robust in place that we can leverage for all services&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;start-from-the-os-level&#34;&gt;Start from the OS level&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Linux_PAM&#34;&gt;PAM&lt;/a&gt; provides the Linux/Unix OS API for authentication, and there is good support for both &lt;a href=&#34;https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol&#34;&gt;LDAP&lt;/a&gt; (Lightweight Directory Access Protocol) and &lt;a href=&#34;https://en.wikipedia.org/wiki/Network_Information_Service&#34;&gt;NIS&lt;/a&gt; (Network Information Service) back ends to provide centralised network data stores. (NIS was where I started back in about 1992 on HP-UX&amp;hellip;) However, NIS is deprecated these days as unreliable and insecure, so&amp;hellip; hello LDAP!&lt;/p&gt;
&lt;h3 id=&#34;openldap-ftw&#34;&gt;OpenLDAP FTW&lt;/h3&gt;
&lt;p&gt;OpenLDAP has been around for decades, and is a single binary (slapd) backed by a file store. So this is where we start our yak shaving&amp;hellip; getting the package installed is trivial on both Debian and Ubuntu. Documentation is.. interesting! There has been quite an effort to update slapd recently, moving to an entirely new configuration structure stored in the database itself, and a new integration with PAM using an external daemon (nslcd). Great, if the documentation would ever catch up! Hmm.
You can find more on &lt;a href=&#34;https://www.openldap.org/software/roadmap.html&#34;&gt;OpenLDAP roadmap here&lt;/a&gt; and &lt;a href=&#34;https://arthurdejong.org/nss-pam-ldapd/design&#34;&gt;PAM+LDAP design here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It took some time to find the right steps to get a base configuration that we could ingest data into from the shadow file; since we need a migration and we don&amp;rsquo;t have clear text password credentials for our users (rightly so!) Once the migration scripts were written/executed, and the source data filed away in git, we were able to remove the users from the /etc files and hey presto! We could still log in! PAM+LDAP provides a neat separation of system accounts (generally those below 1000, created by package installers and the like directly in the OS files) from our new, portable user accounts. Here&amp;rsquo;s what we ended up doing:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;First, this line added to &lt;em&gt;/etc/default/slapd&lt;/em&gt; ensures access via TCP, Unix socket &amp;amp; TLS/SSL&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;    SLAPD_SERVICES=&amp;quot;ldap:/// ldapi:/// ldaps:///&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;To update the user DB, we use the root Distinguished Name (rootDN) account,&lt;br&gt;
which we created at install time. This cmd ingests an&lt;br&gt;
LDAP Information File (.ldif) which has a standard syntax.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;    # ldapadd -x -D &#39;cn=admin,dc=ashbysoft,dc=com&#39; -y $rootpwd -f &amp;lt;filename&amp;gt;.ldif
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;-x tells ldapadd to use simple authentication which we need for rootDN access
-D provides the rootDN value &amp;amp; -y the password, which we set at install time.&lt;/p&gt;
&lt;p&gt;First we make an Organisational Unit (OU) to contain user accounts:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;    # ldapadd -x -D &#39;cn=admin,dc=ashbysoft,dc=com&#39; -y $rootpwd -f people.ldif
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;people.ldif contains:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;    dn: ou=People,dc=ashbysoft,dc=com  
    objectClass: organizationalUnit  
    ou: People  
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;We can then add our users. This is the .ldif template we used:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;    dn: uid=${uid},ou=People,dc=ashbysoft,dc=com  
    uid: ${uid}  
    givenName: ${gn}  
    sn: ${sn}  
    cn: ${gn} ${sn}  
    displayName: ${gn} ${sn}  
    objectClass: person  
    objectClass: posixAccount  
    objectClass: inetOrgPerson  
    userPassword: {CRYPT}${pwdh}  
    loginShell: /bin/bash  
    uidNumber: ${uidn}  
    gidNumber: ${gidn}  
    homeDirectory: /home/${uid}  
    mail: ${uid}@ashbysoft.com  
    gecos: ${gn} ${sn}  
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;where the parameters are taken from the /etc files. uid=Linux username, uidn=Linux ID. Ditto for group.&lt;br&gt;
gn=given name, sn=surname, cn=common name. Adjust as required.&lt;br&gt;
pwdh=password hash string from &lt;em&gt;/etc/shadow&lt;/em&gt; file.&lt;br&gt;
&lt;strong&gt;IMPORTANT: we prepend the literal text &amp;lsquo;{CRYPT}&amp;rsquo; on the password hash field!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;NB: We had already done the donkey work of syncing user and group IDs across our two servers - we were lucky to have very few clashes! Retro fitting common user credentials to disparate systems is always going to be messy&amp;hellip; :)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Whilst getting setup, we decided to create an administrator &lt;em&gt;user&lt;/em&gt; with permission to edit records. This avoids having to know or share knowledge of the rootDN password (that gives unlimited access to the data) with any client applications. We can then replicate the admin user&#39;s credentials. We also installed SSL/TLS certificates to provide secure access to clients if they needed it, using the system default &amp;lsquo;snakeoil&amp;rsquo; keys :) This requires us to edit the configuration:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To modify the configuration database we cannot use rootDN access.&lt;br&gt;
We need this magic cmd, run as the root user:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;    # ldapmodify -Y EXTERNAL -H ldapi:/// -f &amp;lt;filename&amp;gt;.ldif
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;-Y EXTERNAL tells slapd to trust the OS user ID.&lt;br&gt;
UID 1 has &amp;lsquo;special&amp;rsquo; access granted in the default installation of slapd&lt;br&gt;
-H ldapi:/// tells ldapmodify to connect using the default Unix socket: /var/run/slapd/ldapi&lt;br&gt;
This enables slapd to locate the UID of the calling process&lt;/p&gt;
&lt;p&gt;With this we can adjust the Access Control List data for our regular user &amp;lsquo;admin&amp;rsquo;.&lt;br&gt;
admin-acl.ldif contains:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;    dn: olcDatabase={1}mdb,cn=config  
    changetype: modify  
    delete: olcAccess  
    -  
    add: olcAccess  
    olcAccess: to attrs=userPassword by dn.exact=&amp;quot;uid=admin,ou=people,dc=ashbysoft,dc=com&amp;quot; manage by self write by anonymous auth by * none  
    -  
    add: olcAccess  
    olcAccess: to attrs=shadowLastChange by dn.exact=&amp;quot;uid=admin,ou=people,dc=ashbysoft,dc=com&amp;quot; manage by self write by * read  
    -  
    add: olcAccess  
    olcAccess: to * by dn.exact=&amp;quot;uid=admin,ou=people,dc=ashbysoft,dc=com&amp;quot; manage by * read  
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;dn=config database section to update, - is required between commands.&lt;br&gt;
This ACL provides access to change the &lt;em&gt;userPassword&lt;/em&gt; field for &amp;lsquo;admin&amp;rsquo; and &lt;em&gt;self&lt;/em&gt;,&lt;br&gt;
to check authentication by the &lt;em&gt;anonymous&lt;/em&gt; user and to block any other access.&lt;br&gt;
(&lt;em&gt;self&lt;/em&gt; allows updates by the authenticated user to their own records)&lt;br&gt;
Note it must also provide similar access to &lt;em&gt;shadowLastChange&lt;/em&gt; field and&lt;br&gt;
provides update access to &amp;lsquo;admin&amp;rsquo; and read access to anyone for all other fields.&lt;/p&gt;
&lt;p&gt;We found the config database was divided up into several sections with different DNs.&lt;br&gt;
you should check your database names are correct and adjust accordingly.&lt;br&gt;
You can use this command to dump the config:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;    # ldapsearch -Y EXTERNAL -H ldapi:/// -b &#39;cn=config&#39; -s one -LLL -Q
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;This will dump the config database to stdout. You can ignore the &amp;lsquo;schema&amp;rsquo; elements,&lt;br&gt;
just look for the olcDatabase elements.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Exercise for the reader: can you find the magic ACL that allows root access to this data?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Here is the TLS/SSL certificate.ldif config file we used:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;    dn: cn=config  
    add: olcTLSCACertificateFile  
    olcTLSCACertificateFile: /etc/ldap/ca-certificates.crt  
    -  
    add: olcTLSCertificateKeyFile  
    olcTLSCertificateKeyFile: /etc/ldap/ssl-cert-snakeoil.key  
    -  
    add: olcTLSCertificateFile  
    olcTLSCertificateFile: /etc/ldap/ssl-cert-snakeoil.pem  
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;You will be getting familiar with this syntax by now!&lt;br&gt;
This config adds the default system &amp;lsquo;snakeoil&amp;rsquo; certificate &amp;amp; key.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;can-i-change-my-password&#34;&gt;Can I change my password?&lt;/h3&gt;
&lt;p&gt;We then needed to check what happened when a user executes the &amp;lsquo;passwd&amp;rsquo; utility.. it works! Well, yes and no. The LDAP stored credentials did update, but they also became hashed with a different algorithm - one very old and from the distant past which is NOT secure :( It turns out there is basically a fight between which components create the hash; the LDAP client software, or the LDAP server itself. There is a &#39;new&#39; method defined as part of an LDAP extension
&lt;a href=&#34;https://www.rfc-editor.org/rfc/rfc3062&#34;&gt;RFC 3062&lt;/a&gt; that allows the LDAP server to create the hash according to a &#39;policy&#39; set in the config. It turns out this policy is just two values (hash algorithm=CRYPT which directs slapd to the OS libcrypt() library, and salt format=&amp;quot;$6$%.6s&amp;quot; which tells libcrypt to select SHA512 and a 6-digit salt), but they are stored in different database sections - &lt;em&gt;sigh&lt;/em&gt;. The good news is that &lt;em&gt;nslcd&lt;/em&gt;, part of the latest PAM+LDAP integration package (as of Q1 2026) already supports this method and infact does NOT support any other!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;here is the crypt.ldif file we used:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;    dn: cn=config   
    changetype: modify  
    add: olcPasswordCryptSaltFormat  
    olcPasswordCryptSaltFormat: &amp;quot;$6$%.6s&amp;quot;  
       
    dn: olcDatabase={-1}frontend,cn=config   
    changetype: modify  
    add: olcPasswordHash  
    olcPasswordHash: {CRYPT}  
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT! Note the hash directive is in frontend, whilst the salt is in the root section. No idea why&amp;hellip;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;With this setup, we get reasonably secure crypto hashing of passwords. &lt;em&gt;BUT&lt;/em&gt; the shadow file was using a &amp;ldquo;$y$&amp;hellip;&amp;rdquo; salt format. This is a reference to &lt;em&gt;yescrypt&lt;/em&gt; which is a very modern, secure algorithm, so why did we not set this up? Unfortunately, we cannot select this as &lt;em&gt;yescrypt is not supported by some client tools yet&lt;/em&gt;. These tools do not understand what is in the password field and fail to display, check or update the password correctly. Notable among those tools is &lt;em&gt;phpLDAPadmin&lt;/em&gt;, possibly the most widely used FOSS LDAP management tool out there; boo! So SHA512CRYPT with a decent salt it is.. We have checked that such hashes can be exported back into a shadow passwd file and still work, (as they should since this was the default for Debian systems before yescrypt was introduced,) which is one of our requirements - to be able to back out a user credential to the file-based PAM system at any time, just incase (!)&lt;/p&gt;
&lt;h3 id=&#34;can-i-have-a-self-service-web-ui-with-that&#34;&gt;Can I have a self-service web UI with that?&lt;/h3&gt;
&lt;p&gt;OK, so the user can change their password from the shell prompt. But let&#39;s be honest, how many will really do that? We need a web UI for this. So began many hours of hunting around for LDAP client UI tools that supported this need.. and we finally stumbled onto the &lt;a href=&#34;https://ltb-project.org/&#34;&gt;LDAP Tools Project.&lt;/a&gt; This is a fantastic resource that happens to include exactly what we need - a basic web UI for user password change. Even better, they make this available as either a Debian package (from their own repository) or a container image from docker.io. Nice :) Since we are at the &#39;throwing at the wall and seeing if it sticks&#39; stage, we installed by container image. Now, had we done this &lt;em&gt;after&lt;/em&gt; the discovery of the password hashing conundrum, it would have saved a lot of time! As it was, the tool pretty much immediately worked, but left some wierd password hash that was nothing like the shadow file syntax and would not work there. Here began the journey of discovery about the aforementioned RFC 3062 and allowing the server to do the hashing. The default settings in this client are to create the hash itself (which uses whatever libcrypt version and configuration is in the container image, &lt;em&gt;not the OS one&lt;/em&gt;) and upload the string directly to the LDAP field. Oops. Fortunately, the tool has a config value the lets it use RFC 3062. Win!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;here is the tweaked config for this tool to match our ACLs and crypt setup:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;    $ldap_url = &amp;quot;ldaps://&amp;lt;server address&amp;gt;&amp;quot;;  
    putenv(&amp;quot;LDAPTLS_REQCERT=allow&amp;quot;);  
    putenv(&amp;quot;LDAPTLS_CACERT=/etc/ssl/certs/ca-certificates.crt&amp;quot;);  
    # use anonymous bind to check pwd  
    $ldap_binddn = null;  
    $who_change_password = &amp;quot;user&amp;quot;;  
    $ldap_base = &amp;quot;dc=ashbysoft,dc=com&amp;quot;;  
    $ldap_login_attribute = &amp;quot;uid&amp;quot;;  
    # use RFC3062 EXOP to make LDAP server do the encryption  
    $ldap_use_exop_passwd = true;  
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Note we needed to allow self-signed certificates via &lt;em&gt;LDAPTLS_REQCERT=allow&lt;/em&gt;&lt;br&gt;
We do not need to use rootDN or even admin user access to check passwords&lt;br&gt;
just anonymous and we can use &amp;lsquo;user&amp;rsquo; to update the password via RFC3062 method.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;can-i-have-an-admin-ui-tool-with-that&#34;&gt;Can I have an admin UI tool with that?&lt;/h3&gt;
&lt;p&gt;In addition to finding this great set of user tools, we came across a number of other LDAP &#39;admin&#39; tools and we thought it would be prudent to have one of these handy as cryptic cmdline tools are an extra cognitive load during any debugging/emergency situation later.. we can recommend &lt;a href=&#34;https://phpldapadmin.org/&#34;&gt;phpLDAPadmin&lt;/a&gt; however be aware of it&amp;rsquo;s limitation with &lt;em&gt;yescrypt&lt;/em&gt; support. Otherwise it seems excellent, and is again available as Debian package or container image. We have the container version running right now..&lt;/p&gt;
&lt;h2 id=&#34;can-we-synchronise-two-servers&#34;&gt;Can we synchronise two servers?&lt;/h2&gt;
&lt;p&gt;Now, all this is very nice on one server, but what happens if it goes offline? How do our users log in on the other server to continue reading their email if the LDAP service is down? This is where we need replication, so we can run an LDAP server local to each site and keep them in sync as the data is updated.&lt;/p&gt;
&lt;h3 id=&#34;lets-use-openldap-sync&#34;&gt;Let&#39;s use OpenLDAP sync&amp;hellip;&lt;/h3&gt;
&lt;p&gt;Those of you more familiar with OpenLDAP will perhaps know it already comes with &lt;a href=&#34;https://openldap.org/doc/admin26/replication.html&#34;&gt;replication tools&amp;hellip;&lt;/a&gt; and indeed supports N-way synchronisation between 2 or more servers. Great! We tried to set this up; I&amp;rsquo;m sure it is possible somehow but we really struggled with the complexity of it. First it won&amp;rsquo;t work without SSL/TLS connections. Then it needs some Access Control List setup to allow servers to talk to each other. Then it needs a cron / systemd timer job to invoke the sync, or separate processes monitoring the DB for changes, then there is a queue of transactions to manage in a file, then&amp;hellip; wow. All with cryptic command line tools. The list went on. Well done if you have set this up successfully on your site - we can see that for 1000&#39;s of accounts and 10&#39;s of servers it may prove worth the effort to understand and maintain. We didn&amp;rsquo;t bother; we felt this was too complex to manage and remember what to do in an emergency. It is also very opaque to monitor.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;No :(&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;lets-use-syncthing-instead&#34;&gt;Let&#39;s use Syncthing instead&amp;hellip;&lt;/h3&gt;
&lt;p&gt;We have already got reliable, cross-site file replication working nicely thanks to &lt;a href=&#34;https://syncthing.net/&#34;&gt;&lt;em&gt;syncthing&lt;/em&gt;&lt;/a&gt;; a simple to manage tool available in most distributions with a simple to manage replication setup and decent web UI. Can we leverage this for LDAP sync? Why, yes of course! If one takes a close look at the built-in synchronisation, really all it is doing is exporting records when they change, queueing them for delivery to the other sites and importing them when they arrive. There is a &lt;em&gt;lot&lt;/em&gt; of extra complexity in trying to export the minimal amount of changes and account for network failures, slower delivery, etc. There is also a big warning about &#39;split brain&#39; situations where changes can occur in multiple servers to the same records at the same time (e.g. during a network outage) and resolving this later is a nightmare. Our situation is much simpler; we only expect the password field to change during self-service requests. This is the only thing we need to sync up. Any other change is manual administrator work and we can replicate it ourselves by whatever means we choose. So with this in mind, we can approach this in a very crude way:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;run strictly in master/slave to avoid split brain. Only change passwords on the master (by only running the self-service web UI tool there.)&lt;/li&gt;
&lt;li&gt;run a sync on a timer at the master - we chose 10 minutes as a reasonable time to replicate a password change. If the system fails in this window, the users will already know about it and can repeat the change action themselves if they wish on the recovered system.&lt;/li&gt;
&lt;li&gt;export all the password hash fields at once - there are a few 10&#39;s of user accounts. No point being smart here, just dump them all out to temporary files.&lt;/li&gt;
&lt;li&gt;identify each file with user&amp;rsquo;s DN from LDAP. This is guaranteed to be unique as it is also the database key.&lt;/li&gt;
&lt;li&gt;check if each temporary file is different from the one currently being replicated - if yes, update the replicated copy. Then delete all the temporaries.&lt;/li&gt;
&lt;li&gt;let syncthing resolve the replication across sites with version monitoring, queuing, recovery, etc.&lt;/li&gt;
&lt;li&gt;run a monitor script at the receiver that checks each replicated file timestamp every few seconds. The number of files is tiny, so again no point being smart. Just check all timestamps&lt;/li&gt;
&lt;li&gt;import the password hash field if a file updates.&lt;/li&gt;
&lt;li&gt;to bootstrap the system, simply run the dump to make a initial dataset, then start the updater which will read the initial timestamps to monitor.&lt;/li&gt;
&lt;li&gt;to restart either end, we just need a replicated file set locally to compare against. This should always be there once bootstrapped.&lt;/li&gt;
&lt;li&gt;to force an update, simply &#39;touch&#39; a file in the replicated set and it will be updated in the receiver.&lt;/li&gt;
&lt;li&gt;if a user is added, their file will appear in the replicated set when dumped. New files will be imported at the receiver then monitored.&lt;/li&gt;
&lt;li&gt;if a user is removed, their replicated file can simply be deleted and the receiver script restarted to remove the in-memory state.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that we do not have to care about the direction of sync with syncthing - it is N-way capable already. We simply either run the sync dump or the update scripts as required for master or slave status of the site. Having the replicated copies locally on the machine provides the startup state we need.
This solution does depend on the system clock NOT going backwards between sync runs&amp;hellip; but then lots of stuff will likely also break if the system clock is out by that much!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Yes!&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;here is the dump script:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;    #!/bin/sh  
    # script to dump user passwords from LDAP and update any changed data to a target folder for sync  
    target=&amp;quot;/var/lib/ldapsync&amp;quot;  
    tmpbase=&amp;quot;/tmp/ldapsync&amp;quot;  
    tmpf=&amp;quot;$tmpbase/$$&amp;quot;  
    admindn=&amp;quot;cn=admin,dc=ashbysoft,dc=com&amp;quot;  
    adminpwd=&amp;quot;/etc/ldap/rootDN.pwd&amp;quot;  
       
    # make sure only root can rwx our files..  
    umask 0077  
       
    [ ! -d &amp;quot;$target&amp;quot; ]  &amp;amp;&amp;amp; echo &amp;quot;target $target missing, exiting&amp;quot;&amp;gt;&amp;amp;2 &amp;amp;&amp;amp; exit 1  
    echo &amp;quot;mkdir -p $tmpf&amp;quot;  
    mkdir -p &amp;quot;$tmpf&amp;quot;  
    cd &amp;quot;$tmpf&amp;quot;  
    ldapsearch -H ldapi:/// -x -D $admindn -y $adminpwd -b &#39;ou=people,dc=ashbysoft,dc=com&#39; -s one -LLL userPassword |awk -v RS= &#39;{print &amp;gt;(&amp;quot;user&amp;quot; NR &amp;quot;.ldif&amp;quot;)}&#39;  
    for f in user*.ldif; do o=$(awk -F: &#39;/dn:/ {print $2}&#39; $f |tr -d &#39; &#39;); mv &amp;quot;$f&amp;quot; &amp;quot;$o&amp;quot;; done  
    for f in uid*; do cmp -s &amp;quot;$f&amp;quot; &amp;quot;$target/$f&amp;quot; &amp;amp;&amp;amp; continue; echo &amp;quot;update $f&amp;quot;; cp &amp;quot;$f&amp;quot; &amp;quot;$target&amp;quot;; done  
    echo &amp;quot;rm -r $tmpf&amp;quot;  
    rm -r &amp;quot;$tmpf&amp;quot;  
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Note we keep the admin credentials in a separate file,&lt;br&gt;
we use &lt;em&gt;ldapsearch&lt;/em&gt; to extract the &lt;em&gt;userPassword&lt;/em&gt; field only&lt;br&gt;
and feed it to a funky awk script that saves the output to separate files.&lt;br&gt;
We then rename the files using their dn= line (more funky awk!)&lt;br&gt;
compare them to the previous files and update any changed ones.
&lt;em&gt;/var/lib/ldapsync&lt;/em&gt; is the folder syncthing is sharing.&lt;/p&gt;
&lt;p&gt;and here is the update script:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;    #!/bin/bash
    # get a list of file timestamps and update userPassword for each one that has changed
    target=&amp;quot;/var/lib/ldapsync&amp;quot;
    delay=10
    debug=&amp;quot;&amp;quot;
    admindn=&amp;quot;cn=admin,dc=ashbysoft,dc=com&amp;quot;
    adminpwd=&amp;quot;/etc/ldap/rootDN.pwd&amp;quot;

    [ ! -d &amp;quot;$target&amp;quot; ] &amp;amp;&amp;amp; echo &amp;quot;$target folder missing, exit 1&amp;quot; &amp;gt;&amp;amp;2 &amp;amp;&amp;amp; exit 1

    cd &amp;quot;$target&amp;quot;
    echo &amp;quot;process target: $(pwd)&amp;quot;
    echo &amp;quot;initialise time stamps&amp;quot;
    declare -A ts
    for f in uid*
    do
        ts[$f]=$(stat -c &#39;%Y&#39; $f)
        [ -n &amp;quot;$debug&amp;quot; ] &amp;amp;&amp;amp; echo &amp;quot;$f: ${ts[$f]} &amp;quot;
    done

    # loop to wait for ts updates
    # timestamp must move forward to update - old files are ignored
    # ts[$f] returns &amp;quot;&amp;quot; for new files so they will be processed and added to ts
    # removing files prevents further update but does not clear ts
    echo &amp;quot;wait for updates; delay: $delay&amp;quot;
    while true
    do
        sleep $delay
        for f in uid*
        do
	        t=$(stat -c &#39;%Y&#39; $f)
	        [ -n &amp;quot;$debug&amp;quot; ] &amp;amp;&amp;amp; echo &amp;quot;$f: ${ts[$f]}-&amp;gt;$t&amp;quot;
	        [[ &amp;quot;${ts[$f]}&amp;quot; -eq &amp;quot;$t&amp;quot; ]] &amp;amp;&amp;amp; continue
	        # ts changed, update
	        ts[$f]=$t
	        echo &amp;quot; update: $f-&amp;gt;$t&amp;quot;
	        # grok userPassword field and update LDAP
	        # dn: must occur first in LDIF, userPassword may be followed by continuation lines with &#39; &#39; first char
	        # also awk does not support filenames with &#39;=&#39; char so use cat |awk here!
	        pwdupdate=$(cat &amp;quot;$f&amp;quot; |awk &#39;/dn:/ {inpwd=0; print $0&amp;quot;\nchangetype: modify&amp;quot;}
			        /userPassword:/ {inpwd=1; print &amp;quot;replace: userPassword\n&amp;quot;$0; next}
			        /^ / {if (inpwd==1) print $0}
			        !/^ / {inpwd=0}&#39;)
                [ -n &amp;quot;$debug&amp;quot; ] &amp;amp;&amp;amp; echo &amp;quot;$pwdupdate&amp;quot;
                echo &amp;quot;$pwdupdate&amp;quot; | ldapmodify -H ldapi:/// -x -D $admindn -y $adminpwd
        done
    done
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Mmm some more funky awk hacking for you :)&lt;br&gt;
This awk groks the dn and userPassword fields from the source file&lt;br&gt;
and removes anything else as we don&amp;rsquo;t want to update random stuff.&lt;br&gt;
It outputs an .ldif that modifies the existing user record.&lt;br&gt;
Why the &lt;em&gt;inpwd&lt;/em&gt; stuff?&lt;br&gt;
This is because the .ldif format enforces continuation lines&lt;br&gt;
after 72 chars and we have to track that keep the lines we need.&lt;br&gt;
Nasty. Hence the debug lines!!&lt;/p&gt;
&lt;p&gt;I suggest this is still easier and more transparent than OpenLDAP sync&amp;hellip;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;can-we-do-sso-now&#34;&gt;Can we do SSO now?&lt;/h2&gt;
&lt;p&gt;No. LDAP provides a single reference source of authentication credentials and other user metadata to authentication tools like PAM. It does not provide a transferrable &#39;token&#39; that can be used to log in to multiple services. That needs another technology layer&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;emailcalendarcontacts---ldap-only&#34;&gt;eMail/calendar/contacts - LDAP only&lt;/h3&gt;
&lt;p&gt;Some applications do not really support the idea of SSO, like a single email account. The access protocols here are &lt;a href=&#34;https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol&#34;&gt;IMAP&lt;/a&gt; and &lt;a href=&#34;https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol&#34;&gt;SMTP&lt;/a&gt;, both of which require a username/password credential. There is no &#39;token&#39; style login, so LDAP has provided us a single point of control for the password but not single sign-on. Calendar and contacts are similar if they use the standardised WebDAV based solutions of &lt;a href=&#34;https://en.wikipedia.org/wiki/CalDAV&#34;&gt;CalDAV&lt;/a&gt; and &lt;a href=&#34;https://en.wikipedia.org/wiki/CardDAV&#34;&gt;CardDAV&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Our chosen email IMAP solution is &lt;a href=&#34;https://www.courier-mta.org/imap/&#34;&gt;courier-imap&lt;/a&gt; which operates using the OS authentication and home directories to locate the users &lt;a href=&#34;https://en.wikipedia.org/wiki/Maildir&#34;&gt;Maildir&lt;/a&gt; folder. Similarly, our chosen email SMTP solution is &lt;a href=&#34;https://www.exim.org/&#34;&gt;exim4&lt;/a&gt; which also authenticates users using OS authentication and home directory via PAM to locate any .forward files and to deliver email files to their Maildir. Our chosen CalDAV/CardDAV solution is &lt;a href=&#34;https://radicale.org/v3.html&#34;&gt;radicale&lt;/a&gt; through which we delegate authentication to IMAP.&lt;/p&gt;
&lt;p&gt;This is the best we can do with eMail protocol level access that supports dedicated eMail client software like Thunderbird, Evolution, etc. We might be able to do better with a webmail client.. maybe. This is perhaps also why GMail desktop services are web based!&lt;/p&gt;
&lt;h3 id=&#34;jellyfin-part-1---ldap&#34;&gt;jellyfin part 1 - LDAP&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://jellyfin.org/&#34;&gt;jellyfin&lt;/a&gt; comes with an LDAP plugin built in. Yaay! Atfer some poking about, we made this work and could provide authentication externally to the jellyfin user database, so that was nice. But it&#39;s not SSO. And we still need to make accounts in jellyfin first, then set their authentication check to LDAP&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;immich-part-1---no&#34;&gt;immich part 1 - No&amp;hellip;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://immich.app/&#34;&gt;immich&lt;/a&gt; comes with many plugins - none of which do LDAP authentication :(&lt;/p&gt;
&lt;h2 id=&#34;domoticz-part-1---no&#34;&gt;Domoticz part 1 - No&amp;hellip;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://domoticz.com/&#34;&gt;Domoticz&lt;/a&gt; does not come with any authentication plugins. It also does not use OS authentication :(&lt;/p&gt;
&lt;h2 id=&#34;ok-so-how-do-we-do-sso&#34;&gt;OK so how do we do SSO?&lt;/h2&gt;
&lt;h3 id=&#34;single-what-now&#34;&gt;Single what now?&lt;/h3&gt;
&lt;p&gt;Single sign-on requires a token that can be trusted and passed around to different services as an indicator that the user has &#39;logged on&#39; to a &lt;em&gt;realm&lt;/em&gt; and can therefore be allowed access to all services that are also registered with the same &lt;em&gt;realm&lt;/em&gt;. One technology layer that does this is Open Authorization, specifically version 2.0. &lt;a href=&#34;https://auth0.com/intro-to-iam/what-is-oauth-2&#34;&gt;OAuth2.0&lt;/a&gt; supports a range of use cases and deliberately does not specify how &lt;em&gt;client&lt;/em&gt; software can register with a &lt;em&gt;realm&lt;/em&gt; nor exchange keys with the same. There is a layer above OAuth2.0 called &lt;a href=&#34;https://openid.net/developers/how-connect-works/&#34;&gt;Open ID Connect&lt;/a&gt; that provides usage profiles of OAuth2.0 and extends the specification so client software can interact with realm software and discover how to manage the user and how to check their token.&lt;/p&gt;
&lt;p&gt;Clearly the &lt;em&gt;client&lt;/em&gt; software is our service application, like jellyfin, immich and Domoticz.&lt;/p&gt;
&lt;p&gt;So, what is this magic &lt;em&gt;realm&lt;/em&gt; software? You may find it under a few different names:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OpenID Provider (OP)&lt;/li&gt;
&lt;li&gt;Identity Provider (IdP)&lt;/li&gt;
&lt;li&gt;Identity and Access Management (IAM) &amp;lt;&amp;ndash; you&#39;ve probably seen this one from AWS :)&lt;/li&gt;
&lt;li&gt;Authorization server &amp;lt;&amp;ndash; this is the OAuth terminology&lt;/li&gt;
&lt;li&gt;OIDC server&lt;/li&gt;
&lt;li&gt;OAuth server&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;hellip;blah blah blah. There seems to be a lot of twaddle and marketing-speak around this stuff as it&#39;s all big corporates and big money stuff doing security!&lt;/p&gt;
&lt;p&gt;We have evaluated a few software packages that can provide this service - we have (so far) picked &lt;a href=&#34;https://www.keycloak.org/&#34;&gt;Keycloak&lt;/a&gt; as the most reasonable looking balance of: it working without huge bootstrap pain, being too opaque to understand / too badly documented to configure in a few hours, too huge and cumbersome for our little servers to handle it or need all the things it does. Also it &lt;em&gt;must&lt;/em&gt; be able to reference/import user credentials from LDAP and provide &lt;em&gt;full OIDC&lt;/em&gt;, not just OAuth2.0.&lt;/p&gt;
&lt;p&gt;We looked at:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://tinyauth.app/&#34;&gt;TinyAuth&lt;/a&gt; - this is not an IAM and does not do OIDC. It might fit your need for login controls for a basic web site.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.authelia.com/&#34;&gt;Authelia&lt;/a&gt; - this might be an IAM. When we had spent the best part of 3 hrs trying to get it even to start up, we moved on. Shame, it looked quite efficient!&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://goauthentik.io/&#34;&gt;Authentik&lt;/a&gt; - this is a whopper! It worked, but we struggled to get it to load users from LDAP. It sucked up resources. It&#39;s also quite commercial in $$$.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.keycloak.org/&#34;&gt;Keycloak&lt;/a&gt; - this is the best balance we think. I&amp;rsquo;d expected a JVM in a container to be slow as h*ll, but it&amp;rsquo;s really not! Also memory footprint is OK. UI is clean!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;immich-part-2---oidc&#34;&gt;immich part 2 - OIDC&lt;/h3&gt;
&lt;p&gt;So.. onwards with Keycloak, in a container deployment again. There are guide websites to setup Authentik with immich; after a bit more yak shaving we got keycloak to connect up and do the token thing by &lt;a href=&#34;https://integrations.goauthentik.io/media/immich/&#34;&gt;following the Authentik guide&lt;/a&gt; and adjusting for keycloak&amp;rsquo;s terminology/UI shifts. Yaay! We also got it to import LDAP users after poking it in the right place (apparently this is &#39;user federation&#39; these days&amp;hellip;) and hooray! It can issue tokens from the LDAP credentials!&lt;/p&gt;
&lt;p&gt;So we are done, right?
&lt;em&gt;For immich - pretty much yes!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Just a tweak to configure immich to allow new users automatically and that&amp;rsquo;s it. Once the users exist in immich you can share content/etc. as normal. Logout is clean and directs the user back to the Keycloak logout page. Great!&lt;/p&gt;
&lt;h3 id=&#34;jellyfin-part-2---oidc&#34;&gt;jellyfin part 2 - OIDC&lt;/h3&gt;
&lt;p&gt;More yak shaving. Jellyfin has a &lt;a href=&#34;https://github.com/9p4/jellyfin-plugin-sso&#34;&gt;plugin that supports OIDC/OAuth2.0.&lt;/a&gt; It is &#39;alpha&#39; by declaration of the owner/developer. It is however used in &lt;em&gt;every&lt;/em&gt; example I have seen of how to enable OIDC for jellyfin! I guess it is the only one out there&amp;hellip; surprisingly, it does work. The config UI is awful and cannot even show you the previous values you have entered. So you have to retype ALL the data every time you tweak something. Nice.&lt;/p&gt;
&lt;p&gt;BUT&amp;hellip; it works! Great! You have to make your own HTML/CSS login button by abusing the &amp;lsquo;branding&amp;rsquo; area of the login screen :) Logout does not work; it returns to the jellyfin login screen but you can press &amp;rsquo;login with keycloak&amp;rsquo; and it goes straight back in. No realm logout is invoked. So I made a new &amp;rsquo;logout from keycloak&amp;rsquo; button on the login screen by abusing the branding HTML area a bit more&amp;hellip; It&#39;s working OK. It creates new users automatically. Can I remember the options I chose when I entered the form data? NO :( Hope I wrote it down&amp;hellip; (I did.)&lt;/p&gt;
&lt;h3 id=&#34;domoticz-part-2---oidc-error&#34;&gt;Domoticz part 2 - OIDC Error&amp;hellip;&lt;/h3&gt;
&lt;p&gt;Oh boy&amp;hellip; (!) Domoticz have a funny &#39;take&#39; on OIDC. Their wiki says they support it and they describe how to configure a client app to access the server, but they kinda don&#39;t say only if you use the Domoticz server as the IAM as well. They solved a different problem - how to enable Android and iOS phone apps to do OIDC authentication so they do not store passwords out there in the big, wide world. Seems a good starting place for using tokens, and credit for going the OIDC route. Shame it is unusable regard using external IAMs (yet) because it makes several assumptions about what must be included in the token&amp;hellip;&lt;/p&gt;
&lt;p&gt;We tried, for many hours, to understand the &lt;a href=&#34;https://github.com/domoticz/domoticz/blob/e7debf54e84b3a167bacac4d95e2a48e40965156/webserver/cWebem.cpp#L1846&#34;&gt;code paths in Domoticz&lt;/a&gt;. We can see it has a parser for JWT tokens which we know Keycloak issues; this follows the OIDC standard. We can also see it checks the token signature against a key stored in the Domoticz database, which is good! We managed to get the key installed from Keycloak and it worked! Yaay! But now the token is rejected because Domoticz uses the JWT &lt;em&gt;claim&lt;/em&gt; fields (OAuth has wierd names for stuff) for unusual purposes. Vis:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;aud&lt;/em&gt; string must contain one value and this must be the client_id which we can store in the Domoticz DB (as a username!) &lt;em&gt;This is OK! We can do this!&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;signature must be PS256 algorithm - we can do this too, and we can import the public key into the client_id user record in the Domoticz DB. &lt;em&gt;OK!&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;issuer&lt;/em&gt; URL must be &amp;ldquo;https://$hostname:$port/&amp;rdquo; of the Domoticz server. Can&#39;t use external IAM then? &lt;em&gt;OOPS :(&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;subject&lt;/em&gt; string must be a valid username stored in the Domticz DB. Keycloak passes UUID values, not under our control. We can&#39;t do this. &lt;em&gt;OOPS :(&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;key_id&lt;/em&gt; string must be an ASCII number that matches the username record in the Domoticz DB. This is NOT how key_id works in OIDC! &lt;em&gt;OOPS :(&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For these reasons, OIDC will currently not work with Domoticz and an external IAM. I have no doubt their own IAM can make a JWT token like they expected. This is no use to man or beast as Domoticz cannot import users from LDAP and we cannot shove in the password hashes ourselves as Domoticz uses MD5 hashing which we don&#39;t. Plus we want SSO, not just password changes.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;No SSO for you:(&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;domoticz-part-3---oauth-proxy-ftw&#34;&gt;Domoticz part 3 - OAuth Proxy FTW&lt;/h3&gt;
&lt;p&gt;We do not give up easily. Domoticz supports other means to provide external credentials, notably it supports Basic Authorization (and ancient X.509 Authorization) headers. Nice! These accept a username and clear text password that must match the Domoticz DB user data. Awesome!&lt;/p&gt;
&lt;p&gt;So.. is there a way to provide a web front-end that &lt;em&gt;can&lt;/em&gt; handle OIDC SSO and generate an Authorization header from it, then proxy requests from our browser? You bet there is! Say hello to &lt;a href=&#34;https://oauth2-proxy.github.io/oauth2-proxy/&#34;&gt;Oauth2 Proxy&lt;/a&gt; - the weapon of choice for adding OIDC capabilities to legacy apps!&lt;/p&gt;
&lt;p&gt;This little beauty is available as a pre-built Go binary or container (you know which I chose by now&amp;hellip;) and acts as an OIDC &lt;em&gt;client&lt;/em&gt; to login to the realm and request the magic JWT token. Once done, it passes the token back to the web browser in a cookie and becomes a HTTP proxy. Now every time a request flows through, it checks the token is valid, does a renewal with the IAM if required, and passes the request on to the upstream web server you have protected. Nice. If the token expires or is not renewed, boom! 401 unauthorised for you! Job done, right? Yes and no&amp;hellip;&lt;/p&gt;
&lt;p&gt;Remember we need a Basic Authorization header. This needs a username and password that matches Domoticz. Well, it turns out that oauth2-proxy can generate just such a header for us. Great! Turns out it also uses the JWT &lt;em&gt;subject&lt;/em&gt; claim field for the username. Not great. This is that pesky UUID we saw before. However, there is also an option to prefer the &lt;em&gt;email&lt;/em&gt; string as the username - now we&#39;re talking :) We can configure users in Domoticz with email addresses for usernames. Done right? Not quite - we still need a password. Now, given we have done a &lt;em&gt;real&lt;/em&gt; user login in the oauth2-proxy to get the JWT token, we can trust the username is legit. The password serves &lt;em&gt;no purpose&lt;/em&gt; anymore as we have already authenticated this username. So we can make them &lt;em&gt;ALL THE SAME&lt;/em&gt; and use a static string here to just get by the Domoticz password check logic. OK? Turns out oauth2-proxy has a configuration to do exactly that already! I love this little guy :)&lt;/p&gt;
&lt;p&gt;So that is what we do now: create new users in Domoticz with email usernames and the same fixed string password. Configure the password in oauth2-proxy and send this in the Authorization header. Bingo! It WORKS! Hooray! Here is our oauth2-proxy config snippet:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    pass_basic_auth=&amp;quot;true&amp;quot;
    set_basic_auth=&amp;quot;true&amp;quot;
    basic_auth_password=&amp;quot;xxxxxxxxxxxxx&amp;quot;
    prefer_email_to_user=&amp;quot;true&amp;quot;
    # to use this from nginx SSL proxy we need this:
    reverse_proxy=&amp;quot;true&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;domoticz-part-4---logout-how&#34;&gt;Domoticz part 4 - Logout how?&lt;/h3&gt;
&lt;p&gt;So login works fine, but we press Logout in the Domoticz and as if by magic, we go straight back to the Dashboard page! This is to be expected; the Domoticz service has no idea we are connecting via the oauth2-proxy and thus we remain logged in, sending the Authorization header. How do we log out of this thing?&lt;/p&gt;
&lt;p&gt;The guide has some instructions for us: first we call the oauth2-proxy endpoint to remove the session, and this can redirect the browser to the Keycloak logout endpoint for us. Nice! BUT&amp;hellip; Domoticz web UI is all JavaScript and API calls, not web pages at all! What to do?&lt;/p&gt;
&lt;p&gt;More yak shaving followed - we tried to block the API calls only; this results in a screen saying &#39;Domoticz is Offline&#39; which is hilarious, but useless. We tried to log out of Keycloak, but the proxy just carries on working until the JWT expires and won&#39;t refresh. Then we noticed Domoticz has a Custom HTML template facility we can abuse&amp;hellip; hehe. A bit like the branding HTML area abuse in jellyfin, we can add a URL button to the Custom menu in Domoticz that calls the required logout URL and we&amp;rsquo;re done! Hooray!&lt;/p&gt;
&lt;p&gt;Here is the logout URL from Domoticz:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    https://&amp;lt;oauth2 server&amp;gt;/oauth2/sign_out?rd=http%3A%2F%2F&amp;lt;keycloak server&amp;gt;%2Frealms%2Fashbysoft-realm%2Fprotocol%2Fopenid-connect%2Flogout
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Note the URLencoding of the redirect URL to direct the browser to keycloak logout screen after oauth2-proxy logout.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;domoticz-part-5---restore-the-nginx-ssl-proxy&#34;&gt;Domoticz part 5 - restore the Nginx SSL Proxy&lt;/h3&gt;
&lt;p&gt;You thought we were done here :)&lt;/p&gt;
&lt;p&gt;Some things are left to tidy up. Unlike all our other services which reside behind our Wireguard VPN and do NOT use SSL (why bother for LAN only?) Domoticz needs to be exposed to the Public Internet. This is so we can get to it without fussing about with VPNs&amp;hellip; and so our phone apps work.&lt;/p&gt;
&lt;p&gt;Prior to implementing SSO, we exposed the Domoticz port via an Nginx proxy that terminated the SSL connection and forwarded requests. This we continue to do for the legacy phone apps that cannot handle SSO. For interest and amusement, we would like to expose the SSO web UI as a public end point. We may consider adding other services to the public rosta later&amp;hellip;&lt;/p&gt;
&lt;p&gt;So - oauth2-proxy comes with some &lt;a href=&#34;https://oauth2-proxy.github.io/oauth2-proxy/configuration/integrations/nginx/&#34;&gt;guidance how to setup nginx&lt;/a&gt; to do the donkey work of the proxying, checking with the oauth-proxy endpoint if the request should be passed on or not. This is done using the auth_request module in nginx, which makes a sub request using the cookie from the browser and gets either 2xx or 401 status code in reply. We need to configure the oauth2-proxy to return our Authorization header in the auth check response, and we include this in the proxy request to Domoticz as before. We also need to adjust the redirect URL to return the browser to the public address, not the internal one when logging in. This means adding the URL to Keycloak and the whitelist in oauth2 also. Seems to work well&amp;hellip;&lt;/p&gt;
&lt;p&gt;BUT we can make it more efficient now we have a better proxy in nginx! If we review the Domoticz code paths, we see that only the API endpoint is checked for authorization. So we can replicate this in nginx with two &lt;em&gt;location&lt;/em&gt; blocks, one for &amp;ldquo;/json&amp;rdquo; which catches the API calls, and one for &amp;ldquo;/&amp;rdquo; which passes all others. This is great BUT - now we get no redirect to login when we open the home page! So we need a third &lt;em&gt;location&lt;/em&gt; header which catches ONLY the home page and redirects to the login endpoint for us. Did you know you can have &lt;em&gt;location =/&lt;/em&gt; in nginx which matches exactly the / request and nothing else? Cool!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;..and that&#39;s how you shave the SSO yak.&lt;/strong&gt; Well done if you made it this far!&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>PVCS Tools</title>
      <link>https://www.ashbysoft.com/posts/pvcstools/</link>
      <pubDate>Wed, 11 Jun 2025 20:00:00 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/pvcstools/</guid>
      <description>Phil engages in lulz-driven development&amp;hellip;</description>
      <content:encoded>&lt;h1 id=&#34;pvcs-tools&#34;&gt;PVCS Tools&lt;/h1&gt;
&lt;p&gt;TL;DR: I have just created and published an open source library + command line interface (CLI) to extract information and file content
from PVCS log files - if this interests you, the code is on sourcehut as usual: &lt;a href=&#34;https://git.sr.ht/~phlash/pvcstools&#34;&gt;https://git.sr.ht/~phlash/pvcstools&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;so-err-why&#34;&gt;So err why?&lt;/h2&gt;
&lt;p&gt;If you remember the early days of revision control software on MS-DOS in the late 80s -&amp;gt; early 90s, you might remember the delightful
Polytron Version Control System, aka Polytron VCS, aka PVCS.&lt;/p&gt;
&lt;p&gt;PVCS was a popular commercial tool that provided similar capabilities to RCS (which was open source and ~1 year older by release date, but
very much Unix / Posix based, so not available as a port to MS-DOS).&lt;/p&gt;
&lt;p&gt;I used it both in work at BT for my day job, &lt;em&gt;and&lt;/em&gt; at home to manage my own stuff. So far, so dull&amp;hellip;&lt;/p&gt;
&lt;p&gt;At the monthly tech meetup I attend (aka &amp;ldquo;nerd beers&amp;rdquo;), a friend reminded me of some toy software we had created that linked message
boards together across Netware file servers (the message board package was Threadz Pinboard), to create a message &amp;ldquo;inter-network&amp;rdquo;.
Later that evening I had a rummage in my archives and &lt;em&gt;found the code&lt;/em&gt; - great, I can now pop that on a 3.5&amp;quot; floppy and present my
friend with it next month as a surprise / late present from 1992 :)&lt;/p&gt;
&lt;p&gt;Now the yak shaving began&amp;hellip; the code was managed using PVCS but there were no checked out source files, all I had were the control
files, aka log files, in their proprietary binary format. No problem I thought, I&amp;rsquo;ll go grab an old archive of pvcs stuff from the
Inter-webs and extract the source - err nope, it turns out PVCS &lt;em&gt;still exists&lt;/em&gt; and is now an expensive (£1500/user) corporate service
platform owned / sold by Microfocus! Surely there is something from the past on &lt;a href=&#34;https://archive.org&#34;&gt;archive.org&lt;/a&gt; I can use.. also nope
(but see later). Oh well, it&amp;rsquo;s a 40 year-old file format, there will be open source tooling for that right&amp;hellip; also nope!&lt;/p&gt;
&lt;p&gt;So here I am needing to prank an old friend but without the tools to do it.. what&amp;rsquo;s an old hacker to do?&lt;/p&gt;
&lt;h2 id=&#34;reversing-the-format&#34;&gt;Reversing the format&lt;/h2&gt;
&lt;p&gt;I bite and decide to write some tooling that can extract source code from the log files. I have several hundred samples to look at
locally, some large and with lots of changes, others smaller and with only one revision in, time to dump some hex..&lt;/p&gt;
&lt;p&gt;It turns out that PVCS is very similar to RCS in keeping the latest file content, plus a series of &lt;em&gt;reverse deltas&lt;/em&gt; to recontruct earlier
revisions, it also supports symbolic names / &lt;em&gt;labels&lt;/em&gt; (we might say &lt;em&gt;tags&lt;/em&gt; in a modern VCS). There is a list of revision &lt;em&gt;locks&lt;/em&gt; and some
control metadata (such as the original file name, the originating user, etc.). All of this is visible in a logfile as plain text blocks,
with some surrounding binary goo. Closer examination between files shows consistent structure, with a fixed header, then a series of
Type-Length-Value (TLV) blocks, much like ASN.1 or Protobuf encoding. I work out how to step through these blocks, and to identify the
one holding the latest revision of the content, extracting that to stdout. Job done for the prank, but&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;the-one-that-got-away&#34;&gt;The one that got away&lt;/h2&gt;
&lt;p&gt;While looking for PVCS downloads in the wayback machine, I discover that Borland C/C++ V5 for Windows &lt;em&gt;supported PVCS natively&lt;/em&gt; as a
built-in version control backend, and &lt;em&gt;there is a CD image on archive.org&lt;/em&gt; :) Yoink!&lt;/p&gt;
&lt;p&gt;After much unpacking (nested 3 layers deep - thanks Borland), I find a specific win32 DLL that contains the PVCS logic, which appears
to have been supplied by Polytron to Borland (according to the copyright and version table strings within). I throw this into Ghidra
and take a quick look - it&amp;rsquo;s quite complicated, so I decide to put that aside and see what I can learn from the raw files first, which
turns out to be all I needed to extract source code - I might return to the decompiler if I ever want / need to know more.&lt;/p&gt;
&lt;h2 id=&#34;making-a-useful-tool&#34;&gt;Making a useful tool&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m enjoying the process of understaning the format, there are likely to be others out there facing a similar issue (always assume another
nerd shares your pain) and &lt;em&gt;there are no open source tools for PVCS&lt;/em&gt;. I feel obliged to finish the job and extend the tooling such that
it is possible to read useful metadata and retrieve &lt;em&gt;any revision&lt;/em&gt; from a logfile, then publish for the good of geekdom - hello!&lt;/p&gt;
&lt;h2 id=&#34;what-can-be-done&#34;&gt;What can be done&lt;/h2&gt;
&lt;p&gt;Read-only extraction of metadata and content revisions (by revision number or label). It&amp;rsquo;s unlikely ever to be possible to write a logfile
as there is too much unknown stuff (although some persistence with the decompiler might get there).&lt;/p&gt;
&lt;p&gt;Have fun and let me know if you use this!&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Introduction to the Fediverse</title>
      <link>https://www.ashbysoft.com/posts/fediverse/</link>
      <pubDate>Tue, 10 Jun 2025 19:00:00 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/fediverse/</guid>
      <description>Phil has found a great introduction video he wants to share</description>
      <content:encoded>&lt;h2 id=&#34;so-phil-whats-this-fediverse-thing&#34;&gt;So Phil, what&amp;rsquo;s this Fediverse thing?&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve been know to bang on about alternative social media for a couple of years now,
in particular the #Fediverse - now I can annoy you with a really nice video introduction
produced by the talented &lt;a href=&#34;https://mastodon.social/@_elena?ref=news.elenarossini.com&#34;&gt;Elena Rossini&lt;/a&gt;, enjoy!:&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://player.vimeo.com/video/1091422023?h=38d0c45f69&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;vimeo video&#34; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;

</content:encoded>
    </item>
    
    <item>
      <title>Phil Ashby CV</title>
      <link>https://www.ashbysoft.com/articles/phlash/cv/</link>
      <pubDate>Tue, 03 Jun 2025 17:00:00 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/phlash/cv/</guid>
      <description>Phil&amp;rsquo;s current CV</description>
      <content:encoded>&lt;!-- some html layout within hugo :) --&gt;
&lt;style type=&#34;text/css&#34;&gt;
.app-container { max-width: none; }
.column { float: left; width: 50%; padding: 1em; }
.grey { color: black; background: #d0d0d0; }
.row h1 { color: black; }
.row h2 { color: black; }
.row h3 { color: black; }
.row .column img { display: block; margin-left: auto; margin-right: auto; max-width: 100%; }
.white { color: black; background: white; }
.row:after { clear: both; }
&lt;/style&gt;
&lt;div class=&#34;row&#34;&gt;
&lt;div class=&#34;column grey&#34;&gt;
&lt;h1 id=&#34;philip-ashby&#34;&gt;Philip Ashby&lt;/h1&gt;
&lt;p&gt;&lt;img src=&#34;../cv-photo-sm.jpg&#34; alt=&#34;Photo of Phil&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;contact&#34;&gt;Contact&lt;/h1&gt;
&lt;hr&gt;
&lt;h3 id=&#34;address&#34;&gt;Address&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&amp;lt;on application&amp;gt;&lt;br/&gt;
Felixstowe&lt;br/&gt;
Suffolk.&lt;br/&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;phone&#34;&gt;Phone&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Mobile: &amp;lt;on application&amp;gt;&lt;br/&gt;&lt;/li&gt;
&lt;li&gt;Home: &amp;lt;on application&amp;gt;&lt;br/&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;email&#34;&gt;Email&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;mailto:phil@ashbysoft.com&#34;&gt;phil@ashbysoft.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;socials&#34;&gt;Socials&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Mastodon: &lt;a href=&#34;https://mastodon.me.uk/@phlash&#34;&gt;https://mastodon.me.uk/@phlash&lt;/a&gt;&lt;br/&gt;&lt;/li&gt;
&lt;li&gt;Website: &lt;a href=&#34;https://www.ashbysoft.com&#34;&gt;https://www.ashbysoft.com/&lt;/a&gt;&lt;br/&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;hobbies&#34;&gt;Hobbies&lt;/h1&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;Amateur radio satellite (AMSAT) development with the &lt;a href=&#34;https://funcube.org.uk&#34;&gt;FUNcube team&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Open source software maintainer (mostly my own toys!):&lt;br/&gt;
Sourcehut: &lt;a href=&#34;https://sr.ht/~phlash&#34;&gt;https://sr.ht/~phlash&lt;/a&gt;&lt;br/&gt;
Github: &lt;a href=&#34;https://github.com/phlash&#34;&gt;https://github.com/phlash&lt;/a&gt;&lt;br/&gt;&lt;/li&gt;
&lt;li&gt;Amateur geneology, collecting my family tree (currently ~900 people known, back to 1765).&lt;/li&gt;
&lt;li&gt;Sailing, I&amp;rsquo;m a qualified dinghy sailor and competent crew member on a yacht, with occasional
trips across the North Sea to Europe. Previously a speedboat owner (too old now!)&lt;/li&gt;
&lt;li&gt;Music, I&amp;rsquo;m a self-taught multi-instrumentalist, sound engineer and ex recording studio owner
(now replaced with a summer house since the children have left home!)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;education&#34;&gt;Education&lt;/h1&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;Masters Degree in Electronics, York, 1989&lt;/li&gt;
&lt;li&gt;A-levels in Mathematics, Further mathematics, Physics &amp;amp; Chemistry with S-level distinctions
in Physics &amp;amp; Chemistry, Broxbourne Grammer, 1985&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;certifications&#34;&gt;Certifications&lt;/h1&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;Member of Institute of Engineering and Technology (MIET)&lt;/li&gt;
&lt;li&gt;Member of British Computer Society (MBCS)&lt;/li&gt;
&lt;li&gt;Associate Member of Chartered Institute of Information Security (AMCIISec)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&#34;column white&#34;&gt;
&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;hr&gt;
&lt;p&gt;Phil is an experienced technical architect; happiest when being the conduit between technologists,
team leads, product owners, fellow architects, customers and leadership teams to guide effective
technical evolution for a business. Phil equally enjoys discovering new ideas and spaces, generating
prototypes, co-innovating with others&lt;sup&gt;1&lt;/sup&gt;, reading manuals&lt;sup&gt;2&lt;/sup&gt;, delivering service
evolution and continuous learning. Phil always likes to work his way out of a role by spreading
knowledge into teams. Phil believes trust matters and information silos are bad.
&lt;br/&gt;
&lt;br/&gt;
&lt;sup&gt;1&lt;/sup&gt; Not a fan of the word &amp;lsquo;brainstorming&amp;rsquo;&lt;br/&gt;
&lt;sup&gt;2&lt;/sup&gt; Has been known to read the GDPR!&lt;br/&gt;&lt;/p&gt;
&lt;h1 id=&#34;skill-highlights&#34;&gt;Skill highlights&lt;/h1&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;Architecture (C4 models, TOGAF, SDLCs &amp;amp; enterprise architectures, Cloud native engineering)&lt;/li&gt;
&lt;li&gt;Communication (within and around delivery teams)&lt;/li&gt;
&lt;li&gt;Reverse Engineering / Software archeology, for architecture discovery, security evaluation, occasionally source recovery!&lt;/li&gt;
&lt;li&gt;Forward Engineering, preferably in C#, Java, Python or C, but not a technology fundamentalist :)&lt;/li&gt;
&lt;li&gt;Operational Engineering, with cloud tooling (eg: ARM), operational visibility (eg: Datadog)&lt;/li&gt;
&lt;li&gt;Security Engineering / Information assurance including risk management and technical security
(ISO27001 &amp;amp; PCI-DSS compliance, security awareness training, previously a Certified Ethical Hacker)&lt;/li&gt;
&lt;li&gt;Information technologies, particularly: Windows Server, Linux, containers &amp;amp; VMs, config management&lt;/li&gt;
&lt;li&gt;Research and learning, especially in new &amp;amp; cross-boundary areas&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;experience&#34;&gt;Experience&lt;/h1&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;2013-2020: &lt;strong&gt;Technical architect for GB Group&lt;/strong&gt;, keeping the company technology evolving successfully as
it grew from ~300 people in the UK to ~1100 people in 40 global locations via product expansion and
aquisitions (I consulted into M&amp;amp;A team). I chaired the Design Authority Board as a core forum of
information exchange, and decision authorisation across the business. I led the evolution of company
platforms from isolated monoliths to interconnected services, allowing flexible service creation for
target markets. I contributed to the migration of a service from un-scalable hardware encryption to
Azure KeyVault. I discovered and documented historical systems on aquisition / retirement of owners.&lt;/li&gt;
&lt;li&gt;2007-2013: &lt;strong&gt;Security analyst for BT&lt;/strong&gt;, where I was part of a small hand-picked group of technology
experts providing investigation, risk assessment and mitigation development for BT and NCSC/GCHQ to
manage the (critical) national infrastucture risks of purchasing and deploying far-eastern telco
equipment into the core BT network. I have been unable to mention this until Feb 2019, when the
ex-technical director of NCSC published
&lt;a href=&#34;https://www.ncsc.gov.uk/blog-post/blog-post-security-complexity-and-huawei-protecting-uks-telecoms-networks&#34;&gt;this blog&lt;/a&gt;
(the paragraph below the final list of bullet points refers to us).&lt;/li&gt;
&lt;li&gt;2000-2007: &lt;strong&gt;Consultant with IDL&lt;/strong&gt;, providing various services to other organisations, ranging from
product design and development (eg: mobile games, high availability routers) to customer communications
(eg: BTexact website management and CMS).&lt;/li&gt;
&lt;li&gt;1996-2000: &lt;strong&gt;Technical lead for BT Wireplay&lt;/strong&gt;, where I led the development team creating the UK&amp;rsquo;s first
(inter-)national computer gaming platform, provided the early architectural designs and enjoyed my
only &amp;lsquo;Internet era startup&amp;rsquo;, from which I resigned after 12 months (it was already dead!)&lt;/li&gt;
&lt;li&gt;1989-1996: &lt;strong&gt;Developer in BT&lt;/strong&gt;, where I worked on both design and software development for automated
speech services (eg: Callminder/1571), speech recognition technology (using neural networks) and gained
valuble experience in operational services as Callminder went to production.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</content:encoded>
    </item>
    
    <item>
      <title>A Museum Piece</title>
      <link>https://www.ashbysoft.com/posts/museum_piece/</link>
      <pubDate>Fri, 25 Apr 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/museum_piece/</guid>
      <description>One does not expect to find something particularly rare buried in the back of a damp shed. But here we are! A genuine museum piece, from the late 1930s, intended for Admiralty use, we find a ship&#39;s radio by Marconi. We donated it to the Marconi Collection which is kept in Oxford Museum by radio history experts :)</description>
      <content:encoded>&lt;p&gt;Well well, if I were to ask you to name the most famous inventors in the world of communications, who
would you include? James Clerk Maxwell for his equations, Heinrich Rudolf Hertz for his demonstration
of electromagnetic waves, or Guglielmo Marconi for his engineering to turn theory into practice and
build the earliest working radio systems?&lt;/p&gt;
&lt;img alt=&#34;The Marconi RS-4 as found&#34; src=IMG_20231231_124508_303.jpg height=400&gt;
&lt;p&gt;Here we have the Marconi RS-4 as we found it, missing a couple of knobs and looking well used.&lt;/p&gt;
&lt;img alt=&#34;The Marconi RS-4 with the case off&#34; src=PXL_20240312_093109020.jpg height=400&gt;
&lt;p&gt;Here it is with the case off, showing that the interior chassis paint seems quite good condition.&lt;/p&gt;
&lt;img alt=&#34;The Marconi RS-4 internal view&#34; src=PXL_20240306_174827247.jpg height=400&gt;
&lt;p&gt;Here is the view inside the case, showing some dust and dirt however all the valves are in place and undamaged.&lt;/p&gt;
&lt;img alt=&#34;The Marconi RS-4 tuning capacitor rack&#34; src=PXL_20240306_181727159.jpg height=400&gt;
&lt;p&gt;Here is a close-up of the tuning capacitor rack, showing a little surface corrosion but otherwise ok.
The tuning dial still moves as well!&lt;/p&gt;
&lt;img alt=&#34;The Marconi RS-4 RF section valves&#34; src=PXL_20240306_181742931.jpg height=400&gt;
&lt;p&gt;Here is a close-up of the RF section valves, showing a mix of Osram and Marconi brands. Most likely
some have been replaced in service.&lt;/p&gt;
&lt;img alt=&#34;The Marconi RS-4 circuit diagram&#34; src=PXL_20240306_175111253.jpg height=400&gt;
&lt;p&gt;Inside the case we found a rather damp but intact circuit diagram!&lt;/p&gt;
&lt;img alt=&#34;The Marconi RS-4 model label&#34; src=PXL_20240306_174549466.PORTRAIT.jpg height=400&gt;
&lt;p&gt;The model label clearly shows the Type and a Serial number, along with the company name of
Marconi Wireless Telegram Co. Ltd. London. Also an &#39;Instrument No&#39;.&lt;/p&gt;
&lt;p&gt;The radio is now in the Marconi Collection. &lt;a href=&#34;https://www.mhs.ox.ac.uk/marconi/index.html&#34;&gt;More information here about the collection&lt;/a&gt;&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Valve gear renovation</title>
      <link>https://www.ashbysoft.com/posts/valve_gear_renovation/</link>
      <pubDate>Fri, 25 Apr 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/valve_gear_renovation/</guid>
      <description>Ahh, the warm glow of valve/tube powered electronics. What did you think I meant? Plumbing??</description>
      <content:encoded>&lt;p&gt;I have been restoring/renovating some olde worlde electronics recently, so I thought
I should write a blog post about it (now &lt;a href=&#34;https://www.ashbysoft.com/articles/phlash/&#34;&gt;Phil&lt;/a&gt;
has explained how our new website works!)&lt;/p&gt;
&lt;p&gt;This stems from the process of slowly clearing out my late Father-in-Law&#39;s farm sheds&amp;hellip;
We keep finding old, rusty things; some of which just scream at me to be repaired!&lt;/p&gt;
&lt;h2 id=&#34;1-the-american-army-radio&#34;&gt;#1 The American Army Radio&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;IMG20240219172039.jpg&#34; alt=&#34;RCA AR88D with a nice rusty patina&#34;&gt;&lt;/p&gt;
&lt;p&gt;Project #1 was a famous WWII radio receiver; the RCA AR88D, as seen in all good warzone
bunkers from about 1942 onwards. This particular model is quite early and flaking with
rust from the 50Kg steel shell. Yes, 50Kg! I can barely move it. This turns out to be
a good thing as it appears to have saved all the valves from high-G shock loads which
is generally what kills them.&lt;/p&gt;
&lt;p&gt;Suffice to say, once the rusty case was levered open I found a remarkably well preserved
chassis, with even some pencil marks to note servicing and repair work. Nice. At this
point I have no idea if any of the electronic components are serviceable - I do the
stupid thing and wire a plug onto it to try it - and surprise myself by it NOT emitting
magic smoke. Infact the lamps come on! But nothing else&amp;hellip;&lt;/p&gt;
&lt;p&gt;So after surviving doing the one thing you should &lt;em&gt;not&lt;/em&gt; do with old valve gear, it was time
to get out the voltmeter and start checking values against the circuit diagram&amp;hellip;
Unsurprisingly many components had been damaged by decades of damp ingress.&lt;/p&gt;
&lt;p&gt;Every single old oil filled paper+foil bypass capacitor was blown; leaky, unmeasurable
capacity, etc. These &#39;bathtub&#39; style components house 3 wound cylinders in a soldered metal
can and are bolted to the chassis. I decided to replace the innards and keep the cans for
a more authentic appearance.  Chopping my way in and scooping out the innards was messy but satisfying :)&lt;/p&gt;
&lt;p&gt;I also found there were capacitors marked &#39;Micamold&#39; that were infact just
paper and foil devices encased in bakelite. These also had all failed - cue more replacement
work.&lt;/p&gt;
&lt;p&gt;Finally a lot of the carbon film resistors had gone &#39;high&#39; and also needed replacing to get
the valve terminal voltages within spec. A few had blown entirely; mostly due to capacitor
leakage (see above!)&lt;/p&gt;
&lt;p&gt;On the upside, &lt;em&gt;all&lt;/em&gt; the valve heater filaments seemed to be intact! This is extraordinary!
I thank both the designers for specifying metal cased valves and the weight of the chassis
in damping any possible shocks.. I was hopeful we had a full set of working valves :)&lt;/p&gt;
&lt;p&gt;Also all the wound components seemed to have survived OK along with the oil-filled power supply
capacitors that are much larger and tougher than the bathtub types&amp;hellip;&lt;/p&gt;
&lt;p&gt;Time to make a CPC order for a handful of new ceramic 630V capacitors and get soldering!&lt;/p&gt;
&lt;p&gt;After a short wait and some painful soldering (access is NOT the best!) it was time to power
it up again! Quite unexpectedly the damn thing actually WORKED! Testing alongside a 1990s
Yaesu we find the frequency is &amp;lsquo;good enough&amp;rsquo; on the manual dial and the sensitivity just
as good as the modern receiver, after some gentle twiddling of the controls. Amazing bit of kit..&lt;/p&gt;
&lt;p&gt;Some more pictures during the restoration..&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;a href=&#34;IMG_20230531_165524_824.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/IMG_20230531_165524_824.jpg&#34;
    alt=&#34;As found condition&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;As found condition&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;IMG_20230531_184200_556.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/IMG_20230531_184200_556.jpg&#34;
    alt=&#34;Inside the case - top&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;Inside - top&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;IMG_20230531_184604_598.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/IMG_20230531_184604_598.jpg&#34;
    alt=&#34;Inside the case - below&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;Inside - below&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;IMG_20230531_192400_838.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/IMG_20230531_192400_838.jpg&#34;
    alt=&#34;Under the tuning cover&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;The tuner&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;IMG_20230531_184458_845.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/IMG_20230531_184458_845.jpg&#34;
    alt=&#34;A note for the service tech&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;A note&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;IMG_20240114_223121_789.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/IMG_20240114_223121_789.jpg&#34;
    alt=&#34;Innards of the bathtub caps!&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;Cap innards&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.radiomuseum.org/r/rca_ar_88_d.html&#34;&gt;More info from the Radiomuseum here&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;2-the-kitchen-radio&#34;&gt;#2 The Kitchen Radio&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;IMG20241219071537.jpg&#34; alt=&#34;Ultra Electric Ltd Model 149 kitchen radio&#34;&gt;&lt;/p&gt;
&lt;p&gt;This is a pre-war Bakelite cased &#39;kitchen radio&#39; with a glass backlit tuning scale. Station
names from the past are inscribed in the paint across three bands: long, medium and short wave.&lt;/p&gt;
&lt;p&gt;On releasing the rusted tight case screws (mind the Bakelite!) we find a seized tuning mechanism
and a very rusted chassis. Several components have burst open from the damp ingress, and black
dirt encrusts everything. The corroded valves are certainly 1930s era designs with top caps and
octal bases. Several wires immediately break and fall off where the solder has corroded away and
the copper gone green with verdigris.&lt;/p&gt;
&lt;p&gt;The speaker is seized and rusty; no chance of this ever working again. All the components likely
need replacing, and we&amp;rsquo;ve no idea if any valves may have survived, but it seems improbable :(&lt;/p&gt;
&lt;p&gt;The value in these is mostly cosmetic - they were made cheaply and in large volumes, parts
are hard to come by and there are no popular radio stations on these bands anymore!&lt;/p&gt;
&lt;p&gt;So I decide this one is to become a display item with new innards. A visit to CeX returns a £20
Bluetooth speaker in a nice round tubular case. Much cleaning and a swift application of two
cable ties later, and the new speaker is strapped just behind the rear grille, allowing one
to still operate the buttons through the gaps. Nice. The paint on the back of the tuning glass
needs some touching up with a matching colour.. try not to cover over the names!&lt;/p&gt;
&lt;p&gt;Now we just attach a trailing USB charger cable, and we&amp;rsquo;re done!&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;a href=&#34;IMG_20231231_124453_810.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/IMG_20231231_124453_810.jpg&#34;
    alt=&#34;As found condition.. much dirt and sawdust&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;Dirt &amp;amp; dust&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;PXL_20241112_170850308.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/PXL_20241112_170850308.jpg&#34;
    alt=&#34;A rusted speaker and chassis&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;Rusty chassis&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;PXL_20241112_170936099.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/PXL_20241112_170936099.jpg&#34;
    alt=&#34;Rear view of the rusty chassis and valves&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;Rear view&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;PXL_20241112_171118729.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/PXL_20241112_171118729.jpg&#34;
    alt=&#34;A 1930s valve in poor condition&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;Broken valve&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id=&#34;3-the-party-piece&#34;&gt;#3 The Party Piece&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;PXL_20250503_115334164.jpg&#34; alt=&#34;Pilot TRG108 Auto-changer and radio&#34;&gt;&lt;/p&gt;
&lt;p&gt;Here is a Pilot TRG108 portable gramaphone and radio unit. The autochanger&#39;s mechanical parts
have been freed up and are working fine :) The audio amplifier section has been restored, however
we await a solution to to the decayed cartridge innards before it plays records again..&lt;/p&gt;
&lt;p&gt;Again this thing has no real value, but it&#39;s a fun toy to play our 78rpm records :) If I can
get it going for little to no investment, I will. The unit uses a BSR8 record deck - very common and needles
are still available at reasonable cost. The electronics use four valves; two for the radio section, one
audio amplifier and one power supply rectifier. We need to be VERY CAREFUL as the chassis is wired
directly to the mains plug (!!) thus saving costs by using an autotransformer for voltage changing.
It also uses Uxx series valves which have a common 0.1A heater filament at various voltages. These run
in series from 125V AC source. Hmm.&lt;/p&gt;
&lt;p&gt;Unfortunately of the four valves installed, one was smashed and two have broken heater filaments :(
I had a box of valves donated to me by a friend many years ago - mostly TV ones. By pure luck I found
an equivalent for the AF valve (UCL82 -&amp;gt; PCL82) and a rectifier valve (EY85-&amp;gt;EZ80)
I could substitute! The main issue is the heater filaments are different current / voltage ratings.&lt;/p&gt;
&lt;p&gt;So far I have managed to replace all the leaky capacitors, a few duff resistors, the rectifier and AF valves.
The rectifier is a half wave originally (urgh!) so the full-wave replacement is connected with both diodes
in parallel to ensure I retain enough current rating. Seems to work ok..
The AF valve is an equivalent so no hacking required :)&lt;/p&gt;
&lt;p&gt;I have managed to swap around the autotransformer to obtain outputs close to the filament ratings I needed;
by running the EZ80 filament off the 6.3v lamp output and the PCL82 between the 220/250 step down taps in
series with one lamp, we have a solution!&lt;/p&gt;
&lt;p&gt;I have disconnected the filaments &amp;amp; HT of the radio section. There is nothing to listen to on MW/LW anyway :) I may
want to re-instate some radio function later.. for now we just abandon this part of the circuit.&lt;/p&gt;
&lt;p&gt;Unbelievably, the speaker cone is NOT seized up however it rattles like a bag of spanners, so I swapped it for
a Kenwood 4-inch car speaker I had lying around. I also wired in a 1/4&amp;quot; socket so I can use it as a guitar
amp. Nice. That completes the work on the audio electronics, just the cartridge to go.&lt;/p&gt;
&lt;p&gt;Unfortunately, after purchasing two replacement stylii, I quickly discovered the pick-up had zero output on either
78 or LP sides. So it was time to disassemble it and find out what was going on.. as you can see from the
photos below, there is significant damage through damp; verdigris on the copper contact plates and it appears
the crystal has dissolved &amp;amp; turned to mush! With no repair possible, I need to find a replacement cartridge&amp;hellip;&lt;/p&gt;
&lt;p&gt;I have picked up (haha!) a BSR X3M cartridge to swap in as the original mono BSR TC8M has very low vertical
compliance and would damage stereo LP records if played. So it&amp;rsquo;s probably for the best it is knackered!
Does anyone want a pair of stylus for the TC8?&lt;/p&gt;
&lt;p&gt;(The replacement stylus is actually from another vintage player! A 1968 ITT Kolster-Brandes KP036 &amp;lsquo;Coloursound&amp;rsquo;
from a local auction. £10! This one is transistor based, so less interesting for me to fix up..)&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;a href=&#34;PXL_20240810_165728899.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/PXL_20240810_165728899.jpg&#34;
    alt=&#34;The Pilot auto-changer as found&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;As found..&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;PXL_20241118_185207609.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/PXL_20241118_185207609.jpg&#34;
    alt=&#34;The BSR8 turntable unit being serviced&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;Servicing!&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;PXL_20250423_204720034.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/PXL_20250423_204720034.jpg&#34;
    alt=&#34;The electronics chassis on the bench&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;Soldering!&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;PXL_20250502_165026620.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/PXL_20250502_165026620.jpg&#34;
    alt=&#34;The knackered crystal pick-up innards&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;What crystal?&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;signal-2025-05-03-192416_002.jpeg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/signal-2025-05-03-192416_002.jpeg&#34;
    alt=&#34;The donor record player&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;The donor&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.radiomuseum.org/r/pilot_trg108.html&#34;&gt;More info from the Radiomuseum here&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;4-the-ones-that-got-away&#34;&gt;#4 The Ones That Got Away&lt;/h2&gt;
&lt;p&gt;Several other items have been salvaged from the scrap pile; notably two 1950s era top quality Hi-Fi
systems and a car radio unit common in Jags at the time! These all went to happy
enthusiasts on eBay for a respectable amount of cash :)&lt;/p&gt;
&lt;h3 id=&#34;a-radiomobile-model-4010&#34;&gt;A Radiomobile model 4010&lt;/h3&gt;
&lt;p&gt;&lt;figure&gt;&lt;a href=&#34;PXL_20250326_213816854.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/PXL_20250326_213816854.jpg&#34;
    alt=&#34;A 1950s Radiomobile model 4010 valve car radio&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;Crusty radio&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;PXL_20250326_213947547.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/PXL_20250326_213947547.jpg&#34;
    alt=&#34;The components inside of the radio&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;Insides..&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;This unit is 6V positive earth, a variation of the more widely known model 100 used in upmarket 1950s Jaguar models.
It includes a &amp;lsquo;vibrator PSU&amp;rsquo; - essentially a mechanical oscillator, transformer and rectifier valve to provide HT.
There is considerable rust and decay of the outside, but inside is not so bad! Even the push buttons kinda work..
but not the tuning. The control is seized and the cable snapped immediately on removing the case!&lt;/p&gt;
&lt;p&gt;I have no use at all for such a radio given it would only work in ancient cars.. so off it went to a Jaguar
restorer for parts.&lt;/p&gt;
&lt;h3 id=&#34;an-rca-new-orthophonic-high-fidelity-system&#34;&gt;An RCA New Orthophonic High Fidelity system&lt;/h3&gt;
&lt;p&gt;&lt;figure&gt;&lt;a href=&#34;PXL_20241118_121037450.PORTRAIT.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/PXL_20241118_121037450.PORTRAIT.jpg&#34;
    alt=&#34;Two boxed 1950s Hi-Fi system head units&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;Fancy HiFi in 1950s&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;IMG20241112143455.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/IMG20241112143455.jpg&#34;
    alt=&#34;The corroded chassis of the RCA mono power amp&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;Rusty chassis&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;PXL_20241112_161439059.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/PXL_20241112_161439059.jpg&#34;
    alt=&#34;The (expensive!) valves from the power amp&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;Expensive valves&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;This system is a classic of it&amp;rsquo;s time, considered an equal to Quad and similar high-end manufacturers. We have here
boxed pre-amp and tuner head units, and an unboxed power amp. The system is mono; stereo came later! As you can see,
the power amp chassis has suffered a lot of surface rusting. Underneath the components are all splitting from damp
ingress and the cables are rotten. The head units fared much better; protected by the wooden box there is little
decay and clean insides. The unit runs a pair of KT66 output valves in class &amp;lsquo;B&amp;rsquo; giving a comfortable 12 watts r.m.s.&lt;/p&gt;
&lt;p&gt;I decided I did not really need a mono amp, even one as rare and nice as this could be! Also I had no way to really sort out
the surface rust and decay to make it look nice - most of the appeal today is cosmetic. So off it went to a Hi-Fi
restorer who could give it some love :)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.radiomuseum.org/r/rca_gb_amplifier_lmi_32216_a.html&#34;&gt;More info from the Radiomuseum here&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;a-pye-mozart-stereo-hi-fi-system&#34;&gt;A Pye Mozart stereo Hi-Fi system&lt;/h3&gt;
&lt;p&gt;&lt;figure&gt;&lt;a href=&#34;PXL_20241112_161849105.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/PXL_20241112_161849105.jpg&#34;
    alt=&#34;Pye Mozart Hi-Fi system head unit&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;Shiny Pye&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;PXL_20241112_163234642.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/PXL_20241112_163234642.jpg&#34;
    alt=&#34;The dirty chassis of the stereo power amp&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;Filthy amp&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href=&#34;PXL_20241112_163604817.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/posts/valve_gear_renovation/PXL_20241112_163604817.jpg&#34;
    alt=&#34;More (expensive!) valves from the power amp&#34; height=&#34;100&#34;&gt;&lt;/a&gt;&lt;figcaption&gt;
      &lt;p&gt;More $$$ valves&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;This Pye HFS-20M system is surprisingly a similar vintage to the mono RCA above, but here we have a smaller footprint
and a more modern appearance. The unit is less powerful, and runs a pair of EL34 output valves in class &amp;lsquo;A&amp;rsquo;
to obtain 2 x 4 watts r.m.s. stereo. (A mono unit was also sold.) The head unit is again quite clean inside having been
boxed, whilst the power amp is filthy; thick with dirt and rust. I didn&amp;rsquo;t spend any time checking if this could
be restored as it&amp;rsquo;s only desirable in good cosmetic condition! It is however, complete and valves appear undamaged.&lt;/p&gt;
&lt;p&gt;Off it went to the same buyer as the RCA system above :)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.radiomuseum.org/r/pye_mozart_hfs_20m.html&#34;&gt;More info from the Radiomuseum here&lt;/a&gt;&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>About (Ashbysoft *)</title>
      <link>https://www.ashbysoft.com/about/</link>
      <pubDate>Thu, 24 Apr 2025 08:36:00 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/about/</guid>
      <description>We are a small family software firm with a wide range of experience in embedded systems, personal computer applications, and distributed systems fields.
People.. Phil Ashby: Previously a technical architect with GB Group. Member of the FUNcube satellite development team. Stuart Ashby: previously a systems architect with NDS/Synamedia, a major technology provider to several large TV companies. Experience.. We consider ourselves to be expert in both high level OO design (systems and software), and low level systems programming with published work in both areas, including:</description>
      <content:encoded>&lt;p&gt;We are a small family software firm with a wide range of experience in
embedded systems, personal computer applications, and distributed
systems fields.&lt;/p&gt;
&lt;h1 id=&#34;people&#34;&gt;People..&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ashbysoft.com/articles/phlash/&#34;&gt;Phil Ashby&lt;/a&gt;: Previously a technical architect
with GB Group. Member of the FUNcube satellite development team.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ashbysoft.com/articles/slash/&#34;&gt;Stuart Ashby&lt;/a&gt;: previously a
systems architect with NDS/Synamedia, a major technology provider to several
large TV companies.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;experience&#34;&gt;Experience..&lt;/h1&gt;
&lt;p&gt;We consider ourselves to be expert in both high level OO design (systems
and software), and low level systems programming with published work in
both areas, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a real-time interactive TV shopping platform (QVC Active on UK Cable TV)&lt;/li&gt;
&lt;li&gt;a UK scale interactive speech system (CallMinder)&lt;/li&gt;
&lt;li&gt;a world-wide multi-player gaming system (Wireplay3)&lt;/li&gt;
&lt;li&gt;a Windows device driver (Wireplay.VxD)&lt;/li&gt;
&lt;li&gt;an Internet content filter (ICRAfilter)&lt;/li&gt;
&lt;li&gt;a professional hosting service portal (BT Selfcare)&lt;/li&gt;
&lt;li&gt;the on-board computer system for several satellites (FUNcube)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We enjoy working with the C/C++, Java &amp;amp; .NET ecosystems, where our depth
of experience allows us to work with many target environments (eg: Windows,
Linux, VxWorks, Solaris, OpenTV), in particular hetrogeneous
distributed platforms.&lt;/p&gt;
&lt;p&gt;We also have some experience with assembly code on Intel x86, SPARC &amp;amp; ARM
CPUs, but prefer not to mention it in these 4th-gen language days ;-)&lt;/p&gt;
&lt;h1 id=&#34;happy-customers&#34;&gt;Happy Customers..&lt;/h1&gt;
&lt;p&gt;We have sucessfully delivered software for large and small customers
such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AMSAT, where Phil is a member of the FUNcube development team.&lt;/li&gt;
&lt;li&gt;broadcast TV software/security system migrations for Sky Germany, Sky Italy, Astro Malaysia, KBW, beIN&lt;/li&gt;
&lt;li&gt;broadcast TV feature upgrades including PVR, IPTV for Sky Mexico, DirecTV, Sky UK, OSN, Airtel&lt;/li&gt;
&lt;li&gt;QVC UK, whose QVC Active shopping system was developed by Stuart and
his team in his day job..&lt;/li&gt;
&lt;li&gt;MTV, whose interactive service on Telewest is powered by software
developed by Stuart in his day job..&lt;/li&gt;
&lt;li&gt;BTexact, whose Internet site content is managed and published
through a system developed by Phil in his day job..&lt;/li&gt;
&lt;li&gt;The Internet Content Rating Association, who asked Phil to develop
their network filtering software (ICRAfilter).&lt;/li&gt;
&lt;li&gt;Wireplay, where Phil &amp;amp; Stuart lead the development team whilst
working for both BT and Gameplay.com.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;contact-us&#34;&gt;Contact Us&lt;/h1&gt;
&lt;p&gt;All enquiries for more information, or quotes: &lt;a href=&#34;mailto:enquiries@ashbysoft.com&#34;&gt;enquiries@ashbysoft.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Support requests for existing customers: &lt;a href=&#34;mailto:support@ashbysoft.com&#34;&gt;support@ashbysoft.com&lt;/a&gt;&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Phlash - the career bits</title>
      <link>https://www.ashbysoft.com/articles/phlash/tech/</link>
      <pubDate>Sat, 29 Mar 2025 15:30:00 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/phlash/tech/</guid>
      <description>My introduction post from dev.to, migrated back home</description>
      <content:encoded>&lt;h1 id=&#34;about-phlash---the-techie-career-bits&#34;&gt;About Phlash - the techie career bits&lt;/h1&gt;
&lt;p&gt;[this post has been migrated back here from https://dev.to where I am no longer active]&lt;/p&gt;
&lt;p&gt;I have been coding for 40+ years. I&amp;rsquo;m a recently retired (yay!)[edit: now part-time employed] senior technical architect (sounds great, means: do all the stuff nobody else wants to, make hard decisions and take responsibility for everything we ship!).&lt;/p&gt;
&lt;p&gt;At a young age I made myself a promise: the day I get up and don&amp;rsquo;t want to play with a computer, I&amp;rsquo;ll give up this hobby and get a proper job&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;a-brief-career-history&#34;&gt;A brief career history:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://bt.com&#34;&gt;BT PLC&lt;/a&gt; from 1989-1996 as part of the speech application division (yep, SAD team), where I helped create CallMinder (now 1571) and early telephone banking systems, while learning all about speech recognition technology (neural nets, now known as machine learning or &amp;lsquo;AI&amp;rsquo; :grin:)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Wireplay&#34;&gt;Wireplay / Gameplay&lt;/a&gt; from 1996-2000 where I was technical lead for the UK&amp;rsquo;s first online (well, dialup!) video gaming service, and had my first unicorn startup experience, including resigning after 12months to&amp;hellip;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://find-and-update.company-information.service.gov.uk/company/NF003653&#34;&gt;Internet Designers Ltd&lt;/a&gt; from 2000-2007, an IT consultancy that grew from the initial 20 or so people to ~110 at its peak, where I worked on a multitude of smaller projects that varied from high reliability routers, through Java mobile games to managing BTexact Technologies website in a custom CMS..&lt;/li&gt;
&lt;li&gt;Back to BT PLC, from 2007-2013 to become a security analyst and hand-picked member of a specialist team &lt;a href=&#34;https://www.ncsc.gov.uk/blog-post/blog-post-security-complexity-and-huawei-protecting-uks-telecoms-networks&#34;&gt;investigating the risks and developing the mitigations&lt;/a&gt; while BT deployed £6Bn worth of far-eastern telco equipment into the UK&amp;rsquo;s core communications network. No biggie!&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.gbgplc.com&#34;&gt;GBGroup PLC&lt;/a&gt; from 2013-2020 when I retired. I was their first &amp;rsquo;technical architect&amp;rsquo;, and helped design and deliver their identity intelligence services as they grew from ~300 people in a couple of UK offices to a global multi-national with 1100 people, 40 offices round the globe and a multitude of products and services, many a result of mergers and acquisitions (I also consulted into the M&amp;amp;A team - enlightening!)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://willistowerswatson.com&#34;&gt;WTW&lt;/a&gt; from 2024-present, where I am working 3 days a week to support their architecture function and generally be a nuisance!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I mostly program in these languages: C#, Java, Python, C, shell, ASM &amp;amp; enthusiasm!&lt;/p&gt;
&lt;p&gt;If you like what I do, feel free to &lt;a href=&#34;https://paypal.me/PhlashBeers&#34;&gt;buy me a beer&lt;/a&gt; 🍺&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>EMFcamp 2024</title>
      <link>https://www.ashbysoft.com/posts/emf2024/</link>
      <pubDate>Thu, 20 Jun 2024 18:00:00 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/emf2024/</guid>
      <description>Some weekends are normal, others&amp;hellip;</description>
      <content:encoded>&lt;h1 id=&#34;emfcamp-whats-that-phil&#34;&gt;EMFcamp? What&amp;rsquo;s that Phil?&lt;/h1&gt;
&lt;p&gt;Oh boy.. you are one of today&amp;rsquo;s &lt;a href=&#34;https://xkcd.com/1053/&#34;&gt;lucky 10,000&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Probably best to start with the &lt;a href=&#34;https://www.emfcamp.org&#34;&gt;EMFcamp website&lt;/a&gt;, although that only really
scratches the surface of what happens when 3000+ geeky / nerdy (why not both) folks get together in
a really rather nice field (thanks Eastnor Deer Park!) and let their inner geek out.&lt;/p&gt;
&lt;p&gt;I have already read through a few &lt;a href=&#34;https://wiki.emfcamp.org/2024/wiki/Memories&#34;&gt;blogs from other attendees&lt;/a&gt;
that describe the experience from their point of view and it&amp;rsquo;s interesting that some things appear quite
different to people, while others are very firmly the same - I&amp;rsquo;ll start by trying to pick out the commonality:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For first timers, an overwhelming sense of having &amp;ldquo;found my people&amp;rdquo; - it&amp;rsquo;s quite beautiful to watch.
My first time (only 2 years ago) was a revelation - despite being one of the lucky ones who already
had some geeky friends and family (yo bro!), being &lt;em&gt;with&lt;/em&gt; so many other geeks was a delight.&lt;/li&gt;
&lt;li&gt;The joy of being able to be yourself, all of yourself and be &lt;em&gt;accepted&lt;/em&gt; even &lt;em&gt;congratulated&lt;/em&gt; on this.&lt;/li&gt;
&lt;li&gt;Knowing that you share a special trait with your fellow attendees: &lt;em&gt;curiosity&lt;/em&gt; is our hallmark and
it&amp;rsquo;s &lt;em&gt;encouraged&lt;/em&gt;! You just know it&amp;rsquo;s fine to pop into a village and ask about their stuff / clothes
/ challenges making things, or go to one of 400+ talks / workshops / events. A wealth of willing
information firehoses to drink from..&lt;/li&gt;
&lt;li&gt;Wonder (awe even) at the ability of others to create / repair / restore / reuse / innovate with things.&lt;/li&gt;
&lt;li&gt;The obvious amount of self / social capital (I don&amp;rsquo;t like that term but it fits) invested by the team
of people who &lt;em&gt;volunteer&lt;/em&gt; for months ahead of the event to make EMF happen, the willingness of attendees
to volunteer during the event, paying forward to ensure we and others get this experience again :)&lt;/li&gt;
&lt;li&gt;The diversity of attendees in many forms.&lt;/li&gt;
&lt;li&gt;The willingness of people to &lt;em&gt;play&lt;/em&gt;, especially regarding silly things like a &amp;lsquo;Cat ears must be worn
beyond this point&amp;rsquo; sign, that was honoured by many.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Whew! Perhaps you were expecting a list of fun techie things, or shared camping experiences, but it seems
it&amp;rsquo;s the social aspects of EMF that &lt;em&gt;everyone gets&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&#34;what-was-it-like-for-phil&#34;&gt;What was it like for Phil?&lt;/h2&gt;
&lt;p&gt;Speaking of camping, I did suffer from the cold overnight - my feet did not like me much (cramp!) and I&amp;rsquo;m
wondering how to keep them warmer without leaving a heated blanket on (bad idea!). There is a campervan
option that my friends took (expensive on your own), or even staying in a local cottage / AirBnB / hotel
(then you miss out on the nightime entertainment however).&lt;/p&gt;
&lt;p&gt;I popped into the Null Sector for a few minutes to experience what has elsewhere been described as &amp;ldquo;filthy&amp;rdquo;
bass (I estimate several kW of large bass bins stacked under the DJ gantry), and can confirm that I was
moved (at least my eyes went out of focus) by much of the infrasound being generated! This however isn&amp;rsquo;t
really my thing (never has been) so I retreated to a safe distance and enjoyed the laser show from both
Null Sector and the projected video games on the hillside (cheers Seb!). Walking back from Null Sector I
realised that some of the lasers (above the entrance) were controlled from a keyboard 50m away in the field
which was there for us to play with - at that time a couple of pre-teens were doing a good job staying with
the beat..&lt;/p&gt;
&lt;p&gt;As a member of the AMSAT village, I spent half my time talking to others about satellite technology: building
them, getting them into space and using them from the ground. Lots of interest, both in how and why we do
this, which was great!&lt;/p&gt;
&lt;p&gt;This time I volunteered for a shift in the shop (lovely people, mostly working terminals) and as a herald on
stage introducing speakers (more lovely people, opportunity for terrible jokes / puns), so you might see me
briefly on the recordings of some of the talks (Stage C, Sat afternoon). The free meal in the volunteer
kitchen was excellent too - thanks team!&lt;/p&gt;
&lt;p&gt;Finally - I decided to spend as much time meeting people as I could, since I could catch up on talks later,
which was definitely worth it for me - the Mastodon meet-up was good (they&amp;rsquo;re all real people!), the craic
in the Robot Arms (bar tent) was chill, I especially liked the waves of applause as / when someone beat the
high score on the games around the sides, the beer was decent and service was prompt. Old friends were there
from 2022 and earlier, and I talked one of my oldest friends (from uni nearly 40 years ago) into coming too.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll be back #emfcamp.&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Scheduled Hugo Posts</title>
      <link>https://www.ashbysoft.com/posts/scheduled-posts/</link>
      <pubDate>Mon, 01 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/scheduled-posts/</guid>
      <description>Post-dating blog posts..</description>
      <content:encoded>&lt;h1 id=&#34;this-post-was-written-earlier&#34;&gt;This post was written earlier..&lt;/h1&gt;
&lt;p&gt;It should appear automatically on the blog in the early hours of April 1st..&lt;/p&gt;
&lt;h2 id=&#34;the-mechanism&#34;&gt;The mechanism&lt;/h2&gt;
&lt;p&gt;As per all scheduled things in Linux / Unix, this uses &lt;code&gt;cron&lt;/code&gt; to run the blog
publishing script every morning at 02:30hrs. Content is processed by Hugo taking
into account the &lt;code&gt;date:&lt;/code&gt; header in metadata, and not pushed to the public site
until we are past that point. Simples.&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Wireplay calling - hello 1996!</title>
      <link>https://www.ashbysoft.com/posts/wireplay-calling-hello-1996/</link>
      <pubDate>Mon, 11 Dec 2023 23:45:41 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/wireplay-calling-hello-1996/</guid>
      <description>A recently recovered BT Wireplay trial pack from Slash&amp;rsquo;s loft - let&amp;rsquo;s open it up :) BONUS: Phlash had one of the original CD-RWs as sent to the pressing plant!</description>
      <content:encoded>&lt;h2 id=&#34;update-2023---we-got-interviewed&#34;&gt;UPDATE: 2023 - We got interviewed&lt;/h2&gt;
&lt;p&gt;Recently, the excellent &lt;a href=&#34;https://crossedwires.net/podcast/wireplay/&#34;&gt;CrossedWires Podcast&lt;/a&gt; asked us for an interview, how could we refuse?
You can use the previous link to listen to us steamrollering poor James the host!&lt;/p&gt;
&lt;h2 id=&#34;update-2022---off-to-the-museum&#34;&gt;UPDATE: 2022 - Off to the museum&lt;/h2&gt;
&lt;p&gt;All the physical goodies below have now been donated to the
&lt;a href=&#34;http://www.computinghistory.org.uk/&#34;&gt;Centre for Computing History&lt;/a&gt; in Cambridge, UK.
We hope that in time they will be merged into their exhibits on on-line gaming and multi-player games.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../../images/upload/IMG_20211030_144742191.jpg&#34; alt=&#34;Handing over the goodies to the centre for computing history&#34;&gt;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s amazing the things you find in people&amp;rsquo;s lofts, in this case a pristine 1996 BT Wireplay trial pack, let&amp;rsquo;s see what you got way back when..&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../../images/upload/trial-box.jpg&#34; alt=&#34;BT Wireplay trial box&#34;&gt;&lt;/p&gt;
&lt;p&gt;This is a CD sized stiff plastic case, about 3cm thick.. inside we have:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../../images/upload/trial-pack.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;A sheet of instructions, the &lt;em&gt;unopened&lt;/em&gt; feedback questionnaire, and a multi-CD case. Here&amp;rsquo;s what the instructions say:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../../images/upload/instructions-front.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../../images/upload/instructions-back.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;We also have a covering letter from the operations manager (Hi Richard!):&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../../images/upload/cover-letter-slash.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Opening the CD case we find more paperwork at the front, inlcuding some sweet untouched stickers!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../../images/upload/wireplay-trial-docs.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;..then at the back, the CD with the client software:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../../images/upload/wireplay-trial-cd.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;So you want a copy of the CD contents right&amp;hellip; &lt;a href=&#34;https://www.ashbysoft.com/wireplay%20stuff.zip&#34;&gt;Come Get Some!&lt;/a&gt; NB: this ZIP contains both the trial (V1.4A) and the later updated (V1.5H) client.&lt;/p&gt;
&lt;h2 id=&#34;bonus-finds&#34;&gt;Bonus finds!&lt;/h2&gt;
&lt;p&gt;Stu also had the install CD for the first V2.0 Windows &amp;amp; DOS clients:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../../images/upload/wireplay-2.0-front.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../../images/upload/wireplay-2.0-back.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../../images/upload/wireplay-2.0-cd.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Phil just found this in his garage, one of the CD-RWs created to send to the pressing plant (this is probably an escrow copy, archive no 2):&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../../images/upload/wireplay-trial-cd-rw.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;so-do-they-still-run&#34;&gt;So do they still run?&lt;/h2&gt;
&lt;p&gt;Of course they do :)&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../../images/upload/wireplay-all-three.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;anyone fancy setting up a server for these?&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Downgrading WordPress after an upgrade incident</title>
      <link>https://www.ashbysoft.com/posts/wordpress-downgrade/</link>
      <pubDate>Wed, 22 Nov 2023 14:07:16 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/wordpress-downgrade/</guid>
      <description>Sometimes you click too many buttons in a UI, then WP doesn&amp;rsquo;t work any more :(</description>
      <content:encoded>&lt;h1 id=&#34;ok-phil-what-did-you-do-this-time&#34;&gt;OK Phil, what did you do this time?&lt;/h1&gt;
&lt;p&gt;Me??! Nothing&amp;hellip;&lt;br/&gt;
&amp;hellip;&lt;br/&gt;
OK, so a friend runs a collection of websites, which she generates offline using WordPress
and the excellent &lt;a href=&#34;https://wp2static.com/&#34;&gt;WP2Static&lt;/a&gt; plugin, allowing us to host the
sites behind a CDN (Azure in case you&amp;rsquo;re curious), and without having to manage WP online.
This is officially a 2-way win for cost and security.&lt;/p&gt;
&lt;p&gt;To do this, I built her a container image using a variant of &lt;a href=&#34;https://lokl.dev/&#34;&gt;Lokl&lt;/a&gt; that
I have added an Azure uploader into, and shrunk the image size as far as possible, including
replacing MariaDB with SQLite. She thus runs n (currently 4) instances of this container on
her own machine, and changes are automatically synced to the hosting service in real time.&lt;/p&gt;
&lt;p&gt;Earlier today she was looking at the admin panel and noticed that WordPress had an upgrade
available, with a nice attractive button&amp;hellip; sometimes you forget that you aren&amp;rsquo;t looking
after an online WP instance, so the old &amp;ldquo;always upgrade for security&amp;rdquo; reaction kicks in.
Suddenly she&amp;rsquo;s looking at this:&lt;br/&gt;
&lt;img src=&#34;upgrade-db.png&#34; alt=&#34;Wordpress database needs upgrading screen&#34;&gt;&lt;br/&gt;
..and WordPress doesn&amp;rsquo;t work anymore. Oops.&lt;/p&gt;
&lt;h1 id=&#34;better-call-phil&#34;&gt;Better call&amp;hellip; Phil?&lt;/h1&gt;
&lt;p&gt;Because she&amp;rsquo;s a smart cookie, this is where she stopped poking and contacted me - correct!&lt;/p&gt;
&lt;p&gt;Now it&amp;rsquo;s possible that we could complete the upgrade, but it provides no useful new features
for her sites, and doing this previously (out of curiosity) broke a few bits inside Lokl and
WP2Static that took a considerable amount of time to find and fix. Our preferred solution is
therefore to revert the button click and &lt;em&gt;downgrade&lt;/em&gt; WordPress (remember, this is all offline
so there are no security issues with old WP code running!). So err, how does one do that?&lt;/p&gt;
&lt;h1 id=&#34;what-did-the-upgrade-button-do&#34;&gt;What did the Upgrade button do?&lt;/h1&gt;
&lt;p&gt;Because she runs &amp;gt;1 instance of this container, we can take a look at the installed WP files
and find out what changed on the affected instance: pretty much all the &lt;code&gt;.php&lt;/code&gt; files in the
WP installation folder are newer, there are new themes and a couple of plugins have appeared.&lt;/p&gt;
&lt;p&gt;Luckily all the actual site content in &lt;code&gt;wp-content/database&lt;/code&gt; and &lt;code&gt;wp-content/uploads&lt;/code&gt; seems
unaltered from the last set of edits made (a few days ago).&lt;/p&gt;
&lt;h1 id=&#34;the-downgrade-process&#34;&gt;The downgrade process&lt;/h1&gt;
&lt;p&gt;Once we had determined that the database and media files were still intact then it was clear
that we could pull the WP installation from another unaffected instance and unpack it on the
broken one, &lt;code&gt;tar&lt;/code&gt; to the rescue!&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the specific workflow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[host] Connect to the broken container: &lt;code&gt;docker exec -it &amp;lt;broken&amp;gt; /bin/bash&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[broken] Back up the site content: &lt;code&gt;cd &amp;lt;wp install&amp;gt;; tar czf /tmp/content.tgz wp-content&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[host] Connect to a donor instance: &lt;code&gt;docker exec -it &amp;lt;donor&amp;gt; /bin/bash&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[donor] Yank WordPress install: &lt;code&gt;cd &amp;lt;wp install&amp;gt;; tar czf /tmp/wp.tgz .&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[host] Transfer the donated install: &lt;code&gt;docker cp &amp;lt;donor&amp;gt;:/tmp/wp.tgz - |docker cp - &amp;lt;broken&amp;gt;:/tmp/wp.tgz&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[donor] Tidy up donor: &lt;code&gt;rm /tmp/wp.tgz; exit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[broken] Stop WP (YMMV): &lt;code&gt;ps |fgrep php; kill &amp;lt;php-fpm pid&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[broken] Nuke WP install: &lt;code&gt;cd ..; rm -rf &amp;lt;wp install&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[broken] Unpack donated WP: &lt;code&gt;mkdir &amp;lt;wp install&amp;gt;; cd &amp;lt;wp-install&amp;gt;; tar xvf /tmp/wp.tgz&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[broken] Remove content: &lt;code&gt;rm -rf wp-content/database wp-content/uploads&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[broken] Unpack backed up content: &lt;code&gt;mkdir restore; cd restore; tar xvf /tmp/content.tgz&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[broken] Restore database: &lt;code&gt;mv restore/wp-content/database wp-content&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[broken] Restore media files: &lt;code&gt;mv restore/wp-content/uploads wp-content&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[broken] Tidy up broken: &lt;code&gt;rm -rf restore /tmp/content.tgz /tmp/wp.tgz; exit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[host] Restart: &lt;code&gt;docker stop &amp;lt;broken&amp;gt;; docker start &amp;lt;broken&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now go check stuff is working :)&lt;/p&gt;
&lt;p&gt;Sip tea in relaxed manner.&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Face Recognition</title>
      <link>https://www.ashbysoft.com/posts/face-recognition/</link>
      <pubDate>Tue, 19 Sep 2023 12:23:34 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/face-recognition/</guid>
      <description>Phil recently noticed that Google Picasa has been discontinued since 2016 on all platforms, and he&amp;rsquo;s heavily invested in the facial recognition capability (over 200 people tagged in 20000+ photos over several years), with increasing likelihood that it will stop working at any point. Time to rescue the knowledge and find alternative technology.</description>
      <content:encoded>&lt;h2 id=&#34;tldr-wheres-the-code&#34;&gt;TL;DR: Where&amp;rsquo;s the code?&lt;/h2&gt;
&lt;p&gt;Hi impatient person, it&amp;rsquo;s here: &lt;a href=&#34;https://sr.ht/~phlash/Face_recognition&#34;&gt;https://sr.ht/~phlash/Face_recognition&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;motivation&#34;&gt;Motivation&lt;/h2&gt;
&lt;p&gt;Google killed off Picasa desktop, which &lt;a href=&#34;https://www.ashbysoft.com/articles/phlash/&#34;&gt;Phil&lt;/a&gt;
has been using for a number of years, in particular because of it&amp;rsquo;s
ability to recognise faces and tag / group them. With over 20000 photos,
and 200+ people tagged, it&amp;rsquo;s time to get out before losing all that
knowledge.&lt;/p&gt;
&lt;h2 id=&#34;data-escape&#34;&gt;Data escape&lt;/h2&gt;
&lt;p&gt;Provided the appropriate option is ticked, Picasa will save a
&lt;code&gt;.picasa.ini&lt;/code&gt; file in each folder it knows about, containing rectangles
that locate faces in image files, and where those faces have been
tagged, the name tag used. While this preserves the output data, it does
not include the trained recognition model Picasa is using to accurately
match faces, this is buried in a custom binary database, and unlikely to
make any sense outside of the particular recognition engine used, so we
need to start again for this&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;new-recogniser-tech&#34;&gt;New recogniser tech&lt;/h2&gt;
&lt;p&gt;After a bit of rummaging Phil found the excellent &lt;code&gt;face_recognition&lt;/code&gt;
project from Adam Geitgey: &lt;a href=&#34;https://github.com/ageitgey/face_recognition&#34;&gt;https://github.com/ageitgey/face_recognition&lt;/a&gt;
and his clear blog series explaining stuff:
&lt;a href=&#34;https://medium.com/@ageitgey/machine-learning-is-fun-part-4-modern-face-recognition-with-deep-learning-c3cffc121d78&#34;&gt;https://medium.com/@ageitgey/machine-learning-is-fun-part-4-modern-face-recognition-with-deep-learning-c3cffc121d78&lt;/a&gt;,
fabulous job Adam!&lt;/p&gt;
&lt;p&gt;Armed with this code, and after a fair amount of trial &amp;amp; error getting
dependencies working (see below), some testing showed that careful
tuning of image size and algorithm selection could result in decent face
detection &amp;amp; landmark extraction through a batch of images without eating
vast compute time.&lt;/p&gt;
&lt;h2 id=&#34;sane-storage&#34;&gt;Sane storage&lt;/h2&gt;
&lt;p&gt;Because I intend to save overnight image processing results in a format
that can be easily queried by other tools on multiple systems, I need
portability, indexing and structure, preferably without a lot more
installation / maintenance pain: step forward SQLite :)&lt;/p&gt;
&lt;p&gt;The current database schema supports two distinct jobs:&lt;/p&gt;
&lt;p&gt;- keeping a record of all files (images or not) in the searched areas,
detecting changes and duplicates (via file hashes).
- keeping a record of facial co-ordinates in each image (file hash),
grouping them into similar clusters and labelling clusters.&lt;/p&gt;
&lt;h2 id=&#34;bootstrapping-the-clustering&#34;&gt;Bootstrapping the clustering&lt;/h2&gt;
&lt;p&gt;Since I already have tags from Picasa, on some image files, I can
pre-load clusters from this Picasa data (including the multiple groups
per label), which gives me a starting point for clustering unknown faces
too.&lt;/p&gt;
&lt;h2 id=&#34;sage-advice&#34;&gt;Sage advice&lt;/h2&gt;
&lt;p&gt;Having got this far, I ran off the end of the tutorials from Adam and
was unsure on how to approach the classification / training stages, so I
asked my friend and colleague, GBG&amp;rsquo;s resident data scientist
&lt;a href=&#34;https://ianhopkinson.org.uk/&#34;&gt;Ian&lt;/a&gt;. After my poor problem
description, Ian wisely suggested that I probably didn&amp;rsquo;t have
enough training data to get a good machine learning model, it may well
&amp;lsquo;overfit&amp;rsquo; and have problems, besides that&amp;rsquo;s all hard work with new
libraries (Scikit probably), and there are effective simpler means to an
end: analysis!&lt;/p&gt;
&lt;h2 id=&#34;encoding-analysis&#34;&gt;Encoding analysis&lt;/h2&gt;
&lt;p&gt;Ian suggested I try and improve the basic face matcher that comes in the
&lt;code&gt;face_recognition&lt;/code&gt; package, by looking at the variance of the elements in
a facial encoding (128 of them) across my data set, and weighting
towards those with higher variance when doing simple vector (euclidean)
distance measures. He also thought it would speed up the comparison if I
reduced the n(n-1) complexity back to n by averaging the already
labelled/grouped Picasa faces and comparing new data to those averages,
rather than every member of a group. Good advice, thanks Ian!&lt;/p&gt;
&lt;h2 id=&#34;gthumb-as-a-viewer&#34;&gt;gThumb as a viewer&lt;/h2&gt;
&lt;p&gt;I went looking for a way to visualise outputs as it&amp;rsquo;s tedious picking
through log files and firing up eog for sample images. After some
initial rummaging at &lt;a href=&#34;https://alternativeto.net&#34;&gt;https://alternativeto.net&lt;/a&gt; I installed gThumb from
the standard distro and started work on a plugin
&lt;a href=&#34;https://git.sr.ht/~phlash/gthumb_faces&#34;&gt;https://git.sr.ht/~phlash/gthumb_faces&lt;/a&gt;, which currently intercepts
image rendering to draw facial rectangles on images, while also extending
the tree list with a Faces entry showing all facial labels.&lt;/p&gt;
&lt;h2 id=&#34;face_recognition-install&#34;&gt;face_recognition install&lt;/h2&gt;
&lt;p&gt;Adam provides instructions on installing the C library used (dlib) from
source here:
&lt;a href=&#34;https://gist.github.com/ageitgey/629d75c1baac34dfa5ca2a1928a7aeaf&#34;&gt;https://gist.github.com/ageitgey/629d75c1baac34dfa5ca2a1928a7aeaf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Having been through this, I discovered that the python package manager
does just as well, so my final install list to get this working was:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# aptitude install python-pip python-setuptools python-numpy libboost-python-dev libjpeg-dev cmake
# pip install dlib
# pip install face_recognition
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;speeding-it-all-up&#34;&gt;Speeding it all up&lt;/h2&gt;
&lt;p&gt;With everything in place and mostly working, I started running lots of
image files through.. which is when I discovered the need to tune face
detection settings to get any workable speed. Unfortunately the current
tuning misses a lot of faces that aren&amp;rsquo;t square-on (it relies on HOG
first, only running CNN if nothing turns up, or not at all). I need GPU
power to make this all go faster!&lt;/p&gt;
&lt;p&gt;Fortunately &lt;a href=&#34;https://www.ashbysoft.com/articles/simon/&#34;&gt;Simon&lt;/a&gt; has just upgraded our
desktop PC which means there is a spare AMD Turks (6670) device and the
Xeon / Haswell integrated Intel graphics device I could use..
Cue installation montage of AMD card into my server and BIOS poking to
stop it disabling the Intel GPU when the AMD was plugged in :)&lt;/p&gt;
&lt;p&gt;NB: If you want both integrated and extension GPUs working in a Dell
machine - you &lt;em&gt;must&lt;/em&gt; [enable &amp;lsquo;Multi-Display&amp;rsquo; in the BIOS]
(&lt;a href=&#34;https://www.dell.com/community/PowerEdge-Hardware-General/Dell-PowerEdge-T20-xeon-Multi-Display-bios-setting/td-p/4542733&#34;&gt;https://www.dell.com/community/PowerEdge-Hardware-General/Dell-PowerEdge-T20-xeon-Multi-Display-bios-setting/td-p/4542733&lt;/a&gt;)
and you &lt;em&gt;must&lt;/em&gt; have a VGA device (or emulator) plugged into the VGA
port at boot - otherwise the BIOS turns off the integrated chip.&lt;/p&gt;
&lt;p&gt;Now it gets fun again - I&amp;rsquo;ve never written any GPGPU code, and it looks
like I may have to port the underlying &lt;code&gt;dlib&lt;/code&gt; library from CUDA to
OpenCL, since there is no CUDA for AMD or Intel devices (kind of..).&lt;/p&gt;
&lt;p&gt;I thus started from zero: got a demo working, then got an FIR filter
implementation working (thanks &lt;a href=&#34;https://github.com/ghostop14/gr-clenabled&#34;&gt;gr-clenabled&lt;/a&gt;)
then started comparing performance between CPU, Xeon GPU, AMD GPU and
was surprised that the Xeon GPU only just outperforms the CPU, while
the AMD GPU is &lt;em&gt;slower&lt;/em&gt;, due to data shifting delays across PCI. Hmmn.
I&amp;rsquo;m still looking at tuning the code for AMD, since I was hoping for
at least 10x over the CPU, perhaps an FIR filter isn&amp;rsquo;t a reasonable
testbed?&lt;/p&gt;
&lt;p&gt;A word of caution here: at one point I wrote some bad GPGPU code which
didn&amp;rsquo;t specify resources correctly, and didn&amp;rsquo;t release them either -
running this a few times started producing errors, then &lt;em&gt;hard locked&lt;/em&gt;
my whole server when it crashed on the Intel GPU - eek!&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Obihai OBi110 Andrews &amp; Arnold VoIP Setup</title>
      <link>https://www.ashbysoft.com/posts/obihai-obi110-aaisp-voip/</link>
      <pubDate>Wed, 21 Jun 2023 19:45:51 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/obihai-obi110-aaisp-voip/</guid>
      <description>Configuring a VoIP bridge for A&amp;amp;A use</description>
      <content:encoded>&lt;h2 id=&#34;whats-this&#34;&gt;What&amp;rsquo;s this?&lt;/h2&gt;
&lt;p&gt;A little back story and terse summary of the settings I am using to enable VoIP (Voice over IP)
telephony from my existing Obihai OBi110 bridge unit, so my analogue phones still work without
an analogue line any more..&lt;/p&gt;
&lt;p&gt;See also: &lt;a href=&#34;../debian-aaisp-l2tp&#34;&gt;my earlier post on using A&amp;amp;A for a static IP separated from my ISP&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;TL;DR? &lt;a href=&#34;#config&#34;&gt;config below&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;the-obihai-obi110&#34;&gt;The Obihai OBi110&lt;/h2&gt;
&lt;p&gt;PC-Magazine &lt;a href=&#34;https://uk.pcmag.com/smb/19609/obihai-obi110&#34;&gt;wrote a review back in 2012&lt;/a&gt; when these
were a shiny new toy explaining what they are for: &lt;strong&gt;bridging telephone technologies together&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&#34;my-current-use&#34;&gt;My Current Use&lt;/h2&gt;
&lt;p&gt;I bought the OBi110 to use as a super configurable call screening device, with a built-in auto-assistant
to inform callers that they are being screened and to press a specific DTMF key, or be diverted to a
voicemail system on my local server (this bit never happened!). The call screening has been in place
for several years, working well, and allowing me to block many nusiance calls.&lt;/p&gt;
&lt;h2 id=&#34;the-plan&#34;&gt;The Plan&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s simple - as the OBi110 supports VoIP via the SIP standard, and A&amp;amp;A can
cost-effectively
&lt;a href=&#34;https://www.aa.net.uk/voice-and-mobile/voip-information/&#34;&gt;port my existing BT landline number&lt;/a&gt;
to their SIP VoIP service, I &lt;em&gt;just&lt;/em&gt; have to figure out the configuration required to
make it work. Behind a Network Address Translation (NAT) router. When nobody has &lt;em&gt;ever&lt;/em&gt; done this
before with an OBi110 (at least not written it up!). Without b0rking my &lt;em&gt;very well known&lt;/em&gt; home
phone number that I have had for almost 35 years.&lt;/p&gt;
&lt;h3 id=&#34;the-detailed-plan-to-protect-my-number&#34;&gt;The detailed plan to protect my number!&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Buy a temporary test number (they&amp;rsquo;re super cheap!).&lt;/li&gt;
&lt;li&gt;Use that temporary number to get the OBi110 working with A&amp;amp;A SIP.&lt;/li&gt;
&lt;li&gt;..or.. if that fails: buy a known-good SIP to Analogue Telephone Adapter (ATA). Get that working.&lt;/li&gt;
&lt;li&gt;Once &lt;em&gt;something&lt;/em&gt; is working, port my real number in and switch over to it.&lt;/li&gt;
&lt;li&gt;Release the temporary number.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;the-side-effects&#34;&gt;The side effects&lt;/h3&gt;
&lt;p&gt;Asking A&amp;amp;A to port my existing number in will have dramtic side effects on my landline services: as
this is the only number, BT will assume I no longer want their telephony and issue a &lt;em&gt;PSTN cease&lt;/em&gt; on
my line, which will also go to my old broadband provider (Plusnet), who will &lt;em&gt;immediately cease&lt;/em&gt;
their service too. A non-reversible and final cessation of my landline and old broadband.&lt;/p&gt;
&lt;h2 id=&#34;the-config&#34;&gt;The Config&lt;/h2&gt;
&lt;p&gt;&lt;a name=&#34;config&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;By section, top-to-bottom in the side menu. &lt;strong&gt;NB: only shows non-default settings&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;System Management, Network Settings&lt;/strong&gt; (these are specific to my internal network - adjust for yours!):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Parameter&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;AddressingType&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;Static&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;IPAddress&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;192.168.0.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;!SubnetMask&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;255.255.255.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;DefaultGateway&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;192.168.0.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;DNSServer1&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;192.168.0.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;NTPServer1&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;192.168.0.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;LocalTimeZone&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;GMT+0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;System Management, Auto Provisioning&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Parameter&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;ITSP Provisioning/Method&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;Disabled&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;System Management, Device Admin&lt;/strong&gt; (I collect syslog on my server, you may not want to):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Parameter&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;AdminPassword&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;&amp;hellip;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;UserPassword&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;&amp;hellip;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;Syslog/Server&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;192.168.0.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;Syslog/Level&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Service Providers, ITSP Profile A, General&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Parameter&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;Name&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;Andrews &amp;amp; Arnold&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;STUNEnable&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;STUNServer&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;stun.aa.net.uk&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Service Providers, ITSP Profile A, SIP&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Parameter&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;ProxyServer&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;voiceless.aa.net.uk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;RegistrarServer&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;voiceless.aa.net.uk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;UserAgentDomain&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;voiceless.aa.net.uk&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt;: Setting a proxy server is &lt;em&gt;against A&amp;amp;A recommendation&lt;/em&gt; but OBi110 considers a service disabled
without it, it provides a default if &lt;code&gt;RegistrarServer&lt;/code&gt; is not set.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Voice Services, SP1 Service&lt;/strong&gt; (as above, I collect detailed syslogs, you may not want to):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Parameter&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;X_RingProfile&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;X_SipDebugOption&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;Log All Except REGISTER Messages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;AuthUserName&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;&amp;lt;allocated number&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;AuthPassword&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;&amp;hellip;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt;: Ring profile B is for UK ringing tones, which are less weird for us.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Voice Services, OBITALK Service&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Parameter&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;Enable&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Voice Services, Auto Attendant&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Parameter&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;Enable&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Physical Interfaces, PHONE Port&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Parameter&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;OutboundCallRoute&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;&lt;code&gt;{([1-9]x?*(Mpli)):pp},{(&amp;lt;#:&amp;gt;|999):pli},{**0:aa},{***:aa2},{(&amp;lt;**1:&amp;gt;(Msp1)):sp1},{(&amp;lt;**2:&amp;gt;(Msp2)):sp2},{(&amp;lt;**8:&amp;gt;(Mli)):li},{(&amp;lt;**9:&amp;gt;(Mpp)):pp},{(Mpli):pli}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;PrimaryLine&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;SP1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;RingFrequency&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;CallerIDMethod&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;FSK(V.23)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;CallerIDTrigger&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;After Polarity Reversal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt;: Outbound call route replaces &lt;code&gt;911&lt;/code&gt; with &lt;code&gt;999&lt;/code&gt; and routes to &lt;code&gt;pli&lt;/code&gt; instead of &lt;code&gt;li&lt;/code&gt;.&lt;br/&gt;
&lt;strong&gt;NBB&lt;/strong&gt;: CallerID settings are for my UK, BT provided analogue phones. YMMV.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Physical Interfaces, LINE Port&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Parameter&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;Enable&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;the-result&#34;&gt;The Result&lt;/h2&gt;
&lt;p&gt;With the above settings, I can dial a standard number (no prefixes) and it calls out on the SP1 SIP
service, connects and can send / receive audio. Incoming calls to the authenticated number are routed
to the analogue phones, which correctly answer and can send / receive audio. Success!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt;: I can still force use of the PSTN line by using the &lt;code&gt;**8&lt;/code&gt; prefix in the outbound call route.&lt;/p&gt;
&lt;p&gt;END.&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Debian to Andrews &amp; Arnold L2TP Setup</title>
      <link>https://www.ashbysoft.com/posts/debian-aaisp-l2tp/</link>
      <pubDate>Fri, 09 Jun 2023 15:30:26 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/debian-aaisp-l2tp/</guid>
      <description>Connecting my server to a public IP elsewhere..</description>
      <content:encoded>&lt;h2 id=&#34;why&#34;&gt;Why?&lt;/h2&gt;
&lt;p&gt;Because I&amp;rsquo;m changing my Internet Service Provider (ISP) from one who provides a static IP
address (Plusnet) to one who doesn&amp;rsquo;t (Virgin Media)^ unless I buy a silly money business
product, however I still need to provide various services to friends and family (email,
chat etc.) which requires a static IP address.&lt;/p&gt;
&lt;p&gt;Conveniently Andrews &amp;amp; Arnold (aka A&amp;amp;A, another ISP)
&lt;a href=&#34;https://www.aa.net.uk/broadband/l2tp-service/&#34;&gt;sell a service specifically for this situation&lt;/a&gt;,
where you get a static IP address in their network that can be associated with a network
interface on a machine in your world over the Layer 2 Tunneling Protocol (L2TP).&lt;/p&gt;
&lt;h2 id=&#34;the-plan&#34;&gt;The Plan&lt;/h2&gt;
&lt;p&gt;I currently have a static IP address on my home broadband. This allows me to forward specific
traffic from the Internet to a server I run in the house, using my OpenWRT router. Easy(ish).&lt;/p&gt;
&lt;p&gt;I will replace this with a remote interface (over L2TP), directly to the server, returning my
router to a simpler configuration (almost no traffic forwarding), in preparation for replacing it
with the Virgin Media one. I will also need to migrate the firewall rules from the router to
the server to filter the raw Internet on this interface (but not any others). Sounds OKish..&lt;/p&gt;
&lt;p&gt;Caveat: I presently have one forwarding rule for the L2TP traffic (port 1701/udp), which may
not be necessary with sufficient tunnelled traffic or keep alives. To Be Experimented With.&lt;/p&gt;
&lt;h2 id=&#34;step-0---buy-the-l2tp-product&#34;&gt;Step #0 - buy the L2TP product&lt;/h2&gt;
&lt;p&gt;This was definitely the easy bit, A&amp;amp;A have a sane and working fully automated sales platform,
so on a Sunday morning I completed my purchase in about 10 mins. I particularly like the way
they integrate with their payment provider, automatically filling out my details once I have
sent them a setup payment.&lt;/p&gt;
&lt;h2 id=&#34;step-1---learn-iptables&#34;&gt;Step #1 - learn &lt;code&gt;iptables&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;As I will be migrating firewall rules, and will want them installed &lt;em&gt;before&lt;/em&gt; exposing my server
to the raw Internet, I looked at this early.&lt;/p&gt;
&lt;p&gt;I read the manual for &lt;code&gt;ufw&lt;/code&gt; which is the usual firewall tooling recommended by Debian and Ubuntu.
Unfortunately it&amp;rsquo;s designed for systems where you want to firewall everything, and arranging it
to only mess with one interface is ugly. I was also unsure the integration into the networking
control stack will work for me, I do not use network manager on my server.. next!&lt;/p&gt;
&lt;p&gt;I looked at &lt;code&gt;FirewallD&lt;/code&gt; which also seemed popular, unfortunately that integrates even more with
network manager and is aimed at road warriors.. it may have managed the multi-homing better.. next!&lt;/p&gt;
&lt;p&gt;Given I really don&amp;rsquo;t want anything &amp;lsquo;clever&amp;rsquo;, and I&amp;rsquo;ve managed to read and understand what
&lt;code&gt;fail2ban&lt;/code&gt; is already doing with the underlying &lt;code&gt;iptables&lt;/code&gt; kernel configuration, I dove into
writing my own ruleset and hooking that in to the &lt;code&gt;INPUT&lt;/code&gt; processing. This pretty much worked
first time, although I did have a minor struggle with unplanned additional traffic (see below)!&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the final script (hooked into PPP, see below: &lt;code&gt;/etc/ppp/ip-pre-up.d/firewall.sh&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#! /bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# iptables firewall setup script for L2TP tunnel interface exposed directly to the &amp;#39;net&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# some config..&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IFACE&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CHAIN&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;aaisp-in
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IPTABLES&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/sbin/iptables
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#IPTABLES=echo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# services we permit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SSHD&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;22/tcp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SMTP&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;25,465,587/tcp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IMAP&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;143,993/tcp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;80,443/tcp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;TINC&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;655/tcp 655/udp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MTRX&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;8448/tcp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# munged together..&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ALLOW&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$SSHD&lt;span style=&#34;color:#e6db74&#34;&gt; &lt;/span&gt;$SMTP&lt;span style=&#34;color:#e6db74&#34;&gt; &lt;/span&gt;$IMAP&lt;span style=&#34;color:#e6db74&#34;&gt; &lt;/span&gt;$HTTP&lt;span style=&#34;color:#e6db74&#34;&gt; &lt;/span&gt;$TINC&lt;span style=&#34;color:#e6db74&#34;&gt; &lt;/span&gt;$MTRX&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# bail out function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fail&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$*&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &amp;gt;&amp;amp;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    exit &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; -n &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$IFACE&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; fail &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;no interface on command line&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# first, clean up&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# - disconnect INPUT chain from calling our user chain (for current interface)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Dropping existing firewall rules..&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$IPTABLES -D INPUT -i $IFACE -j $CHAIN
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sleep &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# - nuke our user chain&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$IPTABLES -F $CHAIN
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$IPTABLES -X $CHAIN
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# now build our user chain&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Creating firewall rules..&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$IPTABLES -N $CHAIN
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; s in $ALLOW
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PROT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;echo $s |cut -d/ -f2&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;echo $s |cut -d/ -f1&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; -n &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$PORT&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; fail &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;missing port number(s): &lt;/span&gt;$s&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $IPTABLES -A $CHAIN -p $PROT -s 0/0 -d 0/0 -m multiport --dports $PORT -j ACCEPT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# permit established connections (that we have made from inside)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$IPTABLES -A $CHAIN -m conntrack --ctstate ESTABLISHED -j ACCEPT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# default log then reject after all allows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$IPTABLES -A $CHAIN -j LOG --log-prefix &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;_FIREWALL_ &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$IPTABLES -A $CHAIN -j REJECT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# connect current interface to user chain&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$IPTABLES -A INPUT -i $IFACE -j $CHAIN
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# done!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exit &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, I run a few TCP services, plus a &lt;code&gt;tinc&lt;/code&gt; VPN (TCP &amp;amp; UDP). The original plan was
&lt;em&gt;not&lt;/em&gt; to have the default route via the new interface, so I wouldn&amp;rsquo;t need to allow any other
traffic apart from the well-known services. Unfortunately this didn&amp;rsquo;t work (routing issues),
so I now include the additional &lt;code&gt;ESTABLISHED&lt;/code&gt; rule which allows Internet things to reply to
any packets my server sends out (like DNS!).&lt;/p&gt;
&lt;p&gt;Currently I&amp;rsquo;m logging rejected packets, with a prefix that allows me to dump the logs into a
separate file (&lt;code&gt;/var/log/firewall.log&lt;/code&gt;). YMMV.&lt;/p&gt;
&lt;h2 id=&#34;step-2---hook-up-the-l2tp--ppp&#34;&gt;Step #2 - hook up the L2TP &amp;amp; PPP&lt;/h2&gt;
&lt;p&gt;A&amp;amp;A &lt;a href=&#34;https://support.aa.net.uk/L2TP_Client:_Debian&#34;&gt;provide a guide for Debian&lt;/a&gt; which was quite
helpful, but doesn&amp;rsquo;t really reflect my use case. I also read the manuals for the software used
and it turns out there are better ways to acheive some things - might poke their wiki with an
update at some point :)&lt;/p&gt;
&lt;h3 id=&#34;required-packages&#34;&gt;required packages&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# aptitude install xl2tpd pppd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;static-routes-for-the-tunnel&#34;&gt;static routes for the tunnel&lt;/h3&gt;
&lt;p&gt;This ensures that even if the default route changes (it will) then tunnel traffic always goes
out over the underlying network (&lt;code&gt;/etc/network/interfaces&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# The primary network interface&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# - additional static routes for l2tp.aa.net.uk so it remains routed via gateway even&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#   after xl2tpd/pppd brings up a new default route via the tunnel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;auto eno1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;iface eno1 inet static
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        address 192.168.0.5
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        broadcast 192.168.0.255
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        netmask 255.255.255.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        gateway 192.168.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        up /sbin/ip route add 90.155.53.19/32 via 192.168.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        up /sbin/ip route add 194.4.172.12/32 via 192.168.0.1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;xl2tpd-tunnel-client&#34;&gt;xl2tpd tunnel client&lt;/h3&gt;
&lt;p&gt;Here we provide the L2TP daemon with connection details for A&amp;amp;A, and a useful option that
automatically starts connection attempts. We also ask it to retry effectively forever if the
connection fails. This avoids the ugly cron job hack in the original guide to start the
connection (&lt;code&gt;/etc/xl2tpd/xl2tpd.conf&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;lac aaisp&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lns &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; l2tp.aa.net.uk
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;autodial &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; yes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;redial &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; yes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;redial timeout &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;max redials &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;9999&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;require authentication &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; no
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pppoptfile &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; /etc/ppp/peers/lac.aaisp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that this &lt;em&gt;needs working DNS&lt;/em&gt; to locate the tunnel server. At this point we have a default
route to the Internet via the router, so we can resolve names (I happen to run a full recursive
resolver on this system, which is paranoia on my part and you may be happy to simply forward
requests to your ISP!)&lt;/p&gt;
&lt;h3 id=&#34;pppd-remote-interface&#34;&gt;pppd remote interface&lt;/h3&gt;
&lt;p&gt;Almost the final part of the puzzle, this configures &lt;code&gt;pppd&lt;/code&gt; to negotiate an IP address and create
a new network interface associated with it (&lt;code&gt;/etc/ppp/peers/lac.aaisp&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# PPP outbound config for AAISP/L2TP tunnel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# - do not require peer to authenticate with us&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# - replace default route via this interface when up&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# - call the new interface &amp;#39;aaisp-l2tp&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# - include our AAISP credentials&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;noauth
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;replacedefaultroute
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;defaultroute
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ifname aaisp-l2tp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;name &amp;lt;insert your A&amp;amp;A L2TP identity here&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;password &amp;lt;insert your A&amp;amp;A L2TP password here&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that this replaces the default route on the server (previously to my gateway at 192.168.0.1)
so that connecting clients &lt;em&gt;get replies from the same IP they sent packets to&lt;/em&gt;. I tried
configuring without adjusting the default route, but things get messy with trying to associate
incoming and outgoing packets in the network core and force non-default specific routing.. Maybe
later when I&amp;rsquo;ve read another manual! I also have other interfaces on this server..&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pppd&lt;/code&gt; will automatically run the firewall setup script (see above) as this interface comes up,
providing the interface name as the first argument. Note that as I only run one ppp connection,
I don&amp;rsquo;t need to filter on interface name in the script to avoid firewalling other things. YMMV.&lt;/p&gt;
&lt;h2 id=&#34;fire-up-the-beast&#34;&gt;Fire up the beast!&lt;/h2&gt;
&lt;p&gt;This is the easy bit:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# systemctl start xl2tpd; tail -f /var/log/syslog&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;..and watch the magic happen :)&lt;/p&gt;
&lt;hr/&gt;
^ Also why: because they are the only alternative to a terrible aluminium POTS line that
will never go faster than 50/1.5, and there is zero sign of Openreach putting actual fibre
along my road. Le sigh..
</content:encoded>
    </item>
    
    <item>
      <title>Swingland</title>
      <link>https://www.ashbysoft.com/articles/swingland/</link>
      <pubDate>Fri, 12 May 2023 19:00:00 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/swingland/</guid>
      <description>Re-writing Java Swing on Wayland - how hard can it be?</description>
      <content:encoded>&lt;h1 id=&#34;irritation-driven-development&#34;&gt;Irritation-driven-development&lt;/h1&gt;
&lt;p&gt;Back in the past &lt;a href=&#34;https://git.sr.ht/~phlash/java-sdr&#34;&gt;I wrote&lt;/a&gt; a couple of &lt;a href=&#34;https://git.sr.ht/~phlash/powermonitor&#34;&gt;Java apps&lt;/a&gt;. These were
written using the &lt;a href=&#34;https://docs.oracle.com/javase/tutorial/uiswing/&#34;&gt;Java Swing&lt;/a&gt; framework, and have worked nicely on both Windows and
Linux X11 desktops for a long time.&lt;/p&gt;
&lt;p&gt;More recently I switched away from X11 &amp;amp; &lt;a href=&#34;https://blog.buddiesofbudgie.org/&#34;&gt;Budgie&lt;/a&gt; to pure &lt;a href=&#34;https://wayland.freedesktop.org/&#34;&gt;Wayland&lt;/a&gt; for my,
desktop on the assumption that it&amp;rsquo;s over 10 years old now, and is the default technology underlying current Gnome and KDE desktops.. everything
will be fine right? Kind of..&lt;/p&gt;
&lt;p&gt;It turns out Java GUI technology has been somewhat abandoned by Oracle, in particular when running Swing (or JavaFX) applications on Wayland,
Java relies on the &lt;code&gt;XWayland&lt;/code&gt; adpater to bodge X11 API calls back to Wayland proper. This is not great (read: doesn&amp;rsquo;t work out of the box), so
I wondered if someone had implemented a native Wayland backend for Swing -
&lt;a href=&#34;https://wiki.openjdk.org/display/wakefield/OpenJDK+Project+Wakefield+-+Wayland+desktop+support+for+JDK+on+Linux&#34;&gt;and they have&lt;/a&gt;,
&lt;a href=&#34;https://github.com/CaciocavalloSilano/caciocavallo&#34;&gt;multiple times&lt;/a&gt; - super, but wait.. Oracle have not merged either project into mainline Openjdk,
and indeed the only way to make either of them work is by &lt;a href=&#34;https://github.com/CaciocavalloSilano/caciocavallo/blob/master/cacio-tta/src/main/java/com/github/caciocavallosilano/cacio/ctc/junit/CacioExtension.java&#34;&gt;hideous bodging&lt;/a&gt;, which also puts paid to any thoughts of writing my own backend, as the hacks
required to load it at run time (read: in every application) are not sustainable. Grrr! So what to do?&lt;/p&gt;
&lt;p&gt;I can of course switch back to an X11 desktop (ie: Budgie), but &lt;strong&gt;this irritates me&lt;/strong&gt;, plus I have
&lt;a href=&#34;https://github.com/phlash/OpenSceneGraph&#34;&gt;already ported OpenSceneGraph + Flightgear to Wayland&lt;/a&gt;, it wasn&amp;rsquo;t that difficult :)&lt;/p&gt;
&lt;p&gt;Swing, like most medium-large frameworks has documented public API and internal implementations, so I &lt;em&gt;could&lt;/em&gt; choose to re-write Swing, retaining the
public API (thus existing applications can re-compile against my library) but &lt;em&gt;rewrite Swing internals&lt;/em&gt; from the ground up on top of Wayland APIs.
Sounds sensible right? However Swing (and the earlier AWT it relies on) have
&lt;a href=&#34;https://docs.oracle.com/en/java/javase/17/docs/api/java.desktop/module-summary.html&#34;&gt;several hundred documented classes&lt;/a&gt;, with many more undocumented
internal classes and a fair amount of native code (in C) to connect to X11, Win32 or Cocoa (macOS), plus there are no Java bindings to Wayland, only
the &lt;code&gt;libwayland&lt;/code&gt; C API. How brave do I feel?&lt;/p&gt;
&lt;p&gt;Looking at my existing apps (see above), I have only used a small number of Swing features, so I &lt;em&gt;should&lt;/em&gt; be able to
&lt;a href=&#34;https://en.wikipedia.org/wiki/Spike_(software_development)&#34;&gt;create a spike&lt;/a&gt; that supports just the features I need to prove my proposal.. still
seems pretty mad, but I have time (the glory of retirement!), so let&amp;rsquo;s go!&lt;/p&gt;
&lt;h1 id=&#34;wayland-api-in-mostly-java&#34;&gt;Wayland API in (mostly) Java&lt;/h1&gt;
&lt;p&gt;Given I &lt;em&gt;will&lt;/em&gt; be using most of the Wayland protocol to achieve anything (it&amp;rsquo;s minimal) and &lt;a href=&#34;https://wayland.app/protocols/&#34;&gt;Wayland is well specified&lt;/a&gt;
then the &amp;lsquo;start at the bottom and build up&amp;rsquo; design pattern fits. Wayland has a &lt;code&gt;wire protocol&lt;/code&gt; based on a Unix socket, and usefully Java has
supported Unix sockets since release 16, so I can write everything in Java to (de)serialise messages. This gets me going quickly, providing
positive feedback that I&amp;rsquo;m on the right track..&lt;/p&gt;
&lt;p&gt;Unfortunately Wayland also uses two Unix features that Java doesn&amp;rsquo;t have: SYS V shared memory buffers; file descriptor passing over Unix sockets. I
then discover a bug (or misunderstand the documentation!)..&lt;/p&gt;
&lt;h3 id=&#34;shared-memory-solution&#34;&gt;Shared memory solution&lt;/h3&gt;
&lt;p&gt;Helpfully &lt;a href=&#34;https://docs.oracle.com/en/java/javase/17/docs/specs/jni/&#34;&gt;Java Native Interface (JNI)&lt;/a&gt; &lt;em&gt;does&lt;/em&gt; allow memory buffers to be passed from native
code back to Java, and vice versa using &lt;code&gt;DirectByteBuffer&lt;/code&gt; objects - so I only have to write enough JNI/C code to allocate and destroy shared memory,
which I can then efficiently access from the Java code.&lt;/p&gt;
&lt;h3 id=&#34;passing-file-descriptors&#34;&gt;Passing file descriptors&lt;/h3&gt;
&lt;p&gt;This is a less obvious solution, since Java does &lt;em&gt;not&lt;/em&gt; provide public access to the native file descritor(s) for any operating system APIs, &lt;em&gt;however&lt;/em&gt;
the source code is available identifying where a socket stores this native value (which appears to be stable over many releases), and from JNI/C
I can easily access the required object field without the security challenges of doing so in managed Java code. I&amp;rsquo;ll live with this slightly hacky
solution for now (until Java has accessors for native descriptors, it&amp;rsquo;s been proposed a few times!)&lt;/p&gt;
&lt;h3 id=&#34;checking-for-input&#34;&gt;Checking for input&lt;/h3&gt;
&lt;p&gt;Wayland operates &lt;em&gt;asynchronously&lt;/em&gt; between client and server, there are only a couple of occasions when a client needs to &lt;em&gt;wait for input&lt;/em&gt; and we can
simply &lt;em&gt;block in a read call&lt;/em&gt;, at other times we need to &lt;em&gt;poll for input&lt;/em&gt; using a check for data being available to read. This &lt;em&gt;should work&lt;/em&gt;
via the &lt;code&gt;java.nio.channels.Selector&lt;/code&gt; mechanism, but sadly it does not. Thus I extend my JNI/C a little to provide a working data availability check,
using the above hack to obtain the native file descriptor and calling &lt;code&gt;ioctl(FIONREAD)&lt;/code&gt;, which does work!&lt;/p&gt;
&lt;h2 id=&#34;testing-ensues&#34;&gt;Testing ensues..&lt;/h2&gt;
&lt;p&gt;As soon as I have enough of the protocol implemented to connect and display something, then testing ensues - gotta see something on screen :) The
&lt;a href=&#34;https://git.sr.ht/~phlash/swingland/tree/trunk/item/src/com/ashbysoft/test/Wayland.java&#34;&gt;test program&lt;/a&gt; will now evolve along with the protocol components
as I add features. Oh, and it works nicely - this is 11 days in!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;wayland-test.png&#34; alt=&#34;random noise pattern test&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;swing-api-in-many-steps&#34;&gt;Swing API in many steps&lt;/h1&gt;
&lt;p&gt;With the underlying Wayland protocol up and running, I move on to a &amp;lsquo;baby steps&amp;rsquo; exploration of the Swing API, working down from one of my simple
applications (the powermonitor) and creating &amp;lsquo;just enough code to pass the tests&amp;rsquo;. This takes considerably longer than I hoped, as Swing is rather
tightly coupled, and small refactorings (such as hoisting state to a super class) result in a lot of changes to coupled code - bah!&lt;/p&gt;
&lt;p&gt;Along side the real application, I create a
&lt;a href=&#34;https://git.sr.ht/~phlash/swingland/tree/trunk/item/src/com/ashbysoft/test/Swingland.java&#34;&gt;Swing test application&lt;/a&gt; which provides scope for short cuts
and internal testing during development without hacking my real app about (always good to have something you can run after each change!)&lt;/p&gt;
&lt;p&gt;After another 5 days work, I get to see the first Swing app run, with almost no useful features, but API compatible with the real thing. Neat!&lt;/p&gt;
&lt;h2 id=&#34;features-then-more-features&#34;&gt;Features, then more features&lt;/h2&gt;
&lt;p&gt;So from here I start picking off features to add and working through the stack to &amp;lsquo;make it so&amp;rsquo; for each: first up a single 8x16 &lt;code&gt;MONOSPACED&lt;/code&gt; font
that I &lt;del&gt;steal&lt;/del&gt; borrow from &lt;a href=&#34;https://int10h.org/oldschool-pc-fonts/readme/&#34;&gt;The Ultimate Old Skool PC Font Pack&lt;/a&gt;, the original IBM VGA text mode
font. Retro computing FTW.&lt;/p&gt;
&lt;p&gt;This is followed up with input handling: first keyboard then mouse, both rather buggy; then more high level components (&lt;code&gt;Dialog&lt;/code&gt;, &lt;code&gt;JLabel&lt;/code&gt;, &lt;code&gt;JButton&lt;/code&gt;)
over the next few days, followed by improvements to &lt;code&gt;Graphics&lt;/code&gt; primitives.. and lots of debugging, particularly around the interaction with my
tiling window manager (&lt;code&gt;sway&lt;/code&gt;) and how it chooses to position new windows.&lt;/p&gt;
&lt;p&gt;Cursor support bogs me down for a bit, especially the interaction between an asynchronous protocol, and the need to change the cursor on demand
while the pointer is within a single Wayland window, also the increasingly complex logic required to flow input events through the component stack,
which I refactor a couple of times.&lt;/p&gt;
&lt;h2 id=&#34;help-arrives&#34;&gt;Help arrives!&lt;/h2&gt;
&lt;p&gt;About a month into the project, my eldest son arrives for a family visit, and gets interested in the madness.. he pulls the repository, builds the
code and it runs first time, on his Pinebook, which is both an ARM (not x86) and big-endian by default - I&amp;rsquo;m almost impressed this just works!&lt;/p&gt;
&lt;p&gt;He also find and fixes a couple of protocol bugs for me - thanks Martin!&lt;/p&gt;
&lt;h2 id=&#34;dogfooding-time&#34;&gt;Dogfooding time&lt;/h2&gt;
&lt;p&gt;At this point I decide to write an app that both uses Swingland and supports it, a font editor for the custom file format I have created to store
simple bitmap fonts - this allows me to create a proper cursor font without hand-editing in a hex editor (which I have been doing until now!)&lt;/p&gt;
&lt;p&gt;The process of creating this real application finds more bugs (of course!)..&lt;/p&gt;
&lt;h2 id=&#34;image-support&#34;&gt;Image support&lt;/h2&gt;
&lt;p&gt;The next feature is the &lt;code&gt;ImageIO&lt;/code&gt; library that allows bitmap images to be loaded. Because I have contributed to it and I think it&amp;rsquo;s cool, I start
with the &lt;a href=&#34;https://qoiformat.org/&#34;&gt;Quite OK Image format&lt;/a&gt;, then &lt;a href=&#34;https://en.wikipedia.org/wiki/PNG&#34;&gt;Portable Network Graphics&lt;/a&gt; as most images will
be in PNGs. Transparency and alpha blending follow as both image formats support alpha channels.&lt;/p&gt;
&lt;h2 id=&#34;window-manager-interaction&#34;&gt;Window manager interaction&lt;/h2&gt;
&lt;p&gt;Switching an application to full screen (and back) under program control is explicitly supported in Swing, and useful for games or similar, so this
goes in next, and requires yet another refactor of the way Swing interacts with Wayland&lt;/p&gt;
&lt;h2 id=&#34;menus&#34;&gt;Menus!&lt;/h2&gt;
&lt;p&gt;At this point we&amp;rsquo;re approaching the 80% useful mark of the &lt;a href=&#34;https://en.wikipedia.org/wiki/Pareto_principle&#34;&gt;Pareto Principle&lt;/a&gt;, Swingland is looking
like an actually useful libray (tm), although it really needs application menus.. cue another round of refactoring, popup window handling and event
processing re-design, and we have it! Looking good:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;swingland-lives.png&#34; alt=&#34;swingland-lives!&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;getting-braver-with-testing&#34;&gt;Getting braver with testing&lt;/h2&gt;
&lt;p&gt;Having exhausted my own applications as test beds, I decide to move on to the Oracle-provided Swing demo apps, in particular the &lt;code&gt;TopLevelDemo&lt;/code&gt; and
&lt;code&gt;ButtonDemo&lt;/code&gt; ones that should now work with a simple change of imports and a re-compile.. well almost ;) More debugging and fiddling with the detail
of button processing ensues.&lt;/p&gt;
&lt;h2 id=&#34;more-fonts&#34;&gt;More fonts..&lt;/h2&gt;
&lt;p&gt;The latest feature to go in is support for X11/PCF font files, which opens up a world of reasonable fonts for text. I had looked at TrueType (TTF)
fonts earlier and decided that they were far too much work for now (a whole virtual machine and binary executable format to just fiddle with point
positions during layout.. err nope!).&lt;/p&gt;
&lt;h1 id=&#34;ongoing-development&#34;&gt;Ongoing development&lt;/h1&gt;
&lt;p&gt;I hope to maintain Swingland as an actually useful library for some time, and would particularly welcome other contributors who need other Swing
features that they could develop. Come get some &lt;a href=&#34;https://git.sr.ht/~phlash/swingland&#34;&gt;hot source&lt;/a&gt;&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>DOOM! on the EMF TiDAL badge</title>
      <link>https://www.ashbysoft.com/articles/doom-tidal/</link>
      <pubDate>Fri, 22 Jul 2022 14:00:00 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/doom-tidal/</guid>
      <description>Phil &amp;amp; Simon went to emfcamp this year - does the badge run DOOM yet?</description>
      <content:encoded>&lt;h2 id=&#34;does-it-run-doom&#34;&gt;Does it run DOOM?&lt;/h2&gt;
&lt;figure class=&#34;float-left&#34;&gt;&lt;a href=&#34;tidal-proto-long.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/doom-tidal/tidal-proto-long.jpg&#34; width=&#34;504&#34; height=&#34;378&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;It&amp;rsquo;s becoming the defacto question for any piece of technology with a display on it.. fridges,
printers, &lt;a href=&#34;https://itrunsdoom.tumblr.com/&#34;&gt;all sorts of things&lt;/a&gt; can run DOOM.&lt;/p&gt;
&lt;p&gt;So why not this shiny new ESP32S3 based &lt;a href=&#34;https://badge.emfcamp.org/&#34;&gt;electronic badge&lt;/a&gt; I have
just received from ElectroMagnetic Field 2022? It has a decent dual core 32bit Xtensa MCU,
8MB of RAM, 8MB of flash storage (partitioned up - see below) and an ST7789 colour pixel display.&lt;/p&gt;
&lt;p&gt;Oh, and a joystick :)&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h2 id=&#34;similar-work-amp-self-imposed-constraints&#34;&gt;Similar work &amp;amp; self-imposed constraints&lt;/h2&gt;
&lt;p&gt;There is a &lt;a href=&#34;https://github.com/espressif/esp32-doom&#34;&gt;port of DOOM for an ESP32&lt;/a&gt;, proving that it
can be done, however I have added additional constraints on myself as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Co-exist with the Micropython environment that comes &lt;em&gt;pre-installed&lt;/em&gt; on the badge.&lt;/li&gt;
&lt;li&gt;Create an app that can be distributed from the &lt;a href=&#34;https://2022.badge.emfcamp.org/&#34;&gt;TiDAL Hatchery&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;so-what-does-the-micropython-runtime-environment-look-like&#34;&gt;So what does the micropython runtime environment look like?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;It&amp;rsquo;s based on the &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/stable/esp32s3/get-started/index.html&#34;&gt;Espressif IoT Development Framework (IDF)&lt;/a&gt;,
which defines a &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/stable/esp32s3/api-guides/partition-tables.html&#34;&gt;storage partitioning scheme&lt;/a&gt; that
I cannot replace (but I can use to my advantage..)&lt;/li&gt;
&lt;li&gt;ESP-IDF, and thus Micropython are not designed as an OS with runtime application loading/unloading in mind..&lt;/li&gt;
&lt;li&gt;Micropython &lt;em&gt;is extensible at runtime&lt;/em&gt;, via pre-built &lt;code&gt;.mpy&lt;/code&gt; format modules, which can be compiled from &lt;code&gt;C&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;and-the-hatchery-format&#34;&gt;..and the Hatchery format?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A folder named after the app (eg: &lt;code&gt;/apps/Doom&lt;/code&gt;), that &lt;em&gt;must&lt;/em&gt; be a python module (ie: contain an &lt;code&gt;__init__.py&lt;/code&gt; file),
plus any other files required to run.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;__init__.py&lt;/code&gt; must define an instance of an &lt;code&gt;App&lt;/code&gt; class (or subclass) that the badge shell can locate / load.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;cunning-plan-1-and-failure&#34;&gt;Cunning plan #1, and failure.&lt;/h2&gt;
&lt;p&gt;How hard can it be to simply compile up DOOM as an &lt;code&gt;.mpy&lt;/code&gt; extension, patch in the I/O (display, files, user-input)
back to Micropython and load it up?&lt;/p&gt;
&lt;p&gt;It turns out the Micropython extension format is &lt;em&gt;very homebrew&lt;/em&gt; (for perfectly good reasons), and comes with
significant limitations compared to an off-the-shelf application format such as &lt;code&gt;ELF&lt;/code&gt; or &lt;code&gt;COFF&lt;/code&gt;, in particular:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No declared data, there is no support for loading a &lt;code&gt;.data&lt;/code&gt; segment as part of a module.&lt;/li&gt;
&lt;li&gt;No static global variables (you know, the bedrock of most C programs!) as it cannot re-locate references when
loading into memory, only &lt;em&gt;visible&lt;/em&gt; globals can be used.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also had to choose a starting version of DOOM, with an emphasis on portability. This turned out to be the easy
bit, enter &lt;a href=&#34;https://github.com/ozkl/doomgeneric&#34;&gt;DOOM generic&lt;/a&gt;, which happily compiled and ran first time on my
Linux desktop ;)&lt;/p&gt;
&lt;p&gt;Oh, and of course I had to write a new scaler for the video to &lt;em&gt;reduce&lt;/em&gt; 320x200 =&amp;gt; 240x135.&lt;/p&gt;
&lt;h3 id=&#34;the-grind&#34;&gt;The grind..&lt;/h3&gt;
&lt;p&gt;So, first remove all declared data from the DOOM sources, by moving initialisation into suitable &lt;code&gt;xx_Init()&lt;/code&gt; functions
if they are available, or adding them if not. ~2000 lines of code (LoC) changed, a number of ugly corner cases simply
removed (like being able to change key bindings) and it runs on the desktop again - phew!&lt;/p&gt;
&lt;p&gt;Now remove that &lt;code&gt;static&lt;/code&gt; keyword from all the global variables, and prefix them all with a local module abbreviation
to avoid collisions. Another ~2000 LoC changed, and it still runs on the desktop - double phew since this took several days!&lt;/p&gt;
&lt;p&gt;Chuck all those changes into a &lt;em&gt;large&lt;/em&gt; &lt;code&gt;git patch&lt;/code&gt; file, and save it away. Done.&lt;/p&gt;
&lt;h3 id=&#34;tooling-fail&#34;&gt;Tooling fail.&lt;/h3&gt;
&lt;p&gt;Compile everything according to the Micropython supplied tooling. Discover it cannot link certain object files - grrr :(&lt;/p&gt;
&lt;p&gt;Fix &lt;a href=&#34;https://github.com/micropython/micropython/issues/8781&#34;&gt;Multiple&lt;/a&gt;, &lt;a href=&#34;https://github.com/micropython/micropython/issues/8782&#34;&gt;bugs&lt;/a&gt;
in &lt;a href=&#34;https://github.com/micropython/micropython/issues/8783&#34;&gt;Micropython&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Chuck all the Micropython bug fixes into a &lt;code&gt;git patch&lt;/code&gt; file and save that away. Done now?&lt;/p&gt;
&lt;h3 id=&#34;runtime-fail&#34;&gt;Runtime fail.&lt;/h3&gt;
&lt;p&gt;Errr nope. It turns out Micropython &lt;a href=&#34;https://docs.micropython.org/en/latest/reference/mpyfiles.html&#34;&gt;makes more assumptions about how code is compiled&lt;/a&gt;,
in particular that all things are relocatable in memory via a single Global Offset Table (GOT). DOOM makes different assumptions,
and repeatedly crashes in unpredictable locations due to memory corruption.&lt;/p&gt;
&lt;p&gt;After a few days trying to debug this fiasco (with &lt;code&gt;printf&lt;/code&gt; of course since I cannot use a debugger due to proprietary
module formatting and a special loader), I give up.&lt;/p&gt;
&lt;h2 id=&#34;cunning-plan-2-and-success-eventually&#34;&gt;Cunning plan #2, and success (eventually!)&lt;/h2&gt;
&lt;h3 id=&#34;back-to-basics&#34;&gt;Back to basics&lt;/h3&gt;
&lt;p&gt;Having dismally failed to run anything so far, I decide to start at the other end, building up from a &lt;em&gt;Hello Mum!&lt;/em&gt;
program that relies only on the &lt;em&gt;built-in ESP-ROM&lt;/em&gt; (and is compiled &lt;em&gt;without&lt;/em&gt; the Micropython &amp;ldquo;special tooling&amp;rdquo; that
is causing me problems), designed to run as the first user-provided code on the device, in ESP-IDF parlance,
as the &amp;ldquo;secondary boot loader&amp;rdquo;. Thus is born &lt;code&gt;phlashboot&lt;/code&gt;, the shortest program I can write that says &amp;lsquo;Hi&amp;rsquo; without
crashing.&lt;/p&gt;
&lt;p&gt;After some trial &amp;amp; error with watchdog timers, this works - relief!&lt;/p&gt;
&lt;h3 id=&#34;a-new-plan-forms&#34;&gt;A new plan forms&lt;/h3&gt;
&lt;p&gt;Remember I mentioned a &lt;code&gt;Partition table&lt;/code&gt; that ESP-IDF uses? This puts application code in a specific location within flash^
(one of two &amp;lsquo;over-the-air&amp;rsquo; or OTA update partitions), along with a header that defines &lt;em&gt;where in memory it runs, including
if it&amp;rsquo;s memory mapped&lt;/em&gt;. The normal boot flow of an ESP-IDF application is that the secondary loader applies the defined
memory mapping or copies code/data into RAM (hello &lt;code&gt;.data&lt;/code&gt;!), then jumps to a defined entry point. Neat.&lt;/p&gt;
&lt;p&gt;This is how Micropython itself get&amp;rsquo;s going, can I re-use the same flow to load/run my application at &lt;em&gt;known memory
locations outside Micropython&lt;/em&gt;, without having to use the broken &lt;code&gt;.mpy&lt;/code&gt; module format? Baby steps ensue..&lt;/p&gt;
&lt;p&gt;^ for those of you wondering why not memory map from the filesystem part of flash? The MMU is not granular enough for this,
hence having to map from a specific &amp;lsquo;OTA&amp;rsquo; partition offset.&lt;/p&gt;
&lt;h3 id=&#34;gently-does-it&#34;&gt;Gently does it..&lt;/h3&gt;
&lt;p&gt;I adapt &lt;code&gt;phlashboot&lt;/code&gt; so it doesn&amp;rsquo;t expect to be the bootloader, instead it looks like an OTA application, which the ESP-IDF
secondary loader is happy to memory map (mmap) and run, next step..&lt;/p&gt;
&lt;p&gt;After a great deal of reading through &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/index.html&#34;&gt;technical manuals&lt;/a&gt;
and &lt;a href=&#34;https://github.com/espressif/esp-idf&#34;&gt;rummaging in the code&lt;/a&gt;, creating the &lt;code&gt;romread&lt;/code&gt; test application and generally
poking at (and crashing) my device, I understand how the memory manager works, what I can and cannot touch and in theory
how I can &lt;em&gt;memory map and execute another app within micropython&lt;/em&gt;. There is also a fair amount of investigation into the
Micropython memory layout, see &lt;code&gt;memstuff&lt;/code&gt; folder! Thus is born &lt;code&gt;doomloader.mpy&lt;/code&gt; a short and &lt;em&gt;separate&lt;/em&gt;
Micropython module that pokes at the MMU to load an OTA app into Micropython-safe address space. It works :D, next step..&lt;/p&gt;
&lt;h3 id=&#34;doom-is-back-baby&#34;&gt;DOOM is back baby!&lt;/h3&gt;
&lt;p&gt;I can now use standard tooling, to build a standard application and run it on device &amp;ldquo;underneath&amp;rdquo; Micropython, so back
to DOOM. There is some fiddling with compiler options and load addresses to get a sensible OTA application out, which
fits easily into a flash (~460k, OTA partitions are 2MiB), the existing plan for connecting in I/O is still intact(!)
so in theory it should work&amp;hellip; and it doesn&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;It turns out that DOOM expects a little more POSIX compliance from it&amp;rsquo;s C library than Micropython provides, in particular
the &lt;code&gt;printf&lt;/code&gt; implementation is lacking many features. The good part is that because I&amp;rsquo;m building an entirely separate
binary application, I can &lt;a href=&#34;https://github.com/charlesnicholson/nanoprintf&#34;&gt;&lt;em&gt;use someone elses printf&lt;/em&gt;&lt;/a&gt;, and finally, after
a &lt;em&gt;lot&lt;/em&gt; of pain, it runs!&lt;/p&gt;
&lt;p&gt;The colours are awful. I can&amp;rsquo;t actually control anything yet. I&amp;rsquo;m deliriously happy :D&lt;/p&gt;
&lt;h3 id=&#34;final-fixes&#34;&gt;Final fixes&lt;/h3&gt;
&lt;p&gt;The colour being mangled turns out to be an endian difference between the MPU and the display device, easily determined by
looking at the &lt;a href=&#34;https://github.com/russhughes/st7789_mpy&#34;&gt;code for the display driver&lt;/a&gt;, which byte-swaps everything when
drawing into the device, unless it&amp;rsquo;s blitting a buffer, when it &lt;em&gt;assumes it&amp;rsquo;s already swapped&lt;/em&gt;. Fixed.&lt;/p&gt;
&lt;p&gt;Providing user input is a case of finding the right DOOM keys to fake when pressing joystick buttons or others on the badge.&lt;/p&gt;
&lt;h2 id=&#34;show-me-the-code&#34;&gt;Show me the code!&lt;/h2&gt;
&lt;p&gt;To horribly mis-quote another of my favourite games &lt;a href=&#34;https://git.sr.ht/~phlash/doom-tidal&#34;&gt;come get some baby!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;..OR..&lt;/p&gt;
&lt;p&gt;Grab the built objects &lt;a href=&#34;https://2022.badge.emfcamp.org/projects/doom&#34;&gt;from the hatchery&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;the-required-demo-video&#34;&gt;The required demo video..&lt;/h2&gt;
&lt;p&gt;&lt;video width=&#34;960&#34; height=&#34;540&#34; src=&#34;../../images/TiDAL-DOOM.mkv&#34; controls &gt;Sorry, your browser doesn&amp;rsquo;t support HTML5 video&lt;/video&gt;&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>HDMI Switch Reversing</title>
      <link>https://www.ashbysoft.com/articles/hdmi-switch-reversing/</link>
      <pubDate>Mon, 14 Feb 2022 21:33:45 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/hdmi-switch-reversing/</guid>
      <description>Long time, no blog entry, but Phil has been playing with some toys since Christmas, including an HDMI Switcher that almost worked right.</description>
      <content:encoded>&lt;h2 id=&#34;portta-hdmi-switch-41-with-audio&#34;&gt;PortTa HDMI Switch 4:1 with Audio&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://web.archive.org/web/20150717124158/http://www.port-ta.com/products/203.html&#34;&gt;Nearest archived product page I could find&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.ashbysoft.com/articles/phlash/&#34;&gt;Phil&lt;/a&gt; bought one of the above recently to
avoid excessive grubbing about behind the TV changing over between XBox,
Laptop(s), PS4, DVD player&amp;hellip; you get the idea. It was cheap, it kind of
worked. Unfortunately it had a couple of features that made it useless
in my circumstances: no auto-switching to active input; overlapping IR
codes with my Humax box (change channel on the Humax and the switch
powers down!)&lt;/p&gt;
&lt;p&gt;Needless to say I have had no joy asking the vendor for info on fixing
these bugs, so I could send it back and try another brand, or.. open it
up :) Turns out a couple of folks have taken a look inside similar
devices, mostly to hack round HDCP protection, so I have some idea what
to expect and indeed it&amp;rsquo;s pretty unexciting:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;../../images/upload/IMG_20170526_231505.jpg&#34;&gt;&lt;img src=&#34;../../images/upload/IMG_20170526_231505.png&#34; alt=&#34;HDMI Switch PCB&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a couple of devices from Explore Microelectronics that do the
work (EP94A1K: HDMI switch, EPF021A: MCU), an SPI audio DAC to provide
analogue outputs and some lights and buttons.&lt;/p&gt;
&lt;p&gt;I grabbed the data sheets for the MCU device (or similar, as they&amp;rsquo;re
closed source / NDA stuff) and after much Internet hunting also found
some &lt;a href=&#34;https://ap.koryo.cow.tw&#34;&gt;programming tools&lt;/a&gt;
written in C#/.NET for XP that may work with the MCU (EPF021A).&lt;/p&gt;
&lt;p&gt;The plan:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;* activate the ICP (in-circuit programming) mode in the MCU&lt;/code&gt;&lt;br&gt;
&lt;code&gt;* extract the existing firmware, prove I can re-program the device&lt;/code&gt;&lt;br&gt;
&lt;code&gt;* put a toolchain together that can build new firmware&lt;/code&gt;&lt;br&gt;
&lt;code&gt;* write some open-source firmware to fix my bugs and anyone else&#39;s&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The ICP protocol is badly documented (aka missing), so that needs
reversing from the C#/.NET tools; the PCB is missing the necessary
pull-up resistors for the serial port (normal anti-reversing / cost
saving trick); I don&amp;rsquo;t know if the ICP allows reading the firmware out
(see below!).&lt;/p&gt;
&lt;h3 id=&#34;hardware-first&#34;&gt;Hardware first&lt;/h3&gt;
&lt;p&gt;The EPF011/021 data sheet indicates serial port pins, which appear to be
brought out to solder pads (nice), however the pull-up resistors have
been left off and I need to borrow a TTL-serial adapter (thanks Jason!)
A bit of soldering later and all is good here. Baud rate - get the
&amp;lsquo;scope out and measure the pulse width, looks like ~17usecs/57600 which
matches the screenshots in the dodgy manual for the programming
software.&lt;/p&gt;
&lt;h3 id=&#34;serial-traffic&#34;&gt;Serial traffic&lt;/h3&gt;
&lt;p&gt;So, does it say anything when powered up? fire up minicom and configure
as 57600/8N1. Yes! Hello KL113 software :) I see some debug info at
boot, and more when pressing the channel change button. Out of curiosity
I poked at my keyboard and was surprised to see a message &amp;ldquo;DBGCMD Buffer
Full&amp;rdquo;, ah-ha, looks like I can interact in some way with the firmware..
we&amp;rsquo;ll come back to that!&lt;/p&gt;
&lt;p&gt;What about ICP mode (the data sheet says a pin needs tying to Vdd at
boot - that too is usefully brought to a pair of pads)? Unfortunately
the data sheet says nothing about the device being erased if you enable
ICP mode, time to take a risk. Pop a jumper across the pads, and power
up: I get a continuous stream of semi-colons on the serial port,
probably some kind of synchronisation / detection, and no smoke. Power
down, take off the jumper and re-start - it&amp;rsquo;s back doing normal things -
phew!&lt;/p&gt;
&lt;h3 id=&#34;take-apart-the-programming-tool&#34;&gt;Take apart the programming tool&lt;/h3&gt;
&lt;p&gt;So what of the programming software? Well it works on XP or Win7, but
sadly doesn&amp;rsquo;t have the &amp;lsquo;read device&amp;rsquo; button enabled. Time to pull it
apart too. My tool of choice here is dotNetPeek from JetBrains, a
completely awesome decompiler that turns out almost re-compilable C#
and a Visual Studio project to work in from the .exe - sweet :)&lt;/p&gt;
&lt;p&gt;Now I have a choice, try and fix their code to enable the device read
function, or re-implement from understanding the ICP protocol. Given I
want to end up with Open Source (not decompiled!) code, I&amp;rsquo;ll
re-implement. Following the rather badly structured application down to
the serial port I/O I get the following to read the device:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Bootstrap:
- wait for a sequence of &#39;;&#39; characters (at least 10)
- write &#39;5&#39;, wait to see if &#39;;&#39; chars stop. Repeat if not (up to 4096 times)

Read Flash (one 512 byte block):
- set mode (read) and address (multiple of 256)
  - write 139 (dec) followed by (addr &amp;gt;&amp;gt; 8)
  - read byte, confirm 139 (dec)
  - write 85 (dec)
  - read byte, confirm (addr &amp;gt;&amp;gt; 8)
  - write 85 (dec)
- start command execution
  - write 140 (dec)
- read block bytes and ack
  - read 512 bytes
  - write 85 (dec)
- read block end and ack
  - read byte, confirm 136 (dec)
  - write 85 (dec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;..and for the brave to write to it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Bootstrap (as above)

Write flash (one 512 byte block):
- set mode (write) and address (multiple of 256)
  - write 138 (dec) followed by (addr &amp;gt;&amp;gt; 8)
  - read byte, confirm 138 (dec)
  - write 85 (dec)
  - read byte, confirm (addr &amp;gt;&amp;gt; 8)
  - write 85 (dec)
- start command execution
  - write 140 (dec)
- write block of bytes
  - write 512 bytes
- read block end and ack
  - read byte, confirm 136 (dec)
  - write 85 (dec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;NB: in both cases, the address must be a multiple of 512 (flash block
size), or the device will return an error code in place of the command
echo.&lt;/p&gt;
&lt;p&gt;This seems easy enough to replicate in clean code, and indeed it worked
first time, I have a &lt;a href=&#34;../../images/upload/dump.bin&#34;&gt;flash dump&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;getting-a-new-toolchain-working&#34;&gt;Getting a new toolchain working&lt;/h3&gt;
&lt;p&gt;I picked the readily available (standard package) &lt;code&gt;sdcc&lt;/code&gt; compiler and
fiddled with it&amp;rsquo;s settings to reduce the junk it emits for 8051 targets,
writing my own &lt;code&gt;boot.asm&lt;/code&gt; minimal startup and a couple of very short
test programs (blinkenlight obviously, and a serial port reflector).&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Makefile&lt;/code&gt; does a little more fettling with &lt;code&gt;sdobjcopy&lt;/code&gt; to convert
the Intel hex output of the linker to a binary image, and it works :)&lt;/p&gt;
&lt;h3 id=&#34;thats-it-for-now&#34;&gt;That&amp;rsquo;s it for now&lt;/h3&gt;
&lt;p&gt;Code &lt;a href=&#34;https://git.sr.ht/~phlash/EPFTools&#34;&gt;here in Sourcehut&lt;/a&gt;.&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>GEO Trio II In-Home-Display Insides</title>
      <link>https://www.ashbysoft.com/posts/geo-trio-ii-disassembly/</link>
      <pubDate>Sat, 06 Nov 2021 22:14:30 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/geo-trio-ii-disassembly/</guid>
      <description>I&amp;rsquo;d like to build my own modules for this extensible display..</description>
      <content:encoded>&lt;h1 id=&#34;updates&#34;&gt;Updates&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;2021-11-06&lt;/strong&gt;: Stupid bug fixed in capture code (doh!), links below
are to updated code and &lt;em&gt;corrected&lt;/em&gt; log from an IHD connected to the Geo
together cloud servers and mobile app - whoo :=) As below, all data
exchanged with the cloud is encrypted in some way apart from an obvious
timestamp at the start..&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2021-08-27&lt;/strong&gt;: Much better logs and a corresponding packet capture now
available, annotated with what I have now worked out - it&amp;rsquo;s making a
lot more sense, but sadly - it looks like the Trio II main device
protects all transmitted data before sending to the WiFi module :=(&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ashbysoft.com/wifidump.log&#34;&gt;Annoted log file&lt;/a&gt; (prepare for ASCII documentation!)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ashbysoft.com/geo.pcap&#34;&gt;Packet capture&lt;/a&gt; (load into your favourite decoder)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ashbysoft.com/esp-boot.txt&#34;&gt;WiFi boot text&lt;/a&gt; (might help with hacking firmware?)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;why-would-you-do-this&#34;&gt;Why would you do this?&lt;/h1&gt;
&lt;p&gt;I have just joined the millions who have 2nd gen (SMETS2) smart metering
installed, and was interested in sending metering data to other systems
(like home automation), but it turns out the existing standards and
devices don&amp;rsquo;t really support this (which is a bit crap but hey..)&lt;/p&gt;
&lt;p&gt;The In-Home-Display (IHD) unit I have is a Green Energy Options (GEO)
Trio II, which also works as a Consumer Access Device (CAD), if the
optional WiFi module is fitted. Turns out this will only talk to the
energy company web site and send &lt;em&gt;them&lt;/em&gt; the data for fancy cloud based
app stuff - not what I want.&lt;/p&gt;
&lt;p&gt;However - if the &lt;em&gt;interface&lt;/em&gt; to the WiFi module is easy to understand,
then it might be possible to build a special module that can divert
the data to a sane protocol such as MQTT. So what&amp;rsquo;s the module interface?&lt;/p&gt;
&lt;h1 id=&#34;heres-whats-in-a-geo-trio-ii&#34;&gt;Here&amp;rsquo;s what&amp;rsquo;s in a GEO Trio II&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://photos.app.goo.gl/Viq3mZQFctv81QUDA&#34;&gt;Teardown photos&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you can see, it&amp;rsquo;s a fairly simple beast, with just a few ICs, the
aerial (ZigBee for meter network), the LCD and buttons. The devices are
all identifiable (eventually, once you type the right text into search
engines).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MCU#1: NXP LPC54605J512ET180 low power MCU /
ARM Cortex-M4, 512k Flash, 200k SRAM, USB (x2), many serial/GPIOs&lt;/li&gt;
&lt;li&gt;MCU#2: NXP JN5169 wireless micro controller /
ARM (unstated), 512k Flash, 32k SRAM, 2.4GHz radio I/O, serial/GPIOs&lt;/li&gt;
&lt;li&gt;Flash: GigaDevices GD25Q32CSIG 32Mbit serial flash&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The WiFi adapter connects to the 6 pin 0.1&amp;quot; header at the top, two pins
(1,2) are Vdd and Gnd, one is likely a module detect line, leaving just
three for data - most likely an SPI or UART interface to a full-stack
WiFi+TCP/IP package such as this from Radicom:
&lt;a href=&#34;http://www.radi.com/modular101.htm&#34;&gt;Radicom embedded WiFi Serial Module&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;..which bodes well for faking stuff, as it may not be encrypted at this point
(the TLS happens on the WiFi module) :)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[update, Jan 2021]&lt;/strong&gt;: it&amp;rsquo;s not a standard WiFi/serial module, the WiFi
board has another user-programmable device, an ESP8285, running more Geo code..
this appears to handle asynchronous comms and has a separate command and
control protocol back to the main system. This makes sense if you wanted
to use a different network technology later on, and also holds promise
that I can still emulate and transmit my own data - quite possibly by
reprogramming the existing ESP8285 =) See below&amp;hellip;&lt;/p&gt;
&lt;p&gt;The unpopulated devices may be related to developing SMETS2 standards for
the radio interface, or a change of display technology, moving the LCD
controller function to the LCD itself.&lt;/p&gt;
&lt;p&gt;Next to the WiFi module connector is another set of pads that are accessible
without disassembling the device - these are very likely a JTAG (AVR layout)
connector for programming/upgrades, I still need to buzz these out to find
grounded pads, which will confirm this guess.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[update, Dec 2020]&lt;/strong&gt;: the pads are indeed an
&lt;a href=&#34;https://rowley.zendesk.com/hc/en-us/articles/210033613-What-is-the-pinout-of-the-ARM-10-pin-connector-&#34;&gt;ARM-10 JTAG/SWD&lt;/a&gt;
(dual mode) connector, confirmed by grounding of pads 3,5,9 :)&lt;/p&gt;
&lt;h1 id=&#34;investigating-the-wifi-module&#34;&gt;Investigating the WiFi module&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;[update, Dec 2020]&lt;/strong&gt;: Courtesy of an email or two with William McNicol (thanks!)
I have purchased a WiFi module direct from GEO here:
&lt;a href=&#34;https://www.geotogether.com/consumer/product/wifi-module/&#34;&gt;GEO WiFi module&lt;/a&gt;
plugged it in and confirmed that it&amp;rsquo;s sending packets to the &amp;rsquo;net - rather
surprisingly UDP/IP. More info once I&amp;rsquo;ve got the &amp;lsquo;scope on the connector
pins!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[update, Jan 2021]&lt;/strong&gt;: I finally got round to probing the WiFi module while it&amp;rsquo;s
connected to the main system, and yes, it&amp;rsquo;s a simple UART @ 115k2 8n1 with both
Tx and Rx lines. Attaching an FTDI FT232 at 3v3 logic levels gives me bytes, oh
so many bytes&amp;hellip; so what to do with them?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[update, Jul 2021]&lt;/strong&gt;: I forgot to include the pinout for the WiFi module (thanks
Tim for the nudge!):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(as numbered on the board itself, looking at the back while connected to the IHD)
3v3 - 2  1 - GND
n/c - 4  3 - n/c
Din - 6  5 - Dout
(where Din = UART Data INto the WiFi board, Dout = UART Data OUT of the WiFi board)
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;relationship-between-serial-traffic-and-network&#34;&gt;Relationship between serial traffic and network&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;[update, Aug 2021]&lt;/strong&gt;: I acquired a second TTL serial to USB adapter, and wrote
&lt;a href=&#34;https://www.ashbysoft.com/wifidump.c&#34;&gt;a packet decoder&lt;/a&gt; that gave me much nicer timestamped serial traffic
logs (see top of page!), my assumptions below were a little off, but close :=)&lt;/p&gt;
&lt;h3 id=&#34;historic-info&#34;&gt;historic info&lt;/h3&gt;
&lt;p&gt;I thought it best to try and understand the relationship between traffic on the
serial interface and the network, so I hooked up the FT232 and my network sniffer
to a common clock source (thanks NTP!) and watched everything for the first few
minutes of IHD operation.&lt;/p&gt;
&lt;p&gt;It turns out to be pretty complex - I was able to deduce some of the serial message
format, in particular the start message marker, the length and checksum fields, which
gave me accurate timestamps for each message, and some content boundaries. Trying to
relate these to the UDP traffic on the other hand was not making any sense, it looks
like the command protocol simply issues a &amp;lsquo;connect please&amp;rsquo; request, or one of a couple
of other requests (there are obvious request type codes), and the ESP8285 operates
completely asychronously, sending multiple different network packets, none of which
appear to contain much from the serial messages. There is some consistent timing that
I have noticed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;serial messages are typically at 10 second intervals (per message type)&lt;/li&gt;
&lt;li&gt;network packets are at 4 second intervals (per length/type)&lt;/li&gt;
&lt;li&gt;network packets are repeated 4 times, each with the same timestamp&lt;/li&gt;
&lt;li&gt;network packet timestamps appear to be related to ZigBee / meter time, but
I cannot see this transferred in the serial messages when it updates from
boot (2011) to now (2020) :=(&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Full details are &lt;a href=&#34;https://www.ashbysoft.com/ihd-serial-tx.log&#34;&gt;in my log file&lt;/a&gt; (prepare for ASCII documentation!)&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Libvirt, QEMU &amp; Samba</title>
      <link>https://www.ashbysoft.com/posts/libvirt-qemu-samba/</link>
      <pubDate>Thu, 01 Oct 2020 16:05:00 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/libvirt-qemu-samba/</guid>
      <description>Finally getting a working user-mode shared folder!</description>
      <content:encoded>&lt;h2 id=&#34;trying-to-be-different-again&#34;&gt;Trying to be different again?&lt;/h2&gt;
&lt;p&gt;Well, yes. I have used many virtualisation systems over the years, and many of them &amp;lsquo;just work&amp;rsquo;, especially
well supported tools such as HyperV or VirtualBox, however I wanted to find a solution that was possible
in plain Debian stable, no special repositories (eg: Oracle for VBox), no special agents in the guest (again
VBox needs this) and fully open source (ruling out VMware and HyperV stuff).&lt;/p&gt;
&lt;p&gt;Out-of-the-box virt-manager+libvirt+qemu (also kvm for x86 guests) works quite well for actually running my
guest VMs, the networking is well integrated, the GUI (Spice or VNC) is usable too. Choosing qemu as the
virtualiser means many target platforms (eg: ARM, x86, Sparc, &amp;hellip;) and it tends to be first with new targets
too.&lt;/p&gt;
&lt;p&gt;The problem I wanted to solve has been around for years, but there hasn&amp;rsquo;t been a single documented solution:
getting a shared folder exposed from my Debian/linux host to a Windows (7) guest VM, while running everything
in user-mode, ie: as me. No special privileges or VMs escaping as root!&lt;/p&gt;
&lt;h3 id=&#34;so-what-should-work&#34;&gt;So what &lt;em&gt;should&lt;/em&gt; work?&lt;/h3&gt;
&lt;p&gt;There are guides, oh so many guides to ramming special software into the guest so it can talk Plan9, which
is the only qemu built-in protocol for file system access. This is usually a litany of pain and hideously
slow, probably worth avoiding.&lt;/p&gt;
&lt;p&gt;What about good old SMB/Samba then? Windows will be fine, just need to install a file server on your host
machine and pipe that networking through.. again, many tutorials, that assume you are running stuff as
root (default libvirt setup), that your VM will have networking (what if you are investigating malware?)
and of course lots of manual messing with smb.conf and trying not to expose your host file system to
elsewhere! It&amp;rsquo;s still slow :(&lt;/p&gt;
&lt;p&gt;Interestingly, qemu has built-in pseudo-support for SMB, the -netdev user,smb=/path/to/folder option, as
long as you have Samba installed (doesn&amp;rsquo;t need to be running, qemu does that, plus configuration). This
looks promising, but sadly libvirt and virt-manager know nothing about it so I put this aside for a bit..&lt;/p&gt;
&lt;p&gt;I found a &amp;lsquo;modern&amp;rsquo; alternative, the aptly named &lt;a href=&#34;https://virtio-fs.gitlab.io/&#34;&gt;Virtio-FS&lt;/a&gt;, which promises
performance and security, doesn&amp;rsquo;t need network adapters in the guest and support from RedHat - could be
good?&lt;/p&gt;
&lt;h3 id=&#34;virtio-fs&#34;&gt;Virtio-FS&lt;/h3&gt;
&lt;p&gt;I went with modernity, it has to be better than what it&amp;rsquo;s trying to replace right?&lt;/p&gt;
&lt;p&gt;Turns out, it&amp;rsquo;s a little too modern for Debian stable, I needed a backport build of qemu (v5.0+) to get
the necessary support, then of course libvirt/virt-manager know nothing about it, and there isn&amp;rsquo;t a
backport for these - cue much hacking trying to write that supporting logic in bash in a wrapper script
around qemu (don&amp;rsquo;t do this people!)&amp;hellip;&lt;/p&gt;
&lt;p&gt;Then there&amp;rsquo;s the assumption in the source for virtiofsd (the actual file i/o daemon) that it will be
running as root, because that&amp;rsquo;s how libvirt operates&amp;hellip; nope :( I actually went as far as to pull the source
and fix it, but then finally fell foul of a gap in support on the guest - virtio-fs is only supported
on Windows 8+ Gah! I did learn a lot about libvirt/virt-manager and qemu however!&lt;/p&gt;
&lt;h3 id=&#34;samba-again---but-working&#34;&gt;Samba (again - but working)&lt;/h3&gt;
&lt;p&gt;So back to option #2, SMB/Samba, using the qemu built-in forwarding to a local instance of smbd that
it configures correctly, all with just one simple command line option, that I now understand how to
provide through libvirt/virt-manager - it doesn&amp;rsquo;t work&amp;hellip; Much debugging/rummaging and swearing later
I find that libvirt makes assumptions about how you want to run qemu, in particular it enables the
security sandbox that stops qemu spawning another program - ie: smbd! With this disabled (undocumented
file location BTW), it finally works.&lt;/p&gt;
&lt;p&gt;Alleged documentation for &lt;a href=&#34;https://www.libvirt.org/kbase/qemu-passthrough-security.html&#34;&gt;libvirt security&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;what-actually-needs-doing-then&#34;&gt;What actually needs doing then?&lt;/h2&gt;
&lt;p&gt;OK, here&amp;rsquo;s the full list of things to make user-mode SMB work with libvirt/virt-manager/qemu (+kvm):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Install required packages: &lt;code&gt;# aptitude install virt-manager, qemu, qemu-kvm&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create your VM as desired (or import from elsewhere, VBox in my case)&lt;/li&gt;
&lt;li&gt;Remove the NIC - you will be putting this back via custom arguments below..&lt;/li&gt;
&lt;li&gt;Use the magic &lt;code&gt;virt-xml&lt;/code&gt; tool to add custom qemu arguments as per
&lt;a href=&#34;https://unix.stackexchange.com/questions/235414/libvirt-how-to-pass-qemu-command-line-args&#34;&gt;Stack Overflow&lt;/a&gt;
&lt;code&gt;% virt-xml $(VM) --edit --confirm --qemu-commandline &#39;-netdev&#39;&lt;/code&gt;
to add a single arg, then
&lt;code&gt;% virsh edit $(VM)&lt;/code&gt;
to get into your chosen text editor and add the following additional lines below -netdev:
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;lt;qemu:arg value=&amp;#39;user,id=hostnet0,smb=/path/to/shared/folder&amp;#39;/&amp;gt;
&amp;lt;qemu:arg value=&amp;#39;-device&amp;#39;/&amp;gt;
&amp;lt;qemu:arg value=&amp;#39;virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:21:69:da,bus=pci.1,addr=0x0&amp;#39;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;NB: You may want to change my MAC for one of yours :)&lt;/li&gt;
&lt;li&gt;Create/edit a user-mode qemu.conf in &lt;code&gt;~/.config/libvirt/qemu.conf&lt;/code&gt; and add this text:
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# Override defaults for libvirt when running in a user session
# Turn off the sandbox so we can spawn SMBD..
seccomp_sandbox=0
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This should be it - fire up your VM, ensure you have virtio network drivers installed (part of the OS
unless you are on Win7 - grab them from
&lt;a href=&#34;https://docs.fedoraproject.org/en-US/quick-docs/creating-windows-virtual-machines-using-virtio-drivers/&#34;&gt;Fedora Virtio-Win&lt;/a&gt;
if you are) and map that drive:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;C:\&amp;gt; net use X: \\10.0.2.4\qemu
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Whoo hoo!&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Apeman H45 Trail Camera Insides</title>
      <link>https://www.ashbysoft.com/posts/apeman-h45-insides/</link>
      <pubDate>Sat, 04 Jul 2020 17:20:30 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/apeman-h45-insides/</guid>
      <description>I needed to factory reset a borrowed trail cam but the owner forgot the PIN..</description>
      <content:encoded>&lt;h1 id=&#34;whats-in-the-box-phil&#34;&gt;What&amp;rsquo;s in the box Phil?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://photos.app.goo.gl/EGLB6MBsZdFBRCjr5&#34;&gt;I took some pictures&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It appears to be the common Sunplus 1628A based reference design shared
by many similar Chinese origin trail cameras.&lt;/p&gt;
&lt;h1 id=&#34;did-you-reset-the-pin&#34;&gt;Did you reset the PIN?&lt;/h1&gt;
&lt;p&gt;Err nope. No sign of a battery, so assuming it writes config to flash,
and I was unable to find a button-mashing-based reset process (although
there likely is one as the manufacturer offers a telephone reset service)&lt;/p&gt;
&lt;p&gt;We got lucky, the owner suggested a few numeric pairs they usually use
(I know - poor practice, they know too), and after 20-30 combinations
we got the magic value :)&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>A talk on threat modelling</title>
      <link>https://www.ashbysoft.com/posts/owasp-threat-modelling/</link>
      <pubDate>Sun, 24 May 2020 21:48:36 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/owasp-threat-modelling/</guid>
      <description>Phil did a talk last year for the local OWASP chapter..</description>
      <content:encoded>&lt;h2 id=&#34;threat-modelling-is-not-voodoo&#34;&gt;Threat modelling is not voodoo&lt;/h2&gt;
&lt;p&gt;..honest it&amp;rsquo;s not, but many folks think it&amp;rsquo;s special and don&amp;rsquo;t do it :( Thus &lt;a href=&#34;https://www.ashbysoft.com/articles/phlash/&#34;&gt;Phil&lt;/a&gt; put a talk together for his local
OWASP chapter, which seemed to be well received (you can judge for yourself in the video of course!)&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s only taken 8 months to get the slides on line!&lt;/p&gt;




&lt;div class=&#34;link&#34;&gt;&lt;a href=&#34;https://www.ashbysoft.com/presentations/threatmodeling/&#34;&gt;View raw presentation&lt;/a&gt; or click and press &#39;F&#39; for fullscreen&lt;/div&gt;
&lt;div class=&#34;presentation&#34; style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden&#34;&gt;
        &lt;iframe type=&#34;text/html&#34; src=&#34;https://www.ashbysoft.com/presentations/threatmodeling/&#34; allowfullscreen style=&#34;position: absolute; width: 100%; height: 100%; border: 0&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;Here&amp;rsquo;s me giving the talk (48mins, plus pizza!)&lt;/p&gt;


    
    &lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen=&#34;allowfullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/0HgYZEJXAJo?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;
      &gt;&lt;/iframe&gt;
    &lt;/div&gt;

</content:encoded>
    </item>
    
    <item>
      <title>Summerhouse for 2020!</title>
      <link>https://www.ashbysoft.com/articles/summerhouse/</link>
      <pubDate>Sun, 19 Apr 2020 13:25:10 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/summerhouse/</guid>
      <description>2 weeks off work and Coronavirus keeping us at home - let&amp;rsquo;s build something!</description>
      <content:encoded>&lt;h2 id=&#34;first-buy-a-kit&#34;&gt;First buy a kit..&lt;/h2&gt;
&lt;p&gt;Courtesy of the nice folks at &lt;a href=&#34;https://www.screwfix.com&#34;&gt;Screwfix&lt;/a&gt;,
and &lt;a href=&#34;https://www.shiregb.com/&#34;&gt;Shire Garden Buildings&lt;/a&gt;, we ordered
ourselves a new summerhouse, specifically the
&lt;a href=&#34;https://www.screwfix.com/p/shire-aster-summerhouse-3-59-x-2-39m/1298x&#34;&gt;Aster 12x8 foot model&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We had a delivery date of 29th March, then lockdown happened.. but it turns out deliveries
of existing orders are ok, so a pile of parts arrived on our driveway.&lt;/p&gt;
&lt;h2 id=&#34;paint-everything-twice&#34;&gt;Paint everything. Twice.&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&#34;float-left&#34;&gt;&lt;a href=&#34;th_IMG_20200406_173102886.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/summerhouse/th_IMG_20200406_173102886.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;th_IMG_20200406_173106140.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/summerhouse/th_IMG_20200406_173106140.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s surprising how much garden space you need to lay out all the parts and paint &amp;rsquo;em&amp;hellip;
also worth noting is that some of these do NOT fit through a standard 78&amp;quot;x30&amp;quot; door frame
so we had to carry them over the garage flat roof - you&amp;rsquo;ll need 4 people for that as
the heaviest panel weighs ~80kg.&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h2 id=&#34;prepare-the-ground-and-install-base&#34;&gt;Prepare the ground and install base&lt;/h2&gt;
&lt;figure class=&#34;float-left&#34;&gt;&lt;a href=&#34;th_IMG_20200406_173126607.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/summerhouse/th_IMG_20200406_173126607.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;The instructions are really big on having a level base, luckily for us the &lt;a href=&#34;https://www.ashbysoft.com/articles/theshed/&#34;&gt;previous
building here&lt;/a&gt; took care of much of that, and we were able
to re-use the wooden joists it stood on, after flipping them round 90 degrees so
they are orthogonal to the timbers making up the floor panels.
Also of note - the veranda floor is not connected to the other panels other than at
its ends so both it and the main floor panel need support along their join (you can&amp;rsquo;t
see it here but we have a 4th joist doing that bit).
In case you were wondering, the fork was left there as a position marker while
we flipped the panels over and back to screw them together underneath.&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h2 id=&#34;assemble&#34;&gt;Assemble!&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&#34;float-left&#34;&gt;&lt;a href=&#34;th_IMG_20200407_155552801_HDR.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/summerhouse/th_IMG_20200407_155552801_HDR.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;th_IMG_20200407_181039647_HDR.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/summerhouse/th_IMG_20200407_181039647_HDR.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Attach all the walls, starting with the shed structure to give stability, then work
along the back across the other end and the front, using a spirit level to check
your work as you go and adjust before screwing it all down to the floor. Nice.&lt;/p&gt;
&lt;p&gt;Be careful your floor isn&amp;rsquo;t distorted when making the last join, we had to readjust
on discovering the shed section was slightly tilted backwards!&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h2 id=&#34;roof-it-add-windows-fix-electrics-&#34;&gt;Roof it. Add windows, fix electrics :)&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&#34;float-left&#34;&gt;&lt;a href=&#34;th_IMG_20200412_155454450.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/summerhouse/th_IMG_20200412_155454450.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;th_IMG_20200412_155542215.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/summerhouse/th_IMG_20200412_155542215.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;..and we&amp;rsquo;re done! We took our time, doing a couple of hours a day so we took the
best part of a week to finish. It can be done in a day once the parts are painted
and dry.&lt;/p&gt;
&lt;p&gt;Welcome to the comfy outdoor living experience, yes that&amp;rsquo;s a BBQ patio to the left,
and yes we have power and network installed (I&amp;rsquo;m working from home in here real soon!)&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Downloads</title>
      <link>https://www.ashbysoft.com/articles/downloads/</link>
      <pubDate>Tue, 21 Jan 2020 21:31:20 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/downloads/</guid>
      <description>Useful things once..</description>
      <content:encoded>&lt;h2 id=&#34;stufff&#34;&gt;Stufff!&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://ashbysoft.com/download/ts.zip&#34;&gt;Windows terminal server client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ashbysoft.com/download/ScoutSDK.zip&#34;&gt;LEGO (tm) ScoutSDK documentation (zipped PDF)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ashbysoft.com/download/ScoutTools.zip&#34;&gt;LEGO (tm) ScoutSDK tools (zipped program set)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ashbysoft.com/download/loficc-sol10.tgz&#34;&gt;Solaris 10 encrypted loopback devices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../../wireplay%20stuff.zip&#34;&gt;Wireplay DOS clients 1.4, 1.5, 2.0.5&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Static sites are cool</title>
      <link>https://www.ashbysoft.com/posts/static-sites-are-cool/</link>
      <pubDate>Sat, 01 Jun 2019 19:50:13 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/static-sites-are-cool/</guid>
      <description>Static site are fun ;)</description>
      <content:encoded>&lt;p&gt;You get best of breed cyber security :)&lt;/p&gt;
&lt;p&gt;Deployment is always easy (ZIP anyone?)&lt;/p&gt;
&lt;p&gt;Content management is nicely orthogonal to deployment.&lt;/p&gt;
&lt;p&gt;Version control is whatever you choose - sanity is best.&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Blackhole DNS</title>
      <link>https://www.ashbysoft.com/posts/blackhole-dns/</link>
      <pubDate>Thu, 10 Aug 2017 22:16:10 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/blackhole-dns/</guid>
      <description>Over the last couple of months, Phil has been helping Joseph track down a credential leak problem using various network defence techniques.</description>
      <content:encoded>&lt;h2 id=&#34;tldr-gimme-the-scripts&#34;&gt;TL;DR gimme the scripts!&lt;/h2&gt;
&lt;p&gt;OK, chill&amp;hellip; they&amp;rsquo;re all here: &lt;a href=&#34;https://git.sr.ht/~phlash/sinkhole&#34;&gt;https://git.sr.ht/~phlash/sinkhole&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;err-why&#34;&gt;Err why?&lt;/h2&gt;
&lt;p&gt;Since Christmas &lt;a href=&#34;https://www.ashbysoft.com/articles/joseph/&#34;&gt;Joseph&lt;/a&gt; had noticed a number of
login attempts to Steam from weird locations, none successful due to
using 2 factor authentication (yay!), but concerning as it&amp;rsquo;s an
indicator of compromise. Steam passwords getting stolen / ex-filtrated
from somebody, are a cause of concern for the victim as they may have
other (more important) stuff going the same way.&lt;/p&gt;
&lt;p&gt;Early investigation, by changing the password then carefully sharing it
round the family members who have a need to know, did not turn up
anything obvious such as leakage occurring directly after a specific
individual used it on their device(s). So we thought we would try
setting a trap&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;dns-for-the-win&#34;&gt;DNS for the win&lt;/h2&gt;
&lt;p&gt;All network traffic, from inside our home to outside, will very likely
use a DNS lookup to locate external services before making a connection
or sending UDP packets (there are some exceptions of course, more on
these later). Since we already operate our own DNS server, for
split-brain purposes, we should be able to use this as a filter to pick
up any unexpected lookups, record the device that asked and follow up
with more detailed investigation. Simples. Almost.&lt;/p&gt;
&lt;p&gt;First we need to prevent any DNS requests bypassing our own server, so
that&amp;rsquo;s adding a firewall rule to the home router to block port 53
(TCP+UDP). Turns out this /also/ blocks all ICMP traffic, as an
undocumented side-effect, which was rather confusing for a while (thanks
TP-Link!)&lt;/p&gt;
&lt;p&gt;Next we need to enable logging on dnsmasq (our local DNS service). This
done we investigate the logs, and promptly get swamped by the thousands
and thousands of DNS requests in a day. We&amp;rsquo;ll need to add some
intelligence!&lt;/p&gt;
&lt;h2 id=&#34;blackhole-lists&#34;&gt;Blackhole lists&lt;/h2&gt;
&lt;p&gt;Network intelligence comes in the form of a curated list of &amp;lsquo;bad host
names&amp;rsquo; from github, courtesy of Steven Black
&lt;a href=&#34;https://github.com/StevenBlack/hosts&#34;&gt;https://github.com/StevenBlack/hosts&lt;/a&gt;. Adding this to dnsmasq as a
local hosts file prevents lookups going to the real world, instead
dnsmasq responds with whatever IP address we choose to put in the file,
so we choose 127.0.0.1 (there&amp;rsquo;s no place like home), and ::1 (IP6
equivalent as some evil scripts do IP6 lookups of CNAME records to
bypass DNS blackhole filters like this one).&lt;/p&gt;
&lt;p&gt;This turns out to be /really/ effective, no more adverts on devices,
much faster load times in many cases, but unfortunately in other cases,
no page loading at all. Bah. It seems a number of advert-supported sites
(comics mostly) will not load the content until the ad has arrived, or
sites rely on responses to their stats trackers (looking at you Azure!).
Some exclusions need to be applied to the block list to get everything
back up and running.&lt;/p&gt;
&lt;h2 id=&#34;automating-stuff&#34;&gt;Automating stuff&lt;/h2&gt;
&lt;p&gt;Black hole lists change on a daily basis, exclusions need applying and
reports need emitting: so I&amp;rsquo;ve written a couple of scripts to help
automate these parts (see github above).&lt;/p&gt;
&lt;h2 id=&#34;sinking-traffic&#34;&gt;Sinking traffic&lt;/h2&gt;
&lt;p&gt;Rather than &amp;lsquo;blackhole&amp;rsquo; DNS requests with a local IP(6) address,
&lt;a href=&#34;https://www.ashbysoft.com/articles/phlash/&#34;&gt;Phil&lt;/a&gt; thought it might be fun to operate a true
&amp;lsquo;sinkhole&amp;rsquo;, that is, an endpoint for potentially malevolent TCP/IP
traffic, so it can be captured and investigated. Given the nature of the
traffic, it is unwise to use a real TCP/IP stack in a live system (there
may be exploits arriving!), and it may be useful to avoid the kernel
overheads of processing traffic for real (memory mostly), so the fun
begins:&lt;/p&gt;
&lt;p&gt;Inspired by articles like this
&lt;a href=&#34;https://umbrella.cisco.com/blog/2014/02/28/dns-sinkhole/&#34;&gt;https://umbrella.cisco.com/blog/2014/02/28/dns-sinkhole/&lt;/a&gt;, and starting
with sample code like this &lt;a href=&#34;https://github.com/jedisct1/iptrap&#34;&gt;https://github.com/jedisct1/iptrap&lt;/a&gt;
Phil wrote a Python/Scapy based sinkhole program
(pysink.py in github repo). This worked, but Scapy is seriously slow and
it ground our quad core server to a halt! A second try, this time using
the raw socket API and writing all the protocol dissection required in
custom code (raw.py in github), works much better. To separate
potentially dangerous traffic from normal stuff, we added a USB Ethernet
adapter to the server (borrowed from the Wii!) but did not assign an
address, thus traffic is not passed up/down to IP or higher layers,
allowing the script to fake everything. We /did/ have to disable
promiscuous ARP responses (&lt;code&gt;/etc/sysctl.conf: net.ipv4.conf.all.arp_ignore = 1&lt;/code&gt;), otherwise the ARP layer would
respond to physical broadcast packets on the unaddressed interface.&lt;/p&gt;
&lt;p&gt;OK, we&amp;rsquo;re terminating dodgy traffic to the point where we have the first
payload packet arriving, which is usually enough to classify it, so how
to do that? Turns out there is an off-the-shelf solution, Suricata!
Suricata is a traffic analysis tool/IDS, designed to be fed from the
span or tap port of a physical switch, however it will work just as well
from the raw interface used to terminate the sinkhole :)&lt;/p&gt;
&lt;p&gt;What do we learn/see then? Well, there are several damn noisy bits of
kit on the home network (Windows PCs, Humax STB) and Dropbox and Chrome
do weird things (broadcasting to detect peers
&lt;a href=&#34;https://blogs.dropbox.com/tech/2015/10/inside-lan-sync/&#34;&gt;https://blogs.dropbox.com/tech/2015/10/inside-lan-sync/&lt;/a&gt;, sending fake
DNS requests
&lt;a href=&#34;https://isc.sans.edu/diary/Google+Chrome+and+%28weird%29+DNS+requests/10312&#34;&gt;https://isc.sans.edu/diary/Google+Chrome+and+%28weird%29+DNS+requests/10312&lt;/a&gt;).
Unfortunately we don&amp;rsquo;t see any Steam credentials flying about, nor do we
detect any known malware (yet).&lt;/p&gt;
&lt;h2 id=&#34;catching-the-problem&#34;&gt;Catching the problem&lt;/h2&gt;
&lt;p&gt;So after all that fun (and it was fun!), we are no nearer finding how
Steam passwords are leaking out. Joseph made yet another password change
late one evening, and didn&amp;rsquo;t pass it to anyone else as they were all
asleep. In the morning we discover it has leaked! This clearly indicates
Joe&amp;rsquo;s laptop as the source, so we dive into the DNS and packet logs to
try and find any evidence. After a couple of exciting
&lt;junk&gt;.cloudfront.net names turn up, only to be discarded as they used
by HP (they run cloudfront and dogfood their own CDN), we run out of
data in the time period involved. So we must conclude that the malware
is carefully avoiding DNS, most likely by operating it&amp;rsquo;s own
peer-to-peer network with bootstrap IP addresses. Much as we&amp;rsquo;d like to
attach Suricata to our outbound router to see all the traffic, it cannot
provide a span port (thanks again TP-Link). We also considered putting
Joe&amp;rsquo;s laptop through a real hub (I have kept an old 10M hub for this
purpose) and monitoring that for a while, but time was against us, so we
take a pragmatic route..&lt;/p&gt;
&lt;h2 id=&#34;resolution-by-fire&#34;&gt;Resolution (by fire!)&lt;/h2&gt;
&lt;p&gt;Given Joe needed his laptop cleaned up, and we are unlikely to catch the
malware in action over a short time period, we took the nuclear option:
boot into Linux from a live CD, image the on board drive (SSD) and parts
of the game store (HDD), then wipe the partitions and re-install Windows
from a known good ISO. While Windows was installing several years worth
of patches (at least there is a roll up pack now!), we scanned the
images using ClamAV to see if anything turned up. Sadly not, a few false
positives discovered by putting hash values through VirusTotal, and that
was it :(&lt;/p&gt;
&lt;h2 id=&#34;resolution-by-valve&#34;&gt;Resolution (by Valve)&lt;/h2&gt;
&lt;p&gt;Trying to be helpful, we contacted Valve support and explained the issue
to them, whereupon they asked &amp;ldquo;which account?&amp;rdquo;&amp;hellip; Turns out Joseph had
two, one active and one forgotton - guess which one had a known password in
a data breach? NB: Never use the same email address for &amp;gt;1 account!&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Bosch SMS Disassembly</title>
      <link>https://www.ashbysoft.com/posts/bosch-sms-disassembly/</link>
      <pubDate>Mon, 05 Dec 2016 20:54:30 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/bosch-sms-disassembly/</guid>
      <description>Phil] just experienced a dishwasher failure, it started tripping the house power and thus some disassembly was required.</description>
      <content:encoded>&lt;h2 id=&#34;trip&#34;&gt;Trip!&lt;/h2&gt;
&lt;p&gt;So last Wednesday the house power tripped out while I was away at just
before midnight, &lt;a href=&#34;https://www.ashbysoft.com/articles/joseph/&#34;&gt;Joseph&lt;/a&gt; did the right thing,
checking for burning things before pushing the trip back on. All
appeared well again. Chalk one up to weirdness.&lt;/p&gt;
&lt;p&gt;Then on Thursday it happened again, while I was present. We checked for
obvious failures again, pushed the trip back on and it popped straight
back out this time. Pulling all the plugs around the house got it to
stay on, so we worked through the list of &amp;rsquo;things we turned on about
midnight Weds and 10pm today&amp;rsquo; - the dishwasher was the only option.
Plug everything except the suspected kit back in - all good, problem
identified.&lt;/p&gt;
&lt;p&gt;Grab the multi-meter, measure the resistance between live and earth on
the plug pins, above 20 Mohm with the power off, below 1 Mohm with the
power button in. Time to pull it apart and find the short&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;disassemble&#34;&gt;Disassemble!&lt;/h2&gt;
&lt;p&gt;This is where it gets tricky as there are no disassembly instructions
for my Bosch SMS40T42UK/09 that I can find on the &amp;rsquo;net and no obvious
way in (like screws on the back on the lid). I&amp;rsquo;ll have to wing it,
possibly break stuff and &lt;strong&gt;document as I go&lt;/strong&gt;. If you are going to
follow along at home, you&amp;rsquo;ll need a Torx T20 and a large flat screwdriver.
Here&amp;rsquo;s the teardown photo stream :)&lt;/p&gt;
&lt;h3 id=&#34;the-lid&#34;&gt;the lid&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&#34;float-left&#34;&gt;&lt;img src=&#34;../../images/upload/IMG_20161203_131159.png&#34;&gt;
&lt;/figure&gt;

&lt;figure class=&#34;float-left&#34;&gt;&lt;img src=&#34;../../images/upload/IMG_20161203_131257.png&#34;&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Two catches, accessible through the rectangular apertures just
below the lid hold the whole lid on at the front, which then slides off
the back on hooks. I discovered these the hard way by breaking one
:(&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h3 id=&#34;the-side-panels&#34;&gt;the side panels&lt;/h3&gt;
&lt;figure class=&#34;float-left&#34;&gt;&lt;img src=&#34;../../images/upload/IMG_20161203_131507.png&#34;&gt;
&lt;/figure&gt;

&lt;p&gt;Once the lid was off, the rest was easy, a series of three
(different) screws hold each side panel on. All Torx T20 heads.
Once the screws are removed, the panels tilt outwards and drop
down from hooks underneath.&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h3 id=&#34;trouble-spotted&#34;&gt;trouble spotted&lt;/h3&gt;
&lt;figure class=&#34;float-left&#34;&gt;&lt;img src=&#34;../../images/upload/IMG_20161203_132138.png&#34;&gt;
&lt;/figure&gt;

&lt;p&gt;No need to remove any more panels, at this point I spotted
moisture where it shouldn&amp;rsquo;t be, above the electronics and in the base
tray. What I thought especially odd was that there was a sheet here to
deflect water away from the electrics at all, looks like a known
issue!&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h3 id=&#34;confirmation-of-short&#34;&gt;confirmation of short&lt;/h3&gt;
&lt;figure class=&#34;float-left&#34;&gt;&lt;img src=&#34;../../images/upload/IMG_20161203_133201.png&#34;&gt;
&lt;/figure&gt;

&lt;p&gt;Pulling the cover off the electrics revealed a wiring loom with
one obvious fat connector for the heater, which I disconnected and
measured for resistance to the earth / chassis: &amp;lt;1Mohm, confirmation
that the heater had lost integrity and making the whole machine
suspect.&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h3 id=&#34;abandon-hope&#34;&gt;abandon hope&lt;/h3&gt;
&lt;p&gt;At this point it looks like a known sealing / leakage issue around the
side of the wash tub has resulted in considerable water ingress to the
base tray and thus the heater (which practically rests on the tray),
destroying its insulation from the outside. Further disassembly and
possible replacement of the failed part might resurrect the machine, but
its over 3 years old, and the pipework on the other side (not shown)
looked pretty manky / furred up, so I abandoned further attempts at
fixing and bought a replacement washer. I figured it had depreciated at
under 2 pounds/week so didn&amp;rsquo;t owe me much!&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Family</title>
      <link>https://www.ashbysoft.com/articles/family/</link>
      <pubDate>Sun, 05 Jun 2016 00:59:56 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/family/</guid>
      <description>Here we all are!</description>
      <content:encoded>&lt;h1 id=&#34;here-we-all-are&#34;&gt;Here we all are&amp;hellip;&lt;/h1&gt;
&lt;p&gt;|| &lt;a href=&#34;https://www.ashbysoft.com/articles/phlash/&#34;&gt;Phil&lt;/a&gt; || &lt;a href=&#34;https://www.ashbysoft.com/articles/slash/&#34;&gt;Stuart&lt;/a&gt; || &lt;a href=&#34;#&#34;&gt;Angela&lt;/a&gt; || &lt;a href=&#34;https://www.ashbysoft.com/articles/martin/&#34;&gt;Martin&lt;/a&gt; || &lt;a href=&#34;https://www.ashbysoft.com/articles/robert/&#34;&gt;Robert&lt;/a&gt; || &lt;a href=&#34;https://www.ashbysoft.com/articles/joseph/&#34;&gt;Joseph&lt;/a&gt; || &lt;a href=&#34;https://www.ashbysoft.com/articles/thomas/&#34;&gt;Thomas&lt;/a&gt; || &lt;a href=&#34;https://www.ashbysoft.com/articles/helen/&#34;&gt;Helen&lt;/a&gt; || &lt;a href=&#34;https://www.ashbysoft.com/articles/simon/&#34;&gt;Simon&lt;/a&gt; ||&lt;/p&gt;
&lt;figure&gt;&lt;a href=&#34;../../images/upload/family_phils_house_big.jpg&#34;&gt;&lt;img src=&#34;../../images/upload/family_phils_house_big.jpg&#34; width=&#34;864&#34; height=&#34;576&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;..and for those who need to know what we looked like with hair&amp;hellip;
Phil &amp;amp; Stuart have a collection of
&lt;a href=&#34;https://www.ashbysoft.com/schooldays/&#34;&gt;Old School Photos&lt;/a&gt;
for your delectation and delight!&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Lenovo Battery Hack</title>
      <link>https://www.ashbysoft.com/posts/lenovo-battery-hack/</link>
      <pubDate>Fri, 03 Jun 2016 19:31:21 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/lenovo-battery-hack/</guid>
      <description>Yep, that&amp;rsquo;s actually a post title. it turns out that Phil&amp;rsquo;s laptop is fussy about the brand of battery you use, or to put another way: Lenovo like to lock users into their expensive batteries..right..</description>
      <content:encoded>&lt;h2 id=&#34;the-itch&#34;&gt;The Itch&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://www.ashbysoft.com/articles/phlash/&#34;&gt;Phil&lt;/a&gt; bought himself a replacement high-capacity
battery for his Lenovo T430 laptop recently. It was from a reputable
supplier in Germany, clearly listed the T430 as &amp;lsquo;compatible&amp;rsquo; on the
product description and was half the price of an official Lenovo
battery. What could possibly go wrong&amp;hellip;&lt;/p&gt;
&lt;p&gt;Upon insertion all looked well, the T430 worked fine, Ubuntu was able to
read the capacity and charge level (68%), but after an hour of use while
plugged into the AC power it didn&amp;rsquo;t seem to have charged up (still
68%). Hmmn. Rebooting displayed a warning message:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;The battery installed is not supported by this system and will not charge.
Please replace the battery with the correct Lenovo battery for this system.
Press the ESC key to continue.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;WTF!&lt;/p&gt;
&lt;p&gt;I contacted the seller who promptly offered a return of the item, and a
postage refund once I had a receipt for posting. So I repacked the
battery and popped down to the post office, who told me that Royal Mail
won&amp;rsquo;t handle a battery pack without it&amp;rsquo;s associated &amp;lsquo;device&amp;rsquo; aka my
laptop. Great, so back on the &amp;rsquo;net to find a delivery company who will
ship a battery to Germany. No one. Nowt. Zilch. At least, not for less
than the cost of the thing (£40)!&lt;/p&gt;
&lt;h2 id=&#34;research&#34;&gt;Research&lt;/h2&gt;
&lt;p&gt;Searching the &amp;rsquo;net for the displayed error message it becomes clear
that Lenovo laptops have a &amp;lsquo;Smart Battery&amp;rsquo;, and that from the T430
onwards, they implemented a challenge/response authentication mechanism
to lock users into buying Lenovo supplied parts, ostensibly to protect
systems from battery fires when &amp;lsquo;fast charging&amp;rsquo; the pack. Seems like
3rd party manufacturers are unable to replicate this behaviour properly,
and some (thanks INTENSILO) mis-label their batteries as compatible when
they are not.&lt;/p&gt;
&lt;p&gt;It also turns up the splendid work of zmatt
&lt;a href=&#34;http://www.zmatt.net/unlocking-my-lenovo-laptop-part-1/&#34;&gt;http://www.zmatt.net/unlocking-my-lenovo-laptop-part-1/&lt;/a&gt;, who had the
exact same problem on his X230, but chose to reverse engineer the
problem rather than return the battery - good man!&lt;/p&gt;
&lt;p&gt;A little later I come across more good work by Hamish Coleman
&lt;a href=&#34;https://github.com/hamishcoleman/thinkpad-ec&#34;&gt;https://github.com/hamishcoleman/thinkpad-ec&lt;/a&gt;, who has automated the
earlier work of zmatt and added other patches to support different
keyboards on multiple IBM/Lenovo laptops, including the original battery
fix for the X230.&lt;/p&gt;
&lt;h2 id=&#34;the-scratch&#34;&gt;The Scratch&lt;/h2&gt;
&lt;p&gt;Since I have no sane way to return my 3rd party battery, and prior work
exists which is /almost there/ to fix my problem I decide to go for it
(what&amp;rsquo;s the worst that can happen? I&amp;rsquo;ll brick my laptop):&lt;/p&gt;
&lt;p&gt;Step 1: Replace the original battery and check all is well (apart from
the rubbish capacity).&lt;/p&gt;
&lt;p&gt;Step 2: Carefully work through zmatt&amp;rsquo;s BIOS unpacking and editing
descriptions, double checking with Hamish&amp;rsquo;s Makefile and tooling, and
teaching myself to drive
&lt;a href=&#34;https://github.com/radare/radare2&#34;&gt;radare2&lt;/a&gt; (also awesome),
I arrive at a point of no return: I /think/ I have a correctly patched
BIOS file, there is only one way to test it: flash my laptop and hope
for the best&amp;hellip; I&amp;rsquo;m good: it starts up :)&lt;/p&gt;
&lt;p&gt;Step 3: Swap to the 3rd party battery and see if it charges.. yep!
Relief!&lt;/p&gt;
&lt;h2 id=&#34;the-payback&#34;&gt;The Payback&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s how open source works: I&amp;rsquo;ve got a new capability in front of me -
one that can fix battery charging issues on T430 laptops with a specific
BIOS version (2.57 if you&amp;rsquo;re interested). I have to do the decent thing
and work that into Hamish&amp;rsquo;s tools to give back to the community.&lt;/p&gt;
&lt;p&gt;[edit: pull request accepted] Go get it from Hamish&amp;rsquo;s Github above!&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Rivendell_Chroot</title>
      <link>https://www.ashbysoft.com/posts/rivendell_chroot/</link>
      <pubDate>Mon, 28 Dec 2015 10:20:27 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/rivendell_chroot/</guid>
      <description>&lt;a href=&#34;Phlash&#34; title=&#34;wikilink&#34;&gt;Phil&lt;/a&gt; got down to some Linux voodoo over the Christmas holiday, in order to run a slightly too old application suite (Rivendell Audio 1.7.2) on a supported distribution (Ubuntu 14.04 LTS), and without the aid of a package manager safety net (whoo!), it turns out &lt;a href=&#34;Rivendell_Chroot&#34; title=&#34;wikilink&#34;&gt;Chroot&lt;/a&gt; is a winner.</description>
      <content:encoded>&lt;p&gt;New holiday - new self-imposed challenge!&lt;/p&gt;
&lt;h2 id=&#34;context&#34;&gt;Context&lt;/h2&gt;
&lt;p&gt;My favourite radio station
&lt;a href=&#34;http://www.felixstoweradio.org.uk&#34; title=&#34;wikilink&#34;&gt;FXR&lt;/a&gt; use &lt;a href=&#34;http://www.rivendellaudio.org&#34; title=&#34;wikilink&#34;&gt;Rivendell
Audio&lt;/a&gt; as part of their play
out system, and have recently been donated an [HP
&lt;a href=&#34;TouchSmart&#34; title=&#34;wikilink&#34;&gt;TouchSmart&lt;/a&gt; 300-1025
PC](&lt;a href=&#34;http://h20564.www2.hp.com/hpsc/doc/public/display?docId=c01918320&#34;&gt;http://h20564.www2.hp.com/hpsc/doc/public/display?docId=c01918320&lt;/a&gt; &amp;ldquo;wikilink&amp;rdquo;)
to use in the public area, which I was asked to &#39;make work&#39; for audio
management duties and general Internet stuff..&lt;/p&gt;
&lt;h2 id=&#34;the-patient&#34;&gt;The Patient&lt;/h2&gt;
&lt;p&gt;Turns out that HP ship the !TouchSmart system with Windows 7 Home
Premium, loaded with lots of their own sloooow software (thanks to a
not-exactly-rapid hard drive and heavy use of multiple .NET versions),
then the owner / donor adds another boatload of cruft like Apple iTunes
/ Bonjour, ezRecover, several dodgy browser plugins (the usual suspects&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;adware, search bars, etc.), several browsers (hello Chrome + Google
services) AVG and Norton. The result is a machine that takes 10+ mins to
become usable from a cold start and frequently stalls as background
tasks hog the I/O bandwidth... not nice.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fix Attempt 1: Remove the crud, switch to Security Essentials for
anti-malware, prune the browsers back to Firefox only and see if it&#39;s
usable.&lt;/p&gt;
&lt;p&gt;Fix Result 1: I bricked it (almost) by uninstalling Bonjour, which seems
to completely hose the IP stack. After the uninstall, Windows event log
service fails to start and /lots/ of other stuff depends on the event
log - broken O/S :( System restore got things back working, then I
successfully cleaned out a lot of other junk with help from
!SysInternals tools (autoruns is fabulous!), and Process Hacker.
Unfortunately it wasn&#39;t much more usable in this state, and the Windows
version of Rivendell software is unable to play audio, which doesn&#39;t
make good use of the hardware capabilities. Rethink time.&lt;/p&gt;
&lt;p&gt;Fix Attempt 2: Ubuntu 14.04 LTS live CD, re-size NTFS partition(s) and
install basic GUI system, then add Rivendell packages. Simples.&lt;/p&gt;
&lt;p&gt;Fix Result 2: Ubuntu just worked, almost. Everything except the touch
screen was supported out of the box, including the !WiFi card and
camera, and as expected it was pretty quick, even after choosing the new
Ubuntu GNOME 3 desktop. Some additional rummaging on the &#39;net produced
a working touch screen too :)&lt;/p&gt;
&lt;h2 id=&#34;obsolete-app&#34;&gt;Obsolete app&lt;/h2&gt;
&lt;p&gt;Now I hit a problem - the Rivendell Audio version we use @ FXR is
officially obsolete (1.7.2 circa 2010) and I have lost the original
packages, not that they would install on 14.04 as the dependencies are
all wrong..&lt;/p&gt;
&lt;p&gt;I can of course query the existing installation(s) for file lists, and
collect all the binaries &amp;amp; libraries together. I can also grab the
dependency lists, but how to avoid collisions when I need an old library
to be used and I have a newer one in 14.04?&lt;/p&gt;
&lt;h2 id=&#34;collision-avoidance&#34;&gt;Collision Avoidance&lt;/h2&gt;
&lt;p&gt;My first thought was simply to drop the app and it&#39;s libraries (down to
libc) in a folder, hack the LD_LIBRARY_PATH and see if stuff
worked... kind of, except the app is 32bit, whereas my host O/S was
64bit, and many libraries depended on supporting config files that
collided with the host. Hmmn.&lt;/p&gt;
&lt;p&gt;Some Googling later, it became apparent that what I needed was a chroot
environment, something I tend to avoid as my previous experience with
such things has been fragility and continuous maintenance work (I prefer
to avoid that!). However, there are now tools available to make stuff
easier, in particular the fabulous debootstrap which can build a working
chroot version of any Debian or Ubuntu distribution, and schroot which
manages all the fragile bind mounts and authentication file copying
automatically as you enter/leave the chroot - nice :)&lt;/p&gt;
&lt;h2 id=&#34;the-chroot&#34;&gt;The Chroot&lt;/h2&gt;
&lt;p&gt;With a bit of
&lt;a href=&#34;https://wiki.ubuntu.com/DebootstrapChroot&#34; title=&#34;wikilink&#34;&gt;assistance&lt;/a&gt; I
built a chroot environment targetted at 32bit Lucid Lynx (10.04) to
match the FXR studio systems, I chose to install the minimum system,
which includes apt-get so I can add other components easily. I then
worked through the dependencies from the app, and installed appropriate
packages to satisfy these. So far so good, but I had no package for the
app itself..&lt;/p&gt;
&lt;h2 id=&#34;the-hack&#34;&gt;The Hack&lt;/h2&gt;
&lt;p&gt;Having satisfied the dependencies I then copied the remaining binaries
into place from the archive taken from the studio - did it work? Yep :)&lt;/p&gt;
&lt;p&gt;Unfortunately Rivendell Audio relies on a number of daemon processes,
and other GUI tools to operate, whereas a default chroot expects only
transient programs, so some additional work was required, in particular
creating a session via schroot to host the daemons, then re-attaching to
that session for each transient program. Much learning curve!&lt;/p&gt;
&lt;h2 id=&#34;pulse-audio&#34;&gt;Pulse Audio&lt;/h2&gt;
&lt;p&gt;Yes the daemon from hell :) However it&#39;s mostly useful for normal
programs, I just need to get a daemon running in a chroot to use it via
ALSA bindings.. sounds easy huh? Well it turns out that other folks have
had trouble before, the only reliable approach is to enable network
access and use it - other approaches that rely on DBus and shared memory
seem to be fragile. So enable network access, limit to localhost and
we&#39;re done :)&lt;/p&gt;
&lt;h2 id=&#34;session-on-demand&#34;&gt;Session on Demand&lt;/h2&gt;
&lt;p&gt;Last bit - when to run the schroot session and daemons? Given that we
depend on pulseaudio and that in turn runs per user login, I chose to
have startup scripts for each transient program check for a session and
create it.. then on logout it gets torn down. Job done.&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>FUNcube_2nd_Birthday</title>
      <link>https://www.ashbysoft.com/posts/funcube_2nd_birthday/</link>
      <pubDate>Sun, 22 Nov 2015 14:55:02 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/funcube_2nd_birthday/</guid>
      <description>Well blow me down if the ol&#39; cubesat is still working on it&#39;s 2nd Birthday. Cake was required.</description>
      <content:encoded>&lt;p&gt;In celebration of &lt;a href=&#34;FUNcube&#34; title=&#34;wikilink&#34;&gt;FUNcube&lt;/a&gt;-1
(&lt;a href=&#34;http://funcube.org.uk/&#34;&gt;http://funcube.org.uk/&lt;/a&gt;) having been operational for 2 years,
&lt;a href=&#34;Helen&#34; title=&#34;wikilink&#34;&gt;Helen&lt;/a&gt; made a cube cake, which we deployed :)&lt;/p&gt;
&lt;p&gt;&amp;quot;It&#39;s a cube cake!&amp;quot;&lt;/p&gt;
&lt;p&gt;That critical moment as the antenna are deployed..&lt;/p&gt;
&lt;p&gt;Success - contact established :)&lt;/p&gt;
&lt;p&gt;We just need to make a slight adjustment to the software...&lt;/p&gt;
&lt;p&gt;Happy 2nd Birthday &lt;a href=&#34;FUNcube&#34; title=&#34;wikilink&#34;&gt;FUNcube&lt;/a&gt;-1!&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>OBiLINE</title>
      <link>https://www.ashbysoft.com/posts/obiline/</link>
      <pubDate>Sun, 07 Jun 2015 21:00:25 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/obiline/</guid>
      <description>While looking for a usable cheap FXO port to connect the PSTN to his home server, &lt;a href=&#34;Phlash&#34; title=&#34;wikilink&#34;&gt;Phil&lt;/a&gt; came across the OBIHAI product line, and bought a couple of toys to play with: an &lt;a href=&#34;http://www.obihai.com/docs/OBi110DS.pdf&#34; title=&#34;wikilink&#34;&gt;OBIHAI110&lt;/a&gt; voice service bridge, which will do pretty much what&#39;s required without the server attached, and an &lt;a href=&#34;http://www.obihai.com/obiline&#34; title=&#34;wikilink&#34;&gt;ObiLINE&lt;/a&gt; USB FXO adapter, which is &lt;a href=&#34;OBiLINE&#34; title=&#34;wikilink&#34;&gt;being reverse engineered&lt;/a&gt; for fun :)</description>
      <content:encoded>&lt;ol&gt;
&lt;li&gt;
&lt;ol&gt;
&lt;li&gt;page was renamed from ObiLINE&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;obiline-usb-fxo-adapter&#34;&gt;OBiLINE USB FXO Adapter&lt;/h1&gt;
&lt;p&gt;Those lovely folks at OBIHAI have recently produced the cheapest USB FXO
device I&#39;ve seen: &lt;a href=&#34;http://www.obihai.com/obiline&#34; title=&#34;wikilink&#34;&gt;OBiLINE&lt;/a&gt;,
available from Amazon all over the world, but thus far nobody seems to
have taken the lid off - until now :)&lt;/p&gt;
&lt;p&gt;||&amp;lt;tablestyle=&amp;quot;float:right;&amp;quot; style=&amp;quot;padding: 1em;&amp;quot;:&amp;gt;||&lt;/p&gt;
&lt;h2 id=&#34;whats-in-the-case&#34;&gt;What&#39;s in the case?&lt;/h2&gt;
&lt;p&gt;Not a lot it turns out (kind of expected since it&#39;s £25.00 inc. VAT!).&lt;/p&gt;
&lt;h3 id=&#34;parts&#34;&gt;Parts&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;NuvoTon&#34; title=&#34;wikilink&#34;&gt;NuvoTon&lt;/a&gt; Nano120LD, ARM-Coretex M0 Micro + USB
&lt;a href=&#34;http://www.keil.com/dd/docs/datashts/nuvoton/nano1xx/trm_nano100%28b%29_series_en_rev1.06.pdf&#34; title=&#34;wikilink&#34;&gt;Datasheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;SiLabs&#34; title=&#34;wikilink&#34;&gt;SiLabs&lt;/a&gt; 32178-FM1, Telephone interface chipset
&lt;a href=&#34;http://media.digikey.com/pdf/Data%20Sheets/Silicon%20Laboratories%20PDFs/Si3217x_291x_Brief.pdf&#34; title=&#34;wikilink&#34;&gt;Datasheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;SiLabs&#34; title=&#34;wikilink&#34;&gt;SiLabs&lt;/a&gt; 32919-A-FS, paired with above to provide
FXO parts&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;what-does-it-look-like-on-usb&#34;&gt;What does it look like on USB&lt;/h2&gt;
&lt;p&gt;Here&#39;s the interesting part: the device works in conjunction with
OBIHAI&#39;s closed-source VoIP gateway products (e.g. Obi202). One guy
plugged one into his Windows PC
&lt;a href=&#34;http://www.obitalk.com/forum/index.php?topic=7236.0&#34;&gt;http://www.obitalk.com/forum/index.php?topic=7236.0&lt;/a&gt;, but didn&#39;t get
much info.&lt;/p&gt;
&lt;p&gt;I&#39;ve just bunged mine into my Ubuntu lappy, and it turns up as a sound
card (S16_LE, 8kHz fixed), no other control interfaces are apparent, so
I don&#39;t know how it&#39;s used to seize the line (perhaps by just opening
the device?) or how ring detect works. I will attach the other end to a
PSTN line next and see what happens!&lt;/p&gt;
&lt;h3 id=&#34;can-i-make-it-work&#34;&gt;Can I make it work?&lt;/h3&gt;
&lt;p&gt;Short answer: no :(&lt;/p&gt;
&lt;p&gt;I&#39;ve tried playing with declared audio controls via alsamixer - nothing
much happens. Opening the device for record or playback results in a
stalled device.. there is something that needs to happen to wake this
thing up.&lt;/p&gt;
&lt;p&gt;lsusb dump:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@lenny:~# lsusb -vs 3:5

Bus 003 Device 005: ID 4f42:6901  
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0         8
  idVendor           0x4f42 
  idProduct          0x6901 
  bcdDevice            1.00
  iManufacturer           1 Obihai
  iProduct                2 USB Audio Device
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength          192
    bNumInterfaces          3
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    [[MaxPower]]               64mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      1 Control Device
      bInterfaceProtocol      0 
      iInterface              0 
      [[AudioControl]] Interface Descriptor:
        bLength                10
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength           70
        bInCollection           2
        baInterfaceNr( 0)       1
        baInterfaceNr( 1)       2
      [[AudioControl]] Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        bTerminalID             1
        wTerminalType      0x0101 USB Streaming
        bAssocTerminal          0
        bNrChannels             1
        wChannelConfig     0x0001
          Left Front (L)
        iChannelNames           0 
        iTerminal               0 
      [[AudioControl]] Interface Descriptor:
        bLength                 8
        bDescriptorType        36
        bDescriptorSubtype      6 (FEATURE_UNIT)
        bUnitID                 5
        bSourceID               4
        bControlSize            1
        bmaControls( 0)      0x03
          Mute Control
          Volume Control
        iFeature                0 
      [[AudioControl]] Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (OUTPUT_TERMINAL)
        bTerminalID             2
        wTerminalType      0x0101 USB Streaming
        bAssocTerminal          0
        bSourceID               5
        iTerminal               0 
      [[AudioControl]] Interface Descriptor:
        bLength                10
        bDescriptorType        36
        bDescriptorSubtype      6 (FEATURE_UNIT)
        bUnitID                 6
        bSourceID               1
        bControlSize            1
        bmaControls( 0)      0x01
          Mute Control
        bmaControls( 1)      0x02
          Volume Control
        bmaControls( 2)      0x02
          Volume Control
        iFeature                0 
      [[AudioControl]] Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (OUTPUT_TERMINAL)
        bTerminalID             3
        wTerminalType      0x0301 Speaker
        bAssocTerminal          0
        bSourceID               6
        iTerminal               0 
      [[AudioControl]] Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        bTerminalID             4
        wTerminalType      0x0201 Microphone
        bAssocTerminal          0
        bNrChannels             1
        wChannelConfig     0x0001
          Left Front (L)
        iChannelNames           0 
        iTerminal               0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       1
      bNumEndpoints           1
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
      [[AudioStreaming]] Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink           2
        bDelay                  1 frames
        wFormatTag              1 PCM
      [[AudioStreaming]] Interface Descriptor:
        bLength                11
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bNrChannels             1
        bSubframeSize           2
        bBitResolution         16
        bSamFreqType            1 Discrete
        tSamFreq[ 0]         8000
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            5
          Transfer Type            Isochronous
          Synch Type               Asynchronous
          Usage Type               Data
        wMaxPacketSize     0x0100  1x 256 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
        [[AudioControl]] Endpoint Descriptor:
          bLength                 7
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x00
          bLockDelayUnits         0 Undefined
          wLockDelay              0 Undefined
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       1
      bNumEndpoints           1
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
      [[AudioStreaming]] Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink           1
        bDelay                  1 frames
        wFormatTag              1 PCM
      [[AudioStreaming]] Interface Descriptor:
        bLength                11
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bNrChannels             1
        bSubframeSize           2
        bBitResolution         16
        bSamFreqType            1 Discrete
        tSamFreq[ 0]         8000
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes           13
          Transfer Type            Isochronous
          Synch Type               Synchronous
          Usage Type               Data
        wMaxPacketSize     0x0100  1x 256 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
        [[AudioControl]] Endpoint Descriptor:
          bLength                 7
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x80
            [[MaxPacketsOnly]]
          bLockDelayUnits         0 Undefined
          wLockDelay              0 Undefined
Device Status:     0x0000
  (Bus Powered)
root@lenny:~#
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;hi-res-photos&#34;&gt;Hi-res photos&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;attachment:OBiLINE2.jpg&#34; title=&#34;wikilink&#34;&gt;&lt;/a&gt;
&lt;a href=&#34;attachment:OBiLINE3.jpg&#34; title=&#34;wikilink&#34;&gt;&lt;/a&gt;&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>ScopeHacking</title>
      <link>https://www.ashbysoft.com/posts/scopehacking/</link>
      <pubDate>Fri, 18 Apr 2014 18:50:26 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/scopehacking/</guid>
      <description>Yup - Easter holidays allow one time to play with one&#39;s own toys, so just for the fun (and practice) I &lt;a href=&#34;ScopeHacking&#34; title=&#34;wikilink&#34;&gt;reverse engineered the protocol&lt;/a&gt; on an old infra-red keyboard (it came with a &lt;a href=&#34;http://www.radioandtelly.co.uk/iplayer.html&#34; title=&#34;wikilink&#34;&gt;Netgem set top box&lt;/a&gt; many years ago).</description>
      <content:encoded>&lt;h2 id=&#34;have-dso-will-hack-&#34;&gt;Have DSO, Will Hack :)&lt;/h2&gt;
&lt;p&gt;I&#39;ve got a lot of stuff in the house (that I should probably chuck, but
hey), including a &lt;a href=&#34;http://www.radioandtelly.co.uk/iplayer.html&#34; title=&#34;wikilink&#34;&gt;Netgem
iPlayer&lt;/a&gt; and
it&#39;s associated infra-red full qwerty keyboard. The iPlayer unit is
pretty much useless now, but the keyboard might be fun as a remote for
an under-TV PC, I just need to know the protocol to program
&lt;a href=&#34;http://www.lirc.org/&#34; title=&#34;wikilink&#34;&gt;LIRC&lt;/a&gt;..&lt;/p&gt;
&lt;p&gt;So how to decode an IR protocol? Well, I&#39;ve got a &lt;a href=&#34;http://www.rapidonline.com/Test-Measurement/Owon-Oscilloscope-25MHz-2-Channel-Colour-85-2792&#34; title=&#34;wikilink&#34;&gt;Digital Storage
Oscilloscope&lt;/a&gt;,
and found a photo transistor in the box of bits - hooking them up with a
couple of resistors for bias and a 5v supply (USB cable) gets me an IR
receiver:&lt;/p&gt;
&lt;p&gt;This happened to be pointing at my dimmable lights when connected, which
showed me a nice 100Hz hum :-)&lt;/p&gt;
&lt;p&gt;A bit of fiddling with the controls and I can now detect the signal
coming from the keyboard, a pulse train of IR carrier bursts at 38kHz
(the usual), with variable width pulses in blocks repeated at intervals
while I hold a key down.&lt;/p&gt;
&lt;h2 id=&#34;part-1-pulse-timing&#34;&gt;Part 1: Pulse timing&lt;/h2&gt;
&lt;p&gt;I adjusted the &#39;scope such that one pulse train block fits into the
screen width, set the trigger point at the left edge of the screen and
selected single capture mode, then hit &#39;Space&#39; and grabbed the pulse
train into storage (all timing in milliseconds):&lt;/p&gt;
&lt;p&gt;|| on || 2.4 || || 0.8 || || 1.6 || || 0.8 || || 3.2
|| || 2.4 || || off|| || 0.8 || || 0.8 || || 0.8
|| || 0.8 || || 2.4 || ||&lt;/p&gt;
&lt;p&gt;Hmmn. Looks like everything is a multiple of 0.8 msecs - so let&#39;s
convert those timings to bits and see if it looks like a serial
protocol:&lt;/p&gt;
&lt;p&gt;|| Space || 111010110101111000111 || 21 bits? Not sure, let&#39;s try
another key || || Menu || 11101011010100100111 || 20 bits? Less
sure now, try another one.. || || News || 11101011010111001111
|| 20 bits again. First 11/12 are the same.. ||&lt;/p&gt;
&lt;p&gt;If this was using partiy and start/stop bits (sensible given the
unreliable IR carrier), there should be 11 bits/byte, which fits in with
the first 11/12 bits being the same (address byte followed by keycode
perhaps?). Let&#39;s divide the bits up, include a final stop bit (0) and
check if a parity bit works:&lt;/p&gt;
&lt;p&gt;|| Space || 1(S) 11010110(V) 1(P) 0(T) / 1(S) 11100011(V) 1(P) 0(T)
|| Looks like even parity.. || || Menu || 1(S) 11010110(V) 1(P)
0(T) / 1(S) 00100111(V) 0(P) 0(T) || Checks out, still even.. ||
|| News || 1(S) 11010110(V) 1(P) 0(T) / 1(S) 11001111(V) 0(P) 0(T)
|| Could be right here :) || || LShift|| 1(S) 11010110(V) 1(P)
0(T) / 1(S) 01110011(V) 1(P) 0(T) || Yep - rekon I&#39;m right! ||&lt;/p&gt;
&lt;p&gt;So it looks to be 1200 baud serial data with even parity (aka 8E1), two
bytes per pulse train block.&lt;/p&gt;
&lt;h2 id=&#34;part-2-block-repeats--press--release-bit&#34;&gt;Part 2: Block repeats &amp;amp; press / release bit&lt;/h2&gt;
&lt;p&gt;Are blocks repeated to provide resilience? Or just while a key is held
down?&lt;/p&gt;
&lt;p&gt;Re-adjusting the &#39;scope, I can see that holding a key down produces a
pulse train block every 100 msecs, by capturing two blocks and zooming
in (gotta love &lt;a href=&#34;DSOs&#34; title=&#34;wikilink&#34;&gt;DSOs&lt;/a&gt;!), I can see that the same pulse
train is emitted while a key is held, this gives me a nice key-repeat
feature if I want one.&lt;/p&gt;
&lt;p&gt;What about if I just tap a key?&lt;/p&gt;
&lt;p&gt;I can just about hit and release a key in &amp;lt;100 msecs, the resulting
blocks have a short spacing between the first two blocks, then 100 msecs
to the third block, then nothing. Zooming in again shows that the second
and third blocks are the same, but are different from the first, like
this (omitting start/stop/parity bits):&lt;/p&gt;
&lt;p&gt;|| Menu 1st Block || 11010110 / 00100111 || || Menu 2nd Block
|| 11010100 / 00100111 ||&lt;/p&gt;
&lt;p&gt;Ah-ha! We&#39;ve found the press / release bit in the first byte, and we
also know that release blocks are always sent twice.&lt;/p&gt;
&lt;p&gt;Protocol - &lt;em&gt;&lt;strong&gt;hacked&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>StackGrabbing</title>
      <link>https://www.ashbysoft.com/posts/stackgrabbing/</link>
      <pubDate>Fri, 21 Feb 2014 08:45:09 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/stackgrabbing/</guid>
      <description>Ok, I&#39;m sorry about the subject line, just how &lt;a href=&#34;Phlash&#34; title=&#34;wikilink&#34;&gt;Phil&#39;s&lt;/a&gt; brain works I&#39;m afraid. I&#39;ve been amusing myself recently by writing a &lt;a href=&#34;StackGrabbing&#34; title=&#34;wikilink&#34;&gt;memory allocation tracer&lt;/a&gt; in VC++ to track down some pesky memory leaks in a large app.</description>
      <content:encoded>&lt;h1 id=&#34;grabbing-the-stack-for-fun--profit&#34;&gt;Grabbing the Stack for Fun &amp;amp; Profit&lt;/h1&gt;
&lt;p&gt;So I&#39;m at a work, trying to track down some memory leaks in a
long-running VC++ application (actually a COM object DLL out the back of
a .NET web service - you don&#39;t need to know that bit). No problem,
I&#39;ll use the Microsoft C Run-Time library memory debugging features.. a
quick read / web search later, I have the necessary incantation in a
common code header:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; #define _CRTDBG_MAP_ALLOC
 #include &amp;lt;stdlib.h&amp;gt;
 #include &amp;lt;crtdbg.h&amp;gt;
 #define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;..all goes well, the application terminates and I get a dump file of
leaked memory blocks: 34MB of text, with very few file and line numbers.
Of those entries that do provide file and line numbers, they&#39;re all
just a few places, buffer management classes that could be called from
anywhere. Back to square one.&lt;/p&gt;
&lt;p&gt;OK, so I need more context, in particular I need to see the stack when
those allocations are made. No problem, I can use a &lt;a href=&#34;http://msdn.microsoft.com/en-us/library/z2zscsc2.aspx&#34; title=&#34;wikilink&#34;&gt;debug memory
allocation hook
function&lt;/a&gt;,
take a stack back trace for each alloc, remove it for each free then
dump what&#39;s left at the end.&lt;/p&gt;
&lt;h2 id=&#34;attempt-1-stackwalkerstackwalker-wikilink&#34;&gt;Attempt 1: &lt;a href=&#34;StackWalker&#34; title=&#34;wikilink&#34;&gt;StackWalker&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So - how to grab a stack back trace? I first came across some excellent
but rather involved code from Jochen Kalmbach:
&lt;a href=&#34;http://stackwalker.codeplex.com/&#34;&gt;http://stackwalker.codeplex.com/&lt;/a&gt; which he wrote primarily for printing
a crash dump stack trace with lots of extra info.&lt;/p&gt;
&lt;p&gt;This turns out to be pretty easy to use, but rather slow, mostly because
it does symbol lookups while walking the stack. I&#39;m seeing ~20 million
allocations during a test run, and !StackWalker is tracing at about
100/sec, so a test run would take 200k secs or about 2.3 days. Try
again.&lt;/p&gt;
&lt;h2 id=&#34;attempt-2-capturestackbacktracecapturestackbacktrace-wikilink&#34;&gt;Attempt 2: &lt;a href=&#34;CaptureStackBackTrace&#34; title=&#34;wikilink&#34;&gt;CaptureStackBackTrace&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My Google fu improved after attempt 1, and I found
&lt;a href=&#34;http://msdn.microsoft.com/en-us/library/windows/desktop/bb204633%28v=vs.85%29.aspx&#34; title=&#34;wikilink&#34;&gt;CaptureStackBackTrace&lt;/a&gt;,
a kernel/RTL function that does exactly what it says on the tin -
fabulous and fast, no symbol lookups or callbacks to read process
memory, using this made no discernible difference to memory allocation
speed - winner!&lt;/p&gt;
&lt;h2 id=&#34;crt-oops&#34;&gt;CRT Oops&lt;/h2&gt;
&lt;p&gt;So now I can run a test - result: ~20 million allocations, followed by
zero frees. Nothing. Not one. That can&#39;t be right can it?&lt;/p&gt;
&lt;p&gt;Back to the debugger to trace what&#39;s going on in the memory allocation
hook function where I&#39;m supposed to be matching allocation requests
with free&#39;s and removing those from the list to print out. Turns out
that when Microsoft wrote the debug memory library they chose to not
provide the hook function with any useful information when callers free
memory blocks, so I&#39;m unable to associate free&#39;s with allocs. Genius.
A little more digging and some bodgery results in me being able to
extract the allocation request ID and record memory leakage with stack
traces like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#define _CRTDBG_MAP_ALLOC
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;crtdbg.h&amp;gt;
#include &amp;lt;DbgHelp.h&amp;gt;

// stolen from dbgint.h - because M$ in their wisdom don&#39;t provide matching request serial numbers between alloc/free hook calls. Sheesh.
#define nNoMansLandSize 4
typedef struct _CrtMemBlockHeader
{
        struct _CrtMemBlockHeader * pBlockHeaderNext;
        struct _CrtMemBlockHeader * pBlockHeaderPrev;
        char *                      szFileName;
        int                         nLine;
#ifdef _WIN64
        /* These items are reversed on Win64 to eliminate gaps in the struct
         * and ensure that sizeof(struct)%16 == 0, so 16-byte alignment is
         * maintained in the debug heap.
         */
        int                         nBlockUse;
        size_t                      nDataSize;
#else  /* _WIN64 */
        size_t                      nDataSize;
        int                         nBlockUse;
#endif  /* _WIN64 */
        long                        lRequest;
        unsigned char               gap[nNoMansLandSize];
        /* followed by:
         *  unsigned char           data[nDataSize];
         *  unsigned char           anotherGap[nNoMansLandSize];
         */
} _CrtMemBlockHeader;
#define pbData(pblock) ((unsigned char *)((_CrtMemBlockHeader *)pblock + 1))
#define pHdr(pbData) (((_CrtMemBlockHeader *)pbData)-1)

// require dbghelp.lib for SymXX() calls
#pragma comment(lib, &amp;quot;dbghelp.lib&amp;quot;)

...

// collect stack traces during allocation, remove when free&#39;d
static int maxreq=20000000;
static ULONG skipframes=5;
static ULONG maxframes=10;
typedef struct {
    PVOID trc[10];
    ULONG len;
    ULONG cnt;
} stack_t;
static stack_t stacks[20000000];

static volatile BOOL inWalk = FALSE;
static long acount = 0;
int __cdecl allochook(int type, void *usr, size_t size, int block, long req, const unsigned char *file, int line) {
    wchar_t msg[80];
    if (inWalk) // ignore recursive requests
        return TRUE;
    inWalk = TRUE;
    acount++;
    if (acount%10000==0) {
        wsprintf(msg, L&amp;quot;%ld\n&amp;quot;, acount);
        OutputDebugString(msg);
    }
    if (req&amp;lt;maxreq) {
        DWORD hash;
        switch (type) {
        case _HOOK_ALLOC:
            // insert into map - alert collisions
            if (0==stacks[req].len)
                stacks[req].cnt=1;
            else
                stacks[req].cnt++;
            stacks[req].len=CaptureStackBackTrace(skipframes, maxframes, stacks[req].trc, &amp;amp;hash);
            if (stacks[req].len&amp;gt;maxframes) {
                DebugBreak();
            }
            break;
        case _HOOK_REALLOC:
            // update/insert into map - may collide
            stacks[req].len=CaptureStackBackTrace(skipframes, maxframes, stacks[req].trc, &amp;amp;hash);
            if (stacks[req].len&amp;gt;maxframes) {
                DebugBreak();
            }
            break;
        case _HOOK_FREE:
            // AWOOGA! AWOOGA!! HIDEOUS BODGE ALERT!!! Recover request ID from CRT debug memory header because
            // Microsloth DO NOT PROVIDE IT IN THE HOOK FUNCTION CALL. Numpties.
            if (usr==NULL) {
                OutputDebugString(L&amp;quot;NULL [[UserData]] in free hook\n&amp;quot;);
                DebugBreak();
            }
            req = pHdr(usr)-&amp;gt;lRequest;
            // remove from map - alert missing entries
            if (0!=stacks[req].len) {
                stacks[req].len=0;
            } else {
                wsprintf(msg, L&amp;quot;free without alloc ID: %d\n&amp;quot;, req);
                OutputDebugString(msg);
            }
            break;
        }
    } else {
        OutputDebugString(L&amp;quot;Oops: out of request array!&amp;quot;);
        DebugBreak();
    }
    inWalk = FALSE;
    return TRUE;
}
static void dumpstacks(_HFILE hFile) {
    char buf[4096];
    DWORD nw;
    int cnt=0;
    HANDLE hProc = [[GetCurrentProcess]]();
    wcstombs(buf, path, wcslen(path));
    SymInitialize(hProc, buf, TRUE);
    wsprintfA(buf, &amp;quot;------ stacks\r\n&amp;quot;);
    WriteFile(hFile, buf, strlen(buf), &amp;amp;nw, NULL);
    for (int req=0; req&amp;lt;maxreq; req++) {
        if (0!=stacks[req].len) {
            int o;
            wsprintfA(buf, &amp;quot;{%d/%d}: &amp;quot;, req, stacks[req].cnt);
            o=strlen(buf);
            for (USHORT stk=0; stk&amp;lt;stacks[req].len &amp;amp;&amp;amp; o&amp;lt;4080; stk++) {
                char tmp[256];
                char tmp2[sizeof(SYMBOL_INFO)+256] = {0};
                SYMBOL_INFO *pSym = (SYMBOL_INFO *)tmp2;
                pSym-&amp;gt;MaxNameLen = 255;
                pSym-&amp;gt;SizeOfStruct = sizeof(SYMBOL_INFO);
                if (SymFromAddr(hProc, (DWORD64)stacks[req].trc[stk], 0, pSym))
                    wsprintfA(tmp, &amp;quot;%s (%08x),&amp;quot;, pSym-&amp;gt;Name, pSym-&amp;gt;Address);
                else
                    wsprintfA(tmp, &amp;quot;%08x,&amp;quot;, stacks[req].trc[stk]);
                strcpy(buf+o, tmp);
                o+=strlen(tmp);
            }
            WriteFile(hFile, buf, strlen(buf), &amp;amp;nw, NULL);
            WriteFile(hFile, &amp;quot;\r\n&amp;quot;, 2, &amp;amp;nw, NULL);
            ++cnt;
        }
        if (req%1000==0) {
            wsprintfA(buf, &amp;quot;%d/%d\n&amp;quot;, cnt, req);
            OutputDebugStringA(buf);
        }
    }
}

...

int main() {
...
    memset(&amp;amp;stacks, 0, maxreq*sizeof(stack_t));
    _CRT_ALLOC_HOOK oldHook = _CrtSetAllocHook(allochook);
...
    hFile = [[CreateFile]](L&amp;quot;leaks.txt&amp;quot;, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
    _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
    _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
    _CrtSetReportFile(_CRT_WARN, hFile);
    _CrtSetReportFile(_CRT_ERROR, hFile);
    _CrtSetReportFile(_CRT_ASSERT, hFile);
    OutputDebugString(L&amp;quot;Dumping stacks\n&amp;quot;);
    dumpstacks(hFile);
    OutputDebugString(L&amp;quot;Dumping memory leaks\n&amp;quot;);
    _CrtDumpMemoryLeaks();
    CloseHandle(hFile);
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;..fun eh? But this at least works (whilst eating ~1GB of RAM for the
tracing buffer!).&lt;/p&gt;
&lt;h2 id=&#34;leakage-found&#34;&gt;Leakage Found!&lt;/h2&gt;
&lt;p&gt;After all that entertainment, I finally had ~180k memory blocks that
weren&#39;t free&#39;d on program termination, this time with stack traces,
all with a common ancestor method - victory is mine! I won&#39;t bore you
with the details of the bug (besides it&#39;s proprietary code from work),
but I will say that ATL COM objects are ugly voodoo, and rolling your
own makes stuff much clearer (and not dependant on the paid for version
of Visual Studio).&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Projects</title>
      <link>https://www.ashbysoft.com/articles/projects/</link>
      <pubDate>Sat, 21 Sep 2013 22:25:15 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/projects/</guid>
      <description>Things we&amp;rsquo;ve done outside work and hobbies</description>
      <content:encoded>&lt;h3 id=&#34;illuminated-wesley-guitar&#34;&gt;Illuminated Wesley Guitar&lt;/h3&gt;
&lt;p&gt;[&lt;figure class=&#34;float-left&#34;&gt;&lt;img src=&#34;../illuminatedguitar/blue.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;
&lt;/figure&gt;
]
(/articles/illuminatedguitar/)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.ashbysoft.com/articles/robert/&#34;&gt;Bob&lt;/a&gt; decided to spend his 16th birthday money on a
new axe, but not just any axe - oh no - a clear acrylic Wesley Strat
copy (PE200wh). Of course a perfectly clear acrylic block just begs to
be lit up from the inside. Oh yes it does :)&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;&gt; &lt;hr/&gt; &lt;/div&gt;
&lt;h3 id=&#34;pond&#34;&gt;Pond&lt;/h3&gt;
&lt;p&gt;[&lt;figure class=&#34;float-left&#34;&gt;&lt;img src=&#34;../thepond/pond1.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;
&lt;/figure&gt;
]
(/articles/thepond/)&lt;/p&gt;
&lt;p&gt;In an effort to move our pets outside, to encourage more wildlife in the
garden and to grow more interesting plants, Angela, Phil and the family
have built a pond. Bring on the herons!&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;&gt; &lt;hr/&gt; &lt;/div&gt;
&lt;h3 id=&#34;shed&#34;&gt;Shed&lt;/h3&gt;
&lt;p&gt;[&lt;figure class=&#34;float-left&#34;&gt;&lt;img src=&#34;../theshed/outside1.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;
&lt;/figure&gt;
]
(/articles/theshed/)&lt;/p&gt;
&lt;p&gt;Constructed between Oct/Dec 2005 to replace the mouldy old shed in Phil
and Angela&amp;rsquo;s back garden, &amp;ldquo;the shed&amp;rdquo; is intended as a recording
studio / drum practice room and general bolt hole :) Getting the panels
into the garden was entertaining&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;&gt; &lt;hr/&gt; &lt;/div&gt;
&lt;p&gt;[&lt;figure class=&#34;float-left&#34;&gt;&lt;img src=&#34;https://ashbysoft.com/maps/th_office1.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;
&lt;/figure&gt;
]
(&lt;a href=&#34;https://ashbysoft.com/maps/Roberts_Map_Page.html&#34;&gt;https://ashbysoft.com/maps/Roberts_Map_Page.html&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.ashbysoft.com/articles/robert/&#34;&gt;Bob&lt;/a&gt; has been busying himself with the latest
&lt;a href=&#34;http://www.valvesoftware.com/&#34; title=&#34;wikilink&#34;&gt;Valve Software&lt;/a&gt; Hammer editor,
producing several new maps for the Counter-Strike:Condition Zero game..&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;&gt; &lt;hr/&gt; &lt;/div&gt;
&lt;p&gt;[&lt;figure class=&#34;float-left&#34;&gt;&lt;img src=&#34;../theconservatory/done.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;
&lt;/figure&gt;
]
(/articles/theconservatory/)&lt;/p&gt;
&lt;p&gt;Built between April and November 2003 (but not finished until 2005..),
this was Phil&amp;rsquo;s first serious building project, and it was quite a
challenge!&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;&gt; &lt;hr/&gt; &lt;/div&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Slash</title>
      <link>https://www.ashbysoft.com/articles/slash/</link>
      <pubDate>Mon, 10 Jun 2013 23:51:29 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/slash/</guid>
      <description>all about Stu</description>
      <content:encoded>&lt;h3 id=&#34;all-about-stuart&#34;&gt;All About Stuart&lt;/h3&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;img src=&#34;../../images/upload/stuart2.jpg&#34;&gt;
&lt;/figure&gt;

&lt;p&gt;Hi ! I&amp;rsquo;m the guy on the right. If I look like my brother that&amp;rsquo;s
because we&amp;rsquo;re &lt;em&gt;Twins&lt;/em&gt;. If you haven&amp;rsquo;t worked it our already, I&amp;rsquo;m an
IT geek into badminton, music, coding, games, hacking, fast cars and
occasionally skiing and sailing. Strictly on holiday only of course..&lt;/p&gt;
&lt;p&gt;In police terminology I&amp;rsquo;m 1m70, 80Kg, hazel eyes, short/receeding hair,
glasses. Definite axe-murderer material. [That&#39;s 5ft7 and 12st for all
you imperialists out there.] I prefer &amp;lsquo;cute&amp;rsquo; myself.. Just don&amp;rsquo;t
call me &amp;lsquo;middle age spreading&amp;rsquo; or I&amp;rsquo;ll have to kill you.&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h4 id=&#34;heres-what-im-like&#34;&gt;Here&amp;rsquo;s what I&amp;rsquo;m like:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;I don&amp;rsquo;t smoke (unless I&amp;rsquo;ve already finished too much Jack
Daniels),&lt;/li&gt;
&lt;li&gt;I don&amp;rsquo;t take recreational pharmaceuticals (unless everyone else is)&lt;/li&gt;
&lt;li&gt;I used to play badminton. I want to start again&amp;hellip;&lt;/li&gt;
&lt;li&gt;I drink occasionally (i.e. when anyone buys me a pint). Usually
right after badminton!&lt;/li&gt;
&lt;li&gt;I enjoy adventure, experiencing the power of nature, the local
culture, becoming one with the world; in particular with the local home-brew.&lt;/li&gt;
&lt;li&gt;I play guitar; when I can be bothered to practice.&lt;/li&gt;
&lt;li&gt;I ski and sail when on holiday. I should practice both to get better but I don&amp;rsquo;t&lt;/li&gt;
&lt;li&gt;I&amp;rsquo;m quite funny. No really ! This text was written too late at night..&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Here&amp;rsquo;s the low down. It get&amp;rsquo;s better. Honest!&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&#34;play&#34;&gt;Play&lt;/h3&gt;
&lt;p&gt;Serious &lt;em&gt;playing&lt;/em&gt; requires a little time away from the office, and a
social life. I try to make time for that, but I&amp;rsquo;ve got this lot to
contend with first:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Love Life&lt;/strong&gt;
Amazing! I am now married to a loverly Cornish girl called Gayle;
I suspect she might be a &lt;a href=&#34;http://www.mysteriousbritain.co.uk/folklore/piskies.html&#34;&gt;Piskie&lt;/a&gt;
so I will have to watch my step :)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Family&lt;/strong&gt;
Even more amazing! I have a baby son called James, born September 2011,
and baby girl called Megan born Jan 2013.  So proud of Gayle. Big hug!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Music&lt;/strong&gt;
I am a &lt;em&gt;Practicing musician&lt;/em&gt;; well perhaps &amp;lsquo;practice&amp;rsquo;
is too strong a word - perhaps &amp;lsquo;fools around&amp;rsquo; is more accurate!
Most recent outing as the bass player in the works Xmas band
I USED to I play guitar in an &amp;rsquo;electric folk&amp;rsquo; kind of combo; think
Pentangle but more Irish. You can find out more about &lt;a href=&#34;https://www.ashbysoft.com/articles/ph5/&#34;&gt;pH5&lt;/a&gt;
I also try to write/record stuff and I have a little project
studio in my back room. Digital of course :)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;DIY&lt;/strong&gt;
&lt;a href=&#34;../../images/upload/furniture.jpg&#34;&gt;I make stuff&lt;/a&gt;; furniture mostly, in a rather modern,
modular kinda style. Think Tapley, if you know that brand, but with more handles..&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also try to keep my house sorted, and the car, and the PC network, &amp;hellip;
current projects are to renovate the garden into a zen-like low maintainance area,
and re-build the digital with linux instead of Uncle Bill&amp;rsquo;s nightmare O/S&lt;/p&gt;
&lt;hr&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Helen</title>
      <link>https://www.ashbysoft.com/articles/helen/</link>
      <pubDate>Fri, 29 Mar 2013 17:48:36 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/helen/</guid>
      <description>Email: &amp;laquo;helen@ashbysoft.com&amp;raquo;</description>
      <content:encoded>&lt;p&gt;Email: &amp;laquo;&lt;a href=&#34;mailto:helen@ashbysoft.com&#34;&gt;helen@ashbysoft.com&lt;/a&gt;&amp;raquo;&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>PhilsDroid</title>
      <link>https://www.ashbysoft.com/posts/philsdroid/</link>
      <pubDate>Tue, 12 Mar 2013 11:45:54 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/philsdroid/</guid>
      <description>New Droid for Old So I lent my droid phone (Huawei U8120 below) to Joseph, &#39;cause his shiny toy got pinched :-(
Upon mentioning that I was now droidless, one of my colleagues at work (thanks Duncan!) has lent me his unwanted Samsung GT-I5500, of a similar vintage to the U8120, but locked to Three.. uh-huh.
Unlocking the GT-I5500 According to the interweb (well ok, mostly the excellent XDA Developers Forum), the network unlock code in a GT-I5500 is stored in the ROM image in plain text - nice.</description>
      <content:encoded>&lt;h1 id=&#34;new-droid-for-old&#34;&gt;New Droid for Old&lt;/h1&gt;
&lt;p&gt;So I lent my droid phone (Huawei U8120 below) to
&lt;a href=&#34;Joseph&#34; title=&#34;wikilink&#34;&gt;Joseph&lt;/a&gt;, &#39;cause his shiny toy got pinched :-(&lt;/p&gt;
&lt;p&gt;Upon mentioning that I was now droidless, one of my colleagues at work
(thanks Duncan!) has lent me his unwanted Samsung GT-I5500, of a similar
vintage to the U8120, but locked to Three.. uh-huh.&lt;/p&gt;
&lt;h2 id=&#34;unlocking-the-gt-i5500&#34;&gt;Unlocking the GT-I5500&lt;/h2&gt;
&lt;p&gt;According to the interweb (well ok, mostly the excellent &lt;a href=&#34;http://forum.xda-developers.com&#34; title=&#34;wikilink&#34;&gt;XDA Developers
Forum&lt;/a&gt;), the network unlock
code in a GT-I5500 is stored in the ROM image in plain text - nice.&lt;/p&gt;
&lt;p&gt;All one has to do is temporarily root the device using
rageagainstthecage or similar, connect to an adb shell as root, dump the
ROM from /dev/bml5 using cat or dd, then pull it off the phone and
search for a well-known signature near the unlock code. Power cycle the
phone and type the code in when prompted. Done.&lt;/p&gt;
&lt;h2 id=&#34;the-stock-rom&#34;&gt;The Stock ROM&lt;/h2&gt;
&lt;p&gt;It&#39;s running Froyo (2.2), with Samsung bells and whistles and of course
the G-man spyware. I&#39;ll be wiping this and putting ICS on when I get a
chance. There are also a bunch of Three apps (games mostly) that need to
&#39;authenticate&#39; via 3G (ie: prove you are still using their network!) -
not played any of course since I am on Vodaphone (BT Mobile).&lt;/p&gt;
&lt;h1 id=&#34;old-droid&#34;&gt;Old Droid&lt;/h1&gt;
&lt;p&gt;A colleague at work was kind enough to offer me a free, reasonably
modern handset (Vodafone 845 / Huawei U8120), so I&#39;m now the owner of
an Android phone - how hip is that :)&lt;/p&gt;
&lt;p&gt;This page is here to chart my progress in
updating/modifying/hacking/developing etc. If I learn anything that
wasn&#39;t obvious from the &#39;net I&#39;ll let you know.&lt;/p&gt;
&lt;h2 id=&#34;in-the-beginning&#34;&gt;In The Beginning&lt;/h2&gt;
&lt;p&gt;It was running the stock Vodafone build of Eclair (Android 2.1), the
bootloader was not locked (dunno if Huawei bootloader can be locked),
the recovery OS was stock Huawei and it worked. Time to break it...&lt;/p&gt;
&lt;p&gt;NB: Getting to the recovery OS is a case of holding the &#39;Call&#39; or
green button while powering it on. Getting to the bootloader requires
holding the &#39;Hangup&#39; or red button while powering it on.&lt;/p&gt;
&lt;h2 id=&#34;backups-and-ice-cream&#34;&gt;Backups and Ice-Cream&lt;/h2&gt;
&lt;p&gt;Some rummaging on &lt;a href=&#34;http://forum.xda-developers.com&#34;&gt;http://forum.xda-developers.com&lt;/a&gt; tells me that I can
run Ice-Cream Sandwich (ICS/Android 4.0.4), via an unofficial beta
release of
&lt;a href=&#34;http://forum.xda-developers.com/showthread.php?p=20878789&#34; title=&#34;wikilink&#34;&gt;CyanogenMod9&lt;/a&gt;.
Of course I&#39;d like to keep the stock OS incase I ever need to put it
back.&lt;/p&gt;
&lt;p&gt;The thread on XDA developers was very clear on proceedure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;start in bootloader mode, connect to a machine with the bootloader
control application (fastboot), then replace the recovery OS with
!ClockWorkMod.&lt;/li&gt;
&lt;li&gt;put CM9 installation package on an SD card&lt;/li&gt;
&lt;li&gt;restart in recovery mode, with the SD card installed&lt;/li&gt;
&lt;li&gt;take a &lt;a href=&#34;NANDroid&#34; title=&#34;wikilink&#34;&gt;NANDroid&lt;/a&gt; backup of remaining flash
partitions&lt;/li&gt;
&lt;li&gt;install CM9 from package on SD card&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Take deep breath and restart in normal mode - wait a looong time while
Android configures. It works!&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;interesting-diversion---joes-droid-&#34;&gt;Interesting Diversion -&amp;gt; Joe&#39;s Droid :)&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;Joseph&#34; title=&#34;wikilink&#34;&gt;Joseph&lt;/a&gt; has just got himself a shiny new HTC Desire
C on contract (so now I&#39;m waay less hip), and wanted to backup and root
it (as you do). A little more research turned up our &lt;a href=&#34;http://www.modaco.com/topic/355158-r1-superboot-how-to-root-the-htc-desire-c/&#34; title=&#34;wikilink&#34;&gt;Rooting
method&lt;/a&gt;
of choice.&lt;/p&gt;
&lt;p&gt;Applying this method gained us a root shell (via adb), from which we
were able to copy off the raw flash partition of the recovery OS using
dd from the appropriate /dev/block/mmcpXXX device to
/sdcard/recovery.img. That accomplished we installed !ClockWorkMod and
took a full &lt;a href=&#34;NANDroid&#34; title=&#34;wikilink&#34;&gt;NANDroid&lt;/a&gt; backup. Nice job.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;ui-pointers&#34;&gt;UI Pointers&lt;/h2&gt;
&lt;p&gt;Ok, so I&#39;ve got to get used to the UI metaphors on this touch screen
device (never had one before). Here&#39;s a list of all the things that I
didn&#39;t find obvious:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unpairing bluetooth devices: Get to settings-&amp;gt;bluetooth, then touch
and &lt;em&gt;hold the icon&lt;/em&gt; next to the device name. All the instructions I
found on line forgot to mention the icon behaves differently to the
device name area. Update: this appears to be a CM9 anomaly only -
but I would still have expected someone to mention it (CM is
popular!)&lt;/li&gt;
&lt;li&gt;Tethering to provide Internet access for another device:
settings-&amp;gt;more-&amp;gt;tethering, enable. However, do &lt;strong&gt;not&lt;/strong&gt; then go and
play with the connection options (accessed via the icon as above),
as this &lt;em&gt;reverses&lt;/em&gt; the tethering and the phone expects the device to
provide it with &#39;net access. Took me a long while to work out what
was going on there!&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;network-debugging&#34;&gt;Network Debugging&lt;/h2&gt;
&lt;p&gt;New for ICS, it supports network connections to the debugging daemon
(adbd), so once I finally got it tethered to my laptop (see above), I
could connect to the phone&#39;s IP address and get a wireless shell. Yes
this also works over &lt;a href=&#34;WiFi&#34; title=&#34;wikilink&#34;&gt;WiFi&lt;/a&gt;, but you wouldn&#39;t want to
expose an unauthenticated root shell to the &#39;net would you? eh?&lt;/p&gt;
&lt;h2 id=&#34;photoserr-where&#34;&gt;Photos...Err where?&lt;/h2&gt;
&lt;p&gt;I took a couple of photos to check the camera works ok (it does), but
couldn&#39;t find them anywhere on the phone with the File Manager app..
odd. Turns out I had assumed the DCIM folder on my SD card was a
hangover from previous use, and that the Pictures folder was the obvious
place. Nope. Android follows the JEITA specification and puts photos in
DCIM. And videos. And the Gallery app in CM9 beta is broken so I
couldn&#39;t look at photos on the phone. Now using
&lt;a href=&#34;QuickPic&#34; title=&#34;wikilink&#34;&gt;QuickPic&lt;/a&gt; which seems to work ok.&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Robert</title>
      <link>https://www.ashbysoft.com/articles/robert/</link>
      <pubDate>Sat, 10 Nov 2012 16:33:28 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/robert/</guid>
      <description>Email &amp;laquo;&lt;a href=&#34;mailto:robert@ashbysoft.com&#34;&gt;robert@ashbysoft.com&lt;/a&gt;&amp;raquo;</description>
      <content:encoded>&lt;p&gt;Robert smells. Also he makes musics &lt;a href=&#34;https://soundcloud.com/a66448579&#34;&gt;https://soundcloud.com/a66448579&lt;/a&gt;&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Joseph</title>
      <link>https://www.ashbysoft.com/articles/joseph/</link>
      <pubDate>Sun, 08 Apr 2012 22:46:55 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/joseph/</guid>
      <description>Email &amp;laquo;&lt;a href=&#34;mailto:joseph@ashbysoft.com&#34;&gt;joseph@ashbysoft.com&lt;/a&gt;&amp;raquo;</description>
      <content:encoded>&lt;p&gt;Email: &lt;a href=&#34;mailto:joseph@ashbysoft.com&#34;&gt; Me&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is Joe and I&amp;rsquo;m going to make a proper page whenever I can be
bothered and have found something to write about :)&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Hacking Picasa3</title>
      <link>https://www.ashbysoft.com/posts/hacking-picasa3/</link>
      <pubDate>Tue, 13 Mar 2012 01:00:25 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/hacking-picasa3/</guid>
      <description>The Need I have a whole pile of photos of family and friends that I have indexed with Picasa v3.8 and it&#39;s face recognition ability, using the Windows version of Picasa3 (because it was the &#39;right&#39; way to do this a couple of years ago).
In the middle of some facebook&#39;ery using my preferred OS (Ubuntu 10.10 ATM) I decided I wanted a photo of a friend to post, so grabbed the Picasa installer and ran it up in wine.</description>
      <content:encoded>&lt;h1 id=&#34;the-need&#34;&gt;The Need&lt;/h1&gt;
&lt;p&gt;I have a whole pile of photos of family and friends that I have indexed
with Picasa v3.8 and it&#39;s face recognition ability, using the Windows
version of Picasa3 (because it was the &#39;right&#39; way to do this a couple
of years ago).&lt;/p&gt;
&lt;p&gt;In the middle of some facebook&#39;ery using my preferred OS (Ubuntu 10.10
ATM) I decided I wanted a photo of a friend to post, so grabbed the
Picasa installer and ran it up in wine. All went well, but I got a nice
empty list of albums and no people, despite telling it where the photos
are on the network file server. Time to find out where Picasa hides the
metadata :)&lt;/p&gt;
&lt;h1 id=&#34;the-research&#34;&gt;The Research&lt;/h1&gt;
&lt;p&gt;Of course I went straight to the &#39;net and found a couple of posts back
in 2007 that talked about copying album information from the Application
Data area of the Windows user to the same area in wine&#39;s emulation:
kudos to these guys:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://forensicir.blogspot.com/2007/07/picasa.html&#34;&gt;http://forensicir.blogspot.com/2007/07/picasa.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://smallutilitiesforfree.blogspot.com/2007/11/how-to-copy-picasa-albums-from-windows.html&#34;&gt;http://smallutilitiesforfree.blogspot.com/2007/11/how-to-copy-picasa-albums-from-windows.html&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&#34;the-hacking-&#34;&gt;The Hacking :)&lt;/h1&gt;
&lt;p&gt;A little prodding around on my Windows partition shows that pretty much
the same structure is still there in current Picasa3 builds, along with
the all important Picasa2/contacts folder that has a nice XML file with
all my people in, &lt;em&gt;and their Picasa hash values&lt;/em&gt;. These hash values are
what ties together the contact details and the faces in photos, which
are stored in special files (.picasa.ini), one for each folder through
the image archive itself (on the file server).&lt;/p&gt;
&lt;p&gt;I therefore copied the contacts.xml file, and the album XML files (from
&lt;a href=&#34;Picasa2Albums&#34; title=&#34;wikilink&#34;&gt;Picasa2Albums&lt;/a&gt;/&lt;hash&gt;) from my Windows disk
to wine&#39;s emulation area (~/.wine/...).&lt;/p&gt;
&lt;p&gt;The next trick is to convince Picasa3 that I have the same mapped drive
letter (S:) in wine for the file server that I have in Windows - easy to
arrange with winecfg.&lt;/p&gt;
&lt;p&gt;The final hack was to open up the
&lt;a href=&#34;Picasa2Albums&#34; title=&#34;wikilink&#34;&gt;Picasa2Albums&lt;/a&gt;/watchedfolders.txt file and
remove the slightly broken assumption that I have C:\Documents and
Settings within wine..&lt;/p&gt;
&lt;h1 id=&#34;the-result&#34;&gt;The Result&lt;/h1&gt;
&lt;p&gt;Startup Picasa3 again, and lo! I have albums with photos in, but
&lt;strong&gt;still&lt;/strong&gt; no people. Bah. Just out of curiosity I tried adding a folder
and Picasa did it&#39;s thing, scanning for faces and then &lt;em&gt;oh joy&lt;/em&gt;
reconnecting the faces with the contact details. So the fix is simply to
rescan all the photos and it will pick up all the existing data
(slowly). Time for bed while it chews through 10000 photos!&lt;/p&gt;
&lt;p&gt;Phil.&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>pH5</title>
      <link>https://www.ashbysoft.com/articles/ph5/</link>
      <pubDate>Sat, 01 Oct 2011 14:39:35 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/ph5/</guid>
      <description>In a folk band long, long ago..</description>
      <content:encoded>&lt;h1 id=&#34;slightly-acidic&#34;&gt;Slightly Acidic&lt;/h1&gt;
&lt;p&gt;What do you call a sharp-edged, slight funky/quirky electric folk/rock
band (anything, they can&amp;rsquo;t hear you - ed.)? Ours was called pH5
(geddit?), and it existed from ~1994 - 1999. Band members:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dr. Simon Phoenix: keyboard wizard, technohead, muso and lyricist.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ashbysoft.com/articles/slash/&#34;&gt;Stuart&lt;/a&gt;: guitars, percussion, engineering
and vocals&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ashbysoft.com/articles/phlash/&#34;&gt;Phil&lt;/a&gt;: bass, percussion, engineering.&lt;/li&gt;
&lt;li&gt;Maurice Patrick, violin - just that, but bloody good at it :)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;newish-material-2009&#34;&gt;New(ish) Material (2009!)&lt;/h1&gt;
&lt;p&gt;Back in 2009 - Phil uncovered a couple of
un-mastered tracks recorded by pH5 back in late &amp;lsquo;99 or thereabouts -
probably in Stuart&amp;rsquo;s house, just before the band
separated to pursue their own interests, so for your listening delight,
I mixed them for release here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;../../images/upload/NoOnesThere.ogg&#34;&gt;NoOnesThere.ogg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../../images/upload/DailyBikini-II.ogg&#34;&gt;DailyBikini-II.ogg&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;old-material&#34;&gt;Old Material&lt;/h1&gt;
&lt;p&gt;For your entertainment, here are the tracks from our one and
only half-decent studio album, recorded in 1996 at the Driveway Studio
in Trimley St Mary (cheers Colin!):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;../../images/upload/Driveway%20Demo%2010.96.m3u&#34;&gt;Driveway Demo 10.96.m3u&lt;/a&gt; The playlist for&amp;hellip;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../../images/upload/Driveway%20Demo%2010.96%20-%2001%20-%20Musical%20Priest.mp3&#34;&gt;Musical Priest.mp3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../../images/upload/Driveway%20Demo%2010.96%20-%2002%20-%20Mad%20Moll%20Set.mp3&#34;&gt;Mad Moll Set.mp3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../../images/upload/Driveway%20Demo%2010.96%20-%2003%20-%20Pirate&#39;s%20Waltz%20-%20Drowsy%20Maggie.mp3&#34;&gt;Pirate&amp;rsquo;s Waltz Drowsy Maggie.mp3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../../images/upload/Driveway%20Demo%2010.96%20-%2004%20-%20Daily%20Bikini.mp3&#34;&gt;Daily Bikini.mp3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../../images/upload/Driveway%20Demo%2010.96%20-%2005%20-%20Bay%20Of%20Funday.mp3&#34;&gt;Bay Of Funday.mp3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../../images/upload/Driveway%20Demo%2010.96%20-%2006%20-%20Caislean%20an&#39;%20Oir.mp3&#34;&gt;Caislean an&amp;rsquo; Oir.mp3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CD&amp;rsquo;s available on request for a minimal reproduction fee of £2.00 -
please &lt;a href=&#34;mailto:phil.ph5@ashbysoft.com&#34;&gt;contact Phil&lt;/a&gt; if you
would like one.&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>CMI-8738 vs Jack</title>
      <link>https://www.ashbysoft.com/posts/cmi-8738-vs-jack/</link>
      <pubDate>Sun, 17 Apr 2011 18:39:34 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/cmi-8738-vs-jack/</guid>
      <description>Whilst playing with Ubuntu on the PC in &lt;a href=&#34;TheShed&#34; title=&#34;wikilink&#34;&gt;TheShed&lt;/a&gt; studio I finally discovered a way to &lt;a href=&#34;CMI-8738_vs_Jack&#34; title=&#34;wikilink&#34;&gt;get digital audio input to work reliably&lt;/a&gt; using our impressively cheap CMI-8738 based Trust sound card (£15). This has been bugging me for &lt;em&gt;years&lt;/em&gt;.</description>
      <content:encoded>&lt;h2 id=&#34;the-problem&#34;&gt;The Problem&lt;/h2&gt;
&lt;p&gt;A few years ago I bought an impressively cheap CMI-8738 based sound card
from Trust, it cost £15 I think. Ever since I have been trying to find a
way to use it reliably under Ubuntu linux for digital recording from our
Akai DPS-12.&lt;/p&gt;
&lt;p&gt;The root cause is that as soon as you enable the S/PDIF input, the card
stops delivering sample buffers via Alsa unless there is a valid S/PDIF
signal present (ie: the DPS-12 is connected and &lt;em&gt;switched on&lt;/em&gt;). This is
fine except that we are using jackd at the bottom end of the audio
stack, and jackd doesn&#39;t like a card that doesn&#39;t sample regularly, it
crashes out with a watchdog error.&lt;/p&gt;
&lt;p&gt;We &lt;em&gt;could&lt;/em&gt; remember to switch the DPS-12 on &lt;em&gt;before&lt;/em&gt; the PC every time
we switch the PC on... not gonna happen unless someone intends to
record something, or we can live with no digital input (as we have been
doing for a number of years).&lt;/p&gt;
&lt;h2 id=&#34;the-solution&#34;&gt;The Solution&lt;/h2&gt;
&lt;p&gt;..for which I owe Mr Torben Hoen a beer: &lt;strong&gt;alsa_in&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It&#39;s so darn simple - leave jackd running with output only (S/PDIF and
analogue are fine and nice low-latency), then in my audio startup
script, run alsa_in to read samples from the S/PDIF input and pretend
to be the standard capture backend for jackd (ie: call it &#39;system&#39;).&lt;/p&gt;
&lt;p&gt;The magic is that alsa_in is &lt;em&gt;happy to work with no input&lt;/em&gt;, it just
delivers empty buffers to jackd unless the S/PDIF signal is provided,
thus samples arrive from the CMI-8738, whereupon alsa_in delivers those
to jackd - genius :)&lt;/p&gt;
&lt;p&gt;/me dances a little jig :)&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>ZTE-G X930 Insides</title>
      <link>https://www.ashbysoft.com/posts/zte-g-x930-insides/</link>
      <pubDate>Sat, 12 Feb 2011 17:18:44 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/zte-g-x930-insides/</guid>
      <description>&lt;a href=&#34;Thomas&#34; title=&#34;wikilink&#34;&gt;Tom&lt;/a&gt; broke the USB connector off his phone, so I had to disassemble it (no I really did!), and took the opportunity to take some photos &lt;a href=&#34;ZTE-G_X930_Insides&#34; title=&#34;wikilink&#34;&gt;ZTE-G X930 Insides&lt;/a&gt;
&lt;em&gt;08-Apr-11 Update&lt;/em&gt;: I finally soldered a new connector back on - there aren&#39;t many distributors of micro-USB surface mount sockets in the uk - just Farnell it seems.</description>
      <content:encoded>&lt;h1 id=&#34;i-took-toms-phone-apart&#34;&gt;I took Tom&#39;s phone apart&lt;/h1&gt;
&lt;p&gt;Since there do not appear to be any internal photos of the ZTE-G X930
mobile on the &#39;net at the moment (and it&#39;s not FCC registered) and
&lt;a href=&#34;Thomas&#34; title=&#34;wikilink&#34;&gt;Tom&lt;/a&gt; broke off his USB socket, requiring the phone
to be dismantled, I took the opportunity to photograph the insides,
enjoy (click for larger version):&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;attachment:x930-1.jpg&#34; title=&#34;wikilink&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;attachment:x930-2.jpg&#34; title=&#34;wikilink&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;attachment:x930-3.jpg&#34; title=&#34;wikilink&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;attachment:x930-4.jpg&#34; title=&#34;wikilink&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Not very surprising really - it&#39;s the same !MediaTek ARM-based
processor as many other Chinese mobiles (MT6235BA), and thus likely runs
the Nucleus Plus OS like the &lt;a href=&#34;http://home.comcast.net/~plutarch/Sciphone-i68.html&#34; title=&#34;wikilink&#34;&gt;Sciphone
i68+&lt;/a&gt;.
The soldered in battery is a bit unusual - probably internal RAM backup
(in which case we&#39;d better hope Tom had nothing irreplaceable in
there!)&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>RivendellHacking</title>
      <link>https://www.ashbysoft.com/posts/rivendellhacking/</link>
      <pubDate>Mon, 31 Jan 2011 19:01:07 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/rivendellhacking/</guid>
      <description>Yeah I know, you all thought the site was dead and stuff... anyhow, as part of my role looking after the tech at &lt;a href=&#34;http://www.felixstoweradio.co.uk&#34; title=&#34;wikilink&#34;&gt;Felixstowe Radio&lt;/a&gt;, I maintain the installation of &lt;a href=&#34;http://www.rivendellaudio.org&#34; title=&#34;wikilink&#34;&gt;Rivendell&lt;/a&gt;, one of our play-out software packages, which needed some attention on Windows.. gory details &lt;a href=&#34;RivendellHacking&#34; title=&#34;wikilink&#34;&gt;here&lt;/a&gt;.</description>
      <content:encoded>&lt;h1 id=&#34;rivendell-hacking&#34;&gt;Rivendell Hacking&lt;/h1&gt;
&lt;p&gt;Open source software is great, even when it has faults, since one can
fix it oneself and return the patch to the community right? Well almost,
here&#39;s what I&#39;ve been up to with the play-out software used at the
local community radio station &lt;a href=&#34;http://www.felixstoweradio.co.uk&#34;&gt;http://www.felixstoweradio.co.uk&lt;/a&gt;:&lt;/p&gt;
&lt;h2 id=&#34;win32-binary-fixes&#34;&gt;Win32 Binary Fixes&lt;/h2&gt;
&lt;h3 id=&#34;short-story&#34;&gt;Short story&lt;/h3&gt;
&lt;p&gt;It seems none of the Rivendell developers are interested or able to
build Win32 binaries at the moment, so I had to patch the binary program
using IDA Pro to prevent a crash when creating new logs.&lt;/p&gt;
&lt;p&gt;Get the patched file here: &lt;a href=&#34;attachment:rdlogedit2.exe&#34;&gt;attachment:rdlogedit2.exe&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;long-story&#34;&gt;Long story&lt;/h3&gt;
&lt;p&gt;About a year ago we installed the Windows binaries to allow our editing
/ production teams to create play lists from the comfort of their
desktop(s) in the station office, or indeed at home. Unfortunately we
found that it crashes when attempting to create a new play list (aka a
&#39;log&#39;): so I grabbed the source, a helpful stack dump from wine and
settled down to fix the fault. The problem wasn&#39;t hard to find, a
simple null pointer dereference because the Win32 version doesn&#39;t
support multiple users, but someone forgot and referenced the currently
logged in user name variable. All I had to do now was build a fresh
binary and test it - this is where it all came unstuck as for some
reason the developers had chosen to use a &lt;em&gt;closed source&lt;/em&gt; version of QT
(3.21) on Win32, so I had no means to rebuild the binary. Never mind,
I&#39;ll just post the patch to the developers mailing list and ask them to
rebuild it. I was duly thanked for finding the problem and lo! a new
version of the source code appeared with the fix - but &lt;em&gt;no Windows
binaries&lt;/em&gt; :(&lt;/p&gt;
&lt;p&gt;I waited for 6 months, pestered the developers slightly and waited some
more - still no new binaries. It seems whoever had the right build tools
and libraries (ie: a QT3.21 license) has gone away. So now I have to
choose between trying to port everything to QT4 (which is open source on
Win32), as suggested &lt;em&gt;may&lt;/em&gt; be possible on the Wiki, or do something ugly&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;patch the binary :)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Well I chose the later since it was going to be quicker and we need it
working now: a brief sojourn with IDA Pro, and the excellent advice from
&lt;a href=&#34;http://marcoramilli.blogspot.com/2011/01/how-to-patch-binary-with-ida-pro.html&#34; title=&#34;wikilink&#34;&gt;Marco
Ramilli&lt;/a&gt;
did the trick, overwriting the pointer reference with nop instructions
and inserting a reference to the constant user name instead.
Surprisingly this &lt;em&gt;just worked&lt;/em&gt;. The fixed file is attached above.&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Simon</title>
      <link>https://www.ashbysoft.com/articles/simon/</link>
      <pubDate>Sat, 04 Dec 2010 23:22:49 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/simon/</guid>
      <description>email &amp;laquo;&lt;a href=&#34;mailto:simon@ashbysoft.com&#34;&gt;simon@ashbysoft.com&lt;/a&gt;&amp;raquo;</description>
      <content:encoded>&lt;h1 id=&#34;simon&#34;&gt;SIMON&lt;/h1&gt;
&lt;p&gt;Simon Profile:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Age: 8&lt;/li&gt;
&lt;li&gt;Height: About 4ft&lt;/li&gt;
&lt;li&gt;Weight: Quite heavy&lt;/li&gt;
&lt;li&gt;Hair colour: Blonde&lt;/li&gt;
&lt;li&gt;Eye colour: Brown&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Shoot on sight, he is armed and highly dangerous.&lt;/p&gt;
&lt;p&gt;Reward for capture: £500&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>PlayingWithFire</title>
      <link>https://www.ashbysoft.com/articles/playingwithfire/</link>
      <pubDate>Fri, 08 Oct 2010 08:24:13 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/playingwithfire/</guid>
      <description>Joe&amp;rsquo;s old band page..</description>
      <content:encoded>&lt;p&gt;&lt;a href=&#34;https://www.playingwithfire.org.uk/&#34;&gt;Playing With Fire&lt;/a&gt;
Official Website. This page is no longer needed :)&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>FoodPyramid</title>
      <link>https://www.ashbysoft.com/posts/foodpyramid/</link>
      <pubDate>Sat, 27 Jun 2009 21:50:31 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/posts/foodpyramid/</guid>
      <description>This appeared on our shopping list blackboard at some point last week:
Heh :)</description>
      <content:encoded>&lt;p&gt;This appeared on our shopping list blackboard at some point last week:&lt;/p&gt;
&lt;p&gt;Heh :)&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>TheShed__PartIII</title>
      <link>https://www.ashbysoft.com/articles/theshed/theshed__partiii/</link>
      <pubDate>Tue, 14 Apr 2009 11:34:37 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/theshed/theshed__partiii/</guid>
      <description>fittings, and fancy acoustics</description>
      <content:encoded>&lt;h1 id=&#34;interior-construction&#34;&gt;Interior construction&lt;/h1&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../fw_ceil.jpg&#34;&gt;&lt;img src=&#34;../fw_ceil.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;So the plan (which I will at some point scan in and put here!) goes like
this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Install hidden wiring for lights and power.&lt;/li&gt;
&lt;li&gt;Line the walls and ceiling with good quaility acoustic / thermal
insulation and plasterboard.&lt;/li&gt;
&lt;li&gt;Install lights and heating!!&lt;/li&gt;
&lt;li&gt;Build a partition wall across the middle, at an angle, with a double
door and window to create an isolation booth / drum room.&lt;/li&gt;
&lt;li&gt;Insulate the booth floor with jabloc or similar underfloor
polystyrene slabs.&lt;/li&gt;
&lt;li&gt;Pave the booth floor to provide an acoustic mass, line with ply or
MDF.&lt;/li&gt;
&lt;li&gt;Install acoustic absorbers and diffractors in the booth to control
resonances.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Simple huh? Well yes, but it&amp;rsquo;s a slow and fiddly job and frequent stops
for tea to warm our hands up don&amp;rsquo;t really help :)&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h2 id=&#34;install-wiring&#34;&gt;Install Wiring&lt;/h2&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../wiring.jpg&#34;&gt;&lt;img src=&#34;../wiring.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;This was actually rather easy - once I had decided &lt;em&gt;where&lt;/em&gt; the lights
needed to be, it was just a case of tacking in the cables, marking the
ends so I could tell which is which once the lining is in (thus hiding
the cables), and getting hold of some 3-core + earth for the switch
(which ended up coming from a wholesaler on a 50m roll, of which I used
2m :)&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h2 id=&#34;line-the-walls--ceiling&#34;&gt;Line the walls / ceiling&lt;/h2&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../shoot.jpg&#34;&gt;&lt;img src=&#34;../shoot.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;After some research (ie: surfing the &amp;rsquo;net for hours) I chose to use
&lt;a href=&#34;https://www.knaufinsulation.co.uk/output/products/page_294.html&#34;&gt;Crown Acoustic Partition Roll&lt;/a&gt;
in conjunction with ½&amp;quot; plasterboard which should achieve 20-30dB of
sound insulation and excellent thermal insulation too.&lt;/p&gt;
&lt;p&gt;That dangerous looking chap on the right is &lt;a href=&#34;https://www.ashbysoft.com/articles/martin/&#34;&gt;Martin&lt;/a&gt;
practising holding up a bank with a staple gun&amp;hellip; silly boy.&lt;/p&gt;
&lt;p&gt;Installing said lining is taking a while, but we&amp;rsquo;re half way there now
(11th Jan &amp;lsquo;06). The ceiling (see above) gave us the most
&amp;rsquo;entertainment&amp;rsquo; since a whole sheet of ½&amp;quot; plasterboard weighs about
40kg; Martin and I tried holding that over our heads for several
minutes while &lt;a href=&#34;https://www.ashbysoft.com/articles/joseph/&#34;&gt;Joseph&lt;/a&gt; rushed up
and down the ladder putting the screws in! Not good. It&amp;rsquo;s much easier
with four people holding the board up (thanks to
&lt;a href=&#34;https://www.ashbysoft.com/articles/robert/&#34;&gt;Rob&lt;/a&gt; and &lt;a href=&#34;#&#34;&gt;Angela&lt;/a&gt; :)&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;p&gt;&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../done_front.jpg&#34;&gt;&lt;img src=&#34;../done_front.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../stu_apes.jpg&#34;&gt;&lt;img src=&#34;../stu_apes.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s &lt;a href=&#34;https://www.ashbysoft.com/articles/slash/&#34;&gt;Stuart&lt;/a&gt; putting up the final piece of lining
on the front wall, it was starting to get quite warm inside by this
point.&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;hr&gt;
&lt;p&gt;Onward to &lt;a href=&#34;https://www.ashbysoft.com/articles/theshed/theshed__partiv/&#34;&gt;the results!&lt;/a&gt;&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Big40</title>
      <link>https://www.ashbysoft.com/articles/big40/</link>
      <pubDate>Tue, 14 Apr 2009 11:34:28 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/big40/</guid>
      <description>The chaps at 40..</description>
      <content:encoded>&lt;h1 id=&#34;stuarts-party&#34;&gt;Stuart&amp;rsquo;s Party&lt;/h1&gt;
&lt;p&gt;Hedonism! Well sort of, you&amp;rsquo;ve gotta slow down a bit at 40&amp;hellip; Thus
Stuart and several of his delightful friends had a rather grown up
party, and invited Angela &amp;amp; Phil along too. Apparantly we brought the
camera, I don&amp;rsquo;t really remember much in detail!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&#34;float-left&#34;&gt;&lt;a href=&#34;../../images/upload/lottie.jpg&#34;&gt;&lt;img src=&#34;../../images/upload/lottie.jpg&#34; width=&#34;192&#34; height=&#34;256&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../../images/upload/stuspeaks.jpg&#34;&gt;&lt;img src=&#34;../../images/upload/stuspeaks.jpg&#34; width=&#34;192&#34; height=&#34;256&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;The lovely lady on the sofa to the left is Charlotte, who was eventually
persuaded to bring her parents along so she had someone to sit on. Being
of the fairer sex, and slightly underage for most of the drinking games,
Lottie retied to bed around 10:30, having stolen the show until that point.&lt;/p&gt;
&lt;p&gt;On the right Stuart waxes lyrical about the issue of indigestion in modern
society, and provides some fine examples of his subject :)&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;p&gt;&lt;figure class=&#34;float-left&#34;&gt;&lt;a href=&#34;../../images/upload/whatsthat.jpg&#34;&gt;&lt;img src=&#34;../../images/upload/whatsthat.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../../images/upload/forks.jpg&#34;&gt;&lt;img src=&#34;../../images/upload/forks.jpg&#34; width=&#34;192&#34; height=&#34;256&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;If I remember correctly (although things were getting a tad hazy at this
point), this is Phil, Marie and Stuart trying to work out &amp;ldquo;what IS that
thing on the table?&amp;rdquo; It must have been good, Marie is taking a photo
(hmmn - must ask her for that one!) I strongly suspect we ate it shortly
afterwards&amp;hellip;&lt;/p&gt;
&lt;p&gt;Eeek! It&amp;rsquo;s a madman with a bunch of forks! Runaway! Actually I suspect
it&amp;rsquo;s just Stuart offering cake to all and sundry - after all it soaks
up Jack Daniels nicely - &lt;em&gt;hic&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h1 id=&#34;posh-nosh&#34;&gt;Posh Nosh&lt;/h1&gt;
&lt;p&gt;Having sobered up from the earlier adventures, Phil &amp;amp; Stuart thought it
was about time to treat the family to dinner at a nice restaurant. Thus
we all headed over to St Albans and the
&lt;a href=&#34;http://www.sopwellhouse.co.uk/&#34;&gt;Sopwell House Hotel&lt;/a&gt; for dinner in their
delightful abode.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&#34;float-left&#34;&gt;&lt;a href=&#34;../../images/upload/stutomphil.jpg&#34;&gt;&lt;img src=&#34;../../images/upload/stutomphil.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../../images/upload/mumdadstu.jpg&#34;&gt;&lt;img src=&#34;../../images/upload/mumdadstu.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll start at the end then shall we? This is the birthday boys
themselves, either side of a coffee-revived Tom, for some reason Angela
suggested we take our specs off for this one.&lt;/p&gt;
&lt;p&gt;Yes it&amp;rsquo;s Stuart talking again! I rekon he was telling a joke at this
point, since Dad is laughing and Mum has that slighty quizzical look
that says &amp;ldquo;is this a clean joke?&amp;rdquo; Hehe. You can tell from the mince
pies and plentiful empty glasses that we are still at the end of the
meal.&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;p&gt;&lt;figure class=&#34;float-left&#34;&gt;&lt;a href=&#34;../../images/upload/annemartin.jpg&#34;&gt;&lt;img src=&#34;../../images/upload/annemartin.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../../images/upload/jim.jpg&#34;&gt;&lt;img src=&#34;../../images/upload/jim.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s Anne, all sparkly and surrounded by those very large glasses again
(can&amp;rsquo;t think why). Martin is modelling the latest in &amp;lsquo;can I borrow a
tie&amp;rsquo; fashion, and the expression of a seasoned rock star when
approached by yet more paparazzi - More photos? Oh all right then&amp;hellip;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s the cheeky boy himself! Doing his best not to look like a school
physics teacher (yes he really was one of those), Jim is wearing a
vintage pinstripe shirt, and that special tie that says &amp;ldquo;Mr Higgins -
I&amp;rsquo;ve lost me pencil Sir!&amp;rdquo;&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;p&gt;&lt;figure class=&#34;float-left&#34;&gt;&lt;a href=&#34;../../images/upload/bobjoe.jpg&#34;&gt;&lt;img src=&#34;../../images/upload/bobjoe.jpg&#34; width=&#34;192&#34; height=&#34;256&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../../images/upload/helen.jpg&#34;&gt;&lt;img src=&#34;../../images/upload/helen.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Ohhhh! Is that a camer-&lt;em&gt;flash!&lt;/em&gt; Yup. Bob has decided that shaving is
for wimps, so the tash is likely to get longer&amp;hellip; when it reaches the
same density as his eyebrows he might notice! Joe is demonstrating the
supreme calm that can be achieved by drinking the finest champagne and
stealing Grandad&amp;rsquo;s mince pies.&lt;/p&gt;
&lt;p&gt;So errr when do we get fed exactly then Mum? Poor Helen has been waiting
all day for decent meal, and we made her sit in the car for 3 hours
before she could eat. It&amp;rsquo;s a hard life sometimes. I promise she was
much happier when the food arrived!&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>ThePond</title>
      <link>https://www.ashbysoft.com/articles/thepond/</link>
      <pubDate>Tue, 14 Apr 2009 11:34:28 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/thepond/</guid>
      <description>it&amp;rsquo;s wet, it&amp;rsquo;s roundish, it&amp;rsquo;s&amp;hellip;. a pond!</description>
      <content:encoded>&lt;p&gt;Ah summer - a gentle breeze wafting through the trees, the trickle of
water in the stream, the splash of frogs frolicking in a pond&amp;hellip; ah.
Better dig one then&lt;/p&gt;
&lt;figure class=&#34;float-left&#34;&gt;&lt;a href=&#34;pond1.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/thepond/pond1.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;It&amp;rsquo;s October, so the nasturtiums are running riot :) Can you see the
fish?&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;p&gt;&lt;figure class=&#34;float-left&#34;&gt;&lt;a href=&#34;pond3.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/thepond/pond3.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;pond2.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/thepond/pond2.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;lt;&amp;ndash; the North end&lt;/p&gt;
&lt;p&gt;the South end &amp;ndash;&amp;gt;&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;p&gt;&lt;figure class=&#34;float-left&#34;&gt;&lt;a href=&#34;lilly2.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/thepond/lilly2.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;lilly1.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/thepond/lilly1.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Pretty isn&amp;rsquo;t it?&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;figure class=&#34;float-left&#34;&gt;&lt;a href=&#34;fish.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/thepond/fish.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;2 out of 3 of the fish we put in survived, and then, rather
satisfyingly, we got little fish, and lots of &amp;rsquo;em :) We&amp;rsquo;ll tell you
how it goes over the winter&amp;hellip;&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>TheShed__PartII</title>
      <link>https://www.ashbysoft.com/articles/theshed/theshed__partii/</link>
      <pubDate>Tue, 14 Apr 2009 11:34:28 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/theshed/theshed__partii/</guid>
      <description>Nuke the old, build anew..</description>
      <content:encoded>&lt;h1 id=&#34;demolition&#34;&gt;Demolition&lt;/h1&gt;
&lt;p&gt;&lt;figure class=&#34;float-left&#34;&gt;&lt;a href=&#34;../fire.jpg&#34;&gt;&lt;img src=&#34;../fire.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;figure class=&#34;float-left&#34;&gt;&lt;a href=&#34;../fire2.jpg&#34;&gt;&lt;img src=&#34;../fire2.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;p&gt;Removing the old shed took ages, mostly because we had to carefully take
off the roof panels, while still standing on them, or the very wobbly
supporting rafters, then strip out all the rockwool lining (boy does
that stuff make you itch!) before we could properly enjoy the task of
hacking down the walls with a crowbar and big hammers :) In the end we
filled 2 skips (of 4 yards each), and had some left over to burn - ahhh
the smell of woodsmoke in the evening!&lt;/p&gt;
&lt;h1 id=&#34;construction&#34;&gt;Construction&lt;/h1&gt;
&lt;h2 id=&#34;day-1&#34;&gt;Day 1&lt;/h2&gt;
&lt;p&gt;After the ritual burning, we cleared the area, relocated and levelled
the paving slabs, then laid new joists on them, finally I aligned the
joists carefully before we placed the floor panels on them.&lt;/p&gt;
&lt;p&gt;Now the fun bit - putting up wall panels that are 10 feet long, 8 or 9
feet high, and weigh between 50-70kg each, in a force 4-5 breeze.
Suffice to say that we nearly lost the whole lot over next door at one
point - &lt;a href=&#34;https://www.ashbysoft.com/articles/robert/&#34;&gt;Robert&lt;/a&gt; managed to stop it from
leaving the garden, I then grabbed a nearby lump of 4x2 which I used
as a lever to put the structure back on it&amp;rsquo;s base and
&lt;a href=&#34;https://www.ashbysoft.com/articles/martin/&#34;&gt;Martin&lt;/a&gt; fitted a couple of screws into
the floor which helped a lot- phew!&lt;/p&gt;
&lt;p&gt;Having secured the walls to each other and the floor, we fitted the
central roof rafter and propped the structure using some left over
timbers from the old shed, then retired for the evening - worn out.&lt;/p&gt;
&lt;h2 id=&#34;day-2&#34;&gt;Day 2&lt;/h2&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../outside1.jpg&#34;&gt;&lt;img src=&#34;../outside1.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Pleased to see the structure still where we left it, we tackled the task
of putting the roof panels on, from inside the building with one step
ladder, one exterior ladder and lots of cunning.&lt;/p&gt;
&lt;p&gt;Luckily the panels fitted nicely through the gap between the walls and
the central rafter, and we were able to push them up, then slide them
back into position. &lt;a href=&#34;https://www.ashbysoft.com/articles/joseph/&#34;&gt;Joseph&lt;/a&gt; then got to
work with the drill and fitted the securing coach screws before the
wind picked up again.&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../outside2.jpg&#34;&gt;&lt;img src=&#34;../outside2.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Our final construction task of the day was to put down the roofing felt
which &lt;a href=&#34;https://www.ashbysoft.com/articles/thomas/&#34;&gt;Thomas&lt;/a&gt; and
&lt;a href=&#34;https://www.ashbysoft.com/articles/joseph/&#34;&gt;Joseph&lt;/a&gt; did very nicely with just a bit
of guidance from &lt;a href=&#34;https://www.ashbysoft.com/articles/phlash/&#34;&gt;Dad&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../inside.jpg&#34;&gt;&lt;img src=&#34;../inside.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;a href=&#34;#&#34;&gt;Angela&lt;/a&gt; then set to work with the woodstain, turning our building
a lovely shade of green. The result? See for yourself!&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h1 id=&#34;and-now&#34;&gt;..and now..&lt;/h1&gt;
&lt;p&gt;Detailed design is now starting on the internal room, which is probably
going to involve a diagonal partition wall (to reduce reflections and
gain a little extra space), paving slabs and polystyrene underfloor
insulation, ventilation ducts in (floor level) and out (ceiling), more
rockwool, acoustic curtains and plasterboarding.. to say nothing of the
timber frame to support all this gubbins. I think I&amp;rsquo;ll enjoy this bit!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Interior construction follows&amp;hellip; &lt;a href=&#34;https://www.ashbysoft.com/articles/theshed/theshed__partiii/&#34;&gt;more &amp;raquo;&lt;/a&gt;&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>TheShed__PartIV</title>
      <link>https://www.ashbysoft.com/articles/theshed/theshed__partiv/</link>
      <pubDate>Tue, 14 Apr 2009 11:34:28 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/theshed/theshed__partiv/</guid>
      <description>it&amp;rsquo;s a recording studio :)</description>
      <content:encoded>&lt;h1 id=&#34;the-results&#34;&gt;The Results!&lt;/h1&gt;
&lt;p&gt;Well here it is - the (almost) finished product - a recording studio in
a shed!&lt;/p&gt;
&lt;h2 id=&#34;control-room&#34;&gt;Control room&lt;/h2&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../control.jpg&#34;&gt;&lt;img src=&#34;../control.jpg&#34; width=&#34;192&#34; height=&#34;256&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Here is the control room, from the outside doorway looking in. Nice
curtain huh? That&amp;rsquo;s to absorb any front-to-back reflections at mid /
high frequency. Bass dispersal is achieved by putting shelves on the
back wall and filling them with junk and spare polystyrene blocks from
the floor :)&lt;/p&gt;
&lt;p&gt;The ventilation grille serves two purposes - ventilation (obviously),
and it&amp;rsquo;s our wiring conduit between the control room and the booth,
which minimises the number of holes through the partition wall.&lt;/p&gt;
&lt;p&gt;The control room window is a double glazed conservatory roof vent,
mounted sideways. It was left over from building
&lt;a href=&#34;https://www.ashbysoft.com/articles/theconservatory/&#34;&gt;the conservatory&lt;/a&gt;. Sometimes I&amp;rsquo;m
glad I horde old stuff.&lt;/p&gt;
&lt;p&gt;Yes the speakers really are hung up on bits of string&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h2 id=&#34;sound-booth&#34;&gt;Sound booth&lt;/h2&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../booth.jpg&#34;&gt;&lt;img src=&#34;../booth.jpg&#34; width=&#34;192&#34; height=&#34;256&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Here is the sound booth from the back corner looking towards the control
room window. I ought to be honest and point out the not-quite-finished
ceiling, which should also be sound insulated but isn&amp;rsquo;t (editors note:
it is now, Jan 2008). As you can see, the main insulation material at
the moment is carpet underlay, hung on the interior wooden frame that
forms the booth.&lt;/p&gt;
&lt;p&gt;The interior control room window was saved from the old shed. Just
underneath it is a small shelf holding a cheap MP3-capable mini system
for our headphone monitoring amp, and below that is where the wiring
comes into the room.&lt;/p&gt;
&lt;p&gt;The mixer on the chair and one of a pair of powered PA speakers provide
local foldback for rehearsals. The mixer also supplies two line level
signals from the microphones / guitars into the control room.&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h2 id=&#34;the-studio-in-use&#34;&gt;The studio in use&lt;/h2&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../booth_drums.jpg&#34;&gt;&lt;img src=&#34;../booth_drums.jpg&#34; width=&#34;240&#34; height=&#34;320&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;It&amp;rsquo;s time to rock this joint! Here &lt;a href=&#34;https://www.ashbysoft.com/articles/martin/&#34;&gt;Martin&lt;/a&gt; is
demonstrating there is indeed room to swing some sticks in the sound
booth. You can now see the other interior window (also reused from the
old shed) on the North facing side of the building and letting in a
reasonable amount of natural light, but no direct sunlight.&lt;/p&gt;
&lt;p&gt;The floor (just visible here) consists of a set of plywood boards, taped
together with the indispensable carpet tape (aka Gaffa tape).&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../booth_guitar_martin.jpg&#34;&gt;&lt;img src=&#34;../booth_guitar_martin.jpg&#34; width=&#34;240&#34; height=&#34;320&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Yup it&amp;rsquo;s Martin again, this time looking cool in front of the
partition wall door which leads into the control room.&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../booth_guitar_rob.jpg&#34;&gt;&lt;img src=&#34;../booth_guitar_rob.jpg&#34; width=&#34;320&#34; height=&#34;240&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Of course Bob is super cool when playing guitar too&amp;hellip; :)&lt;/p&gt;
&lt;p&gt;As indeed are many of their friends, who seem to turn up quite often for
organised and random musical events. As long as the food holds out
we&amp;rsquo;ll be fine&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;../partdoor.jpg&#34;&gt;&lt;img src=&#34;../partdoor.jpg&#34; width=&#34;240&#34; height=&#34;320&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;The interior door is just a cheapo from B&amp;amp;Q, with more glass to let in
the light from the control room, via the control room partition door,
which is double glazed (yet another bit of the old shed recycled).&lt;/p&gt;
&lt;p&gt;Here you can see the edge of the 100mm Jabloc underfloor insulation for
the sound booth.&lt;/p&gt;
&lt;p&gt;Oh, just incase you were wondering, the door is upside down!&lt;/p&gt;
&lt;p&gt;Welcome to Shed#1, step this way please&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Thomas</title>
      <link>https://www.ashbysoft.com/articles/thomas/</link>
      <pubDate>Tue, 14 Apr 2009 11:34:28 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/thomas/</guid>
      <description>Email &amp;laquo;&lt;a href=&#34;mailto:thomas@ashbysoft.com&#34;&gt;thomas@ashbysoft.com&lt;/a&gt;&amp;raquo;</description>
      <content:encoded>&lt;p&gt;Rock&amp;rsquo;s :)&lt;/p&gt;
&lt;p&gt;hello all people, Tom here, my band is going better than I expected,
we&amp;rsquo;re called&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;highly corrosive&lt;/strong&gt; ! we rock (or I think so) :) B) {OK}&lt;/p&gt;
&lt;p&gt;I will be back for more stuff later enjoy a bowl of:-&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;does not compute&lt;/strong&gt; this web page will self destruct in {3} {2} {1}
&lt;strong&gt;booooooooooooooooommm!!!!!&lt;/strong&gt; {X} {X} error rebooting page please wait
50 hours {X} {X}&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>IlluminatedGuitar</title>
      <link>https://www.ashbysoft.com/articles/illuminatedguitar/</link>
      <pubDate>Tue, 14 Apr 2009 11:34:27 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/illuminatedguitar/</guid>
      <description>Internal lighting for a Wesley PE200wh acrylic guitar - oh yeah.</description>
      <content:encoded>&lt;ol&gt;
&lt;li&gt;
&lt;ol&gt;
&lt;li&gt;intro&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;open.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/illuminatedguitar/open.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;a href=&#34;https://www.ashbysoft.com/articles/robert/&#34;&gt;Bob&lt;/a&gt; decided to spend his 16th birthday
money on a new guitar, and he chose a rather unusual instrument, the
&lt;a href=&#34;https://www.wesleyguitars.co.uk/&#34;&gt;Wesley Guitars&lt;/a&gt; PE200wh, a clear
acrylic strat copy - cool innit?&lt;/p&gt;
&lt;p&gt;Of course we couldn&amp;rsquo;t just leave it at that could we? Oh no. You see
it&amp;rsquo;s such a lovely clear piece of acrylic, it just had to be
illuminated from the inside. No really, it did&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;cavity.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/illuminatedguitar/cavity.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;If you&amp;rsquo;re gonna put lights inside a guitar, you gotta see what&amp;rsquo;s
already there :)&lt;/p&gt;
&lt;p&gt;Here we are opening it up to check the size and shape of the cavity,
which is nicely routed, and all the hardware is attached to the
frontplate (so no major disassembly required).&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;ledstrip.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/illuminatedguitar/ledstrip.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Some rummaging on the Maplin website turned up the ideal light source -
apparantly designed for lighting around vehicle bodies, these flexible
LED strips are low power, super bright, can be cut into smaller units
and will bend round inside the cavity.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.maplin.co.uk/Search.aspx?criteria=N56CF&amp;amp;DOY=13m12&#34;&gt;https://www.maplin.co.uk/Search.aspx?criteria=N56CF&amp;amp;DOY=13m12&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To provide a bit of colour, I bought two strips, one white and one blue,
and a toggle switch to select between them.&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;lights1.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/illuminatedguitar/lights1.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;lights2.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/illuminatedguitar/lights2.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;After much careful measuring, some cutting and a fair bit of soldering
on wires, the light strips can be taped into the cavity like this. Note
that I have soldered the strips with the negative sides commoned
together, which cuts down on wires and prevents nasty short circuits if
the parallel strips touch.&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;switch.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/illuminatedguitar/switch.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;In order to select different colours, we put in a SPDT toggle switch
with a centre detent (ie: off). To this we connected the feeds to the
lights, and a link wire to the power input, which comes via&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;power.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/illuminatedguitar/power.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;The necessary 12V supply &lt;strong&gt;was&lt;/strong&gt; fed to the guitar via the middle ring
of this stereo jack socket, a stereo screened cable and a custom made
breakout box on the floor, to which a suitable 12V supply is connected
(we&amp;rsquo;ve been using an old PSU from a force feedback steering wheel).&lt;/p&gt;
&lt;p&gt;Although this worked, it wasn&amp;rsquo;t ideal for a couple of reasons: the
pickup signal and lights share the ground connection at the socket, so
ground lift due to lighting currents causes clicks in the signal;
pulling the plug in/out momentarily short circuits all the contacts on
the plug which could damage both the supply and the amp depending on
what shorts first. Not good.&lt;/p&gt;
&lt;p&gt;We subsequently replaced the Strat-style socket mounting plate with a
flat acrylic plate, and added a standard 2.5mm power socket. We also
changed to using a switched mode power supply from an old LCD monitor
which neatly avoids any mains hum. It&amp;rsquo;s now quiet when operating and
safe from short circuits - still using the stereo socket with the
intention of sending digital lighting control signals to the guitar&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;blue.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/illuminatedguitar/blue.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;white.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/illuminatedguitar/white.jpg&#34; width=&#34;256&#34; height=&#34;192&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Need I say anything? Just how cool is that? :)&lt;/p&gt;
&lt;p&gt;Seeing just how darn bright this is, we are now planning on putting a
dual dimmer circuit in the guitar, with perhaps an audio sensor chip
(National Semi LM4970 or the like) so the lights follow your playing
and/or using the middle ring of the stereo socket to deliver a UART
signal from a remote lights controller (DMX via a PIC to the I2C bus
input of LM4970 maybe?). Your suggestions are welcome!&lt;/p&gt;
</content:encoded>
    </item>
    
    <item>
      <title>Martin</title>
      <link>https://www.ashbysoft.com/articles/martin/</link>
      <pubDate>Tue, 14 Apr 2009 11:34:27 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/martin/</guid>
      <description>Email &amp;laquo;&lt;a href=&#34;mailto:martin@ashbysoft.com&#34;&gt;martin@ashbysoft.com&lt;/a&gt;&amp;raquo;</description>
      <content:encoded>&lt;p&gt;Email: &amp;laquo;&lt;a href=&#34;mailto:martin@ashbysoft.com&#34;&gt;martin@ashbysoft.com&lt;/a&gt;&amp;raquo;&lt;/p&gt;
&lt;p&gt;Hi, I am Martin, member of the Ashby family, physics student at Warwick
University, and wannabe musician. I will reply to email I find
interesting, and I also have
&lt;a href=&#34;https://www.facebook.com&#34;&gt;facebook&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;life&#34;&gt;Life:&lt;/h1&gt;
&lt;p&gt;Consists of getting along with everyone if possible, particularly my
girlfriend Georgia. At some point in the near future I will realise that
guitar hero is not the path to passing my degree and do some work. In
the meantime I proceed with normal student/teenager like activities,
plus walking, cycling and minus some of the drinking.&lt;/p&gt;
&lt;h1 id=&#34;friends&#34;&gt;Friends:&lt;/h1&gt;
&lt;p&gt;I do have some, somewhere :) they know who they are and most of them
have facebook or some means of communication available to them. Also I
probably owe some of them money&amp;hellip;&lt;/p&gt;
&lt;h1 id=&#34;future&#34;&gt;Future:&lt;/h1&gt;
&lt;p&gt;In no way do I attempt to predict the future, but after my degree I will
inevitably need to pay off student debt. I hope to do this by moving in
with Georgia plus friends and getting some kind of real work. I would
much prefer to do this by starting some kind of musical career, writing
and/or performing interesting and varied bits of popular music
entertainment. As a back up option I have always considered robbing a
bank or pulling off some major fraud, although now this is publicly
disclosed I would hasten to add that it is very unlikely.&lt;/p&gt;
&lt;h1 id=&#34;music&#34;&gt;Music:&lt;/h1&gt;
&lt;p&gt;I describe myself as wannabe musician purely because I am not a pro. I
have however been playing drums for nearly 8 years, guitar for 5 years
and other instruments as and when people have shown me how to play them.
I have featured in numerous musical escapades, most recently playing
bass guitar and drums in
&lt;a href=&#34;http://www.myspace.com/thekamikazewatermelons&#34;&gt;Quorn&lt;/a&gt;. Since
joining Warwick Uni I have become an active member of the drumming
society, and have developed a taste for samba.&lt;/p&gt;
&lt;h1 id=&#34;education&#34;&gt;Education:&lt;/h1&gt;
&lt;p&gt;I attended St Albans RC High school in Ipswich, including 6th form, and
came out with some A levels and GCSEs: A&amp;rsquo;s in maths, more maths and
physics, and a C in French. I am now on a 3 year course in Physics at
&lt;a href=&#34;https://www2.warwick.ac.uk/&#34;&gt;Warwick University&lt;/a&gt; as previously
mentioned, which is pretty interesting most of the time, and not too
much work so far. This will change no doubt.&lt;/p&gt;
&lt;h1 id=&#34;entertainment&#34;&gt;Entertainment:&lt;/h1&gt;
&lt;p&gt;For entertainment I have many options, most preferable is adventuring
with Georgia. Recent times have seen us walk around 20 miles or
something like that, see some amazing sights and find tyre swings.
Jamming with Robert is another favourite activity, and others to follow
include guitar hero in Whitefields 6, drumming sociey sessions, cycling
and other sports, and just random things that happen really.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt;: If you are Carl Free, please get a life.&lt;/p&gt;
&lt;hr&gt;
</content:encoded>
    </item>
    
    <item>
      <title>TheConservatory</title>
      <link>https://www.ashbysoft.com/articles/theconservatory/</link>
      <pubDate>Tue, 14 Apr 2009 11:34:27 +0000</pubDate>
      
      <guid>https://www.ashbysoft.com/articles/theconservatory/</guid>
      <description>building big things in the garden</description>
      <content:encoded>&lt;h1 id=&#34;the-team&#34;&gt;The Team&lt;/h1&gt;
&lt;p&gt;Here&amp;rsquo;s a list of all the lovely folks who helped with this project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Len (Phil&amp;rsquo;s dad) - planning, labouring, site foreman - you know the
score :).&lt;/li&gt;
&lt;li&gt;Jim (Angela&amp;rsquo;s dad) - moral support, digging &amp;amp; tool hire (pick axe
anyone?).&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ashbysoft.com/articles/slash/&#34;&gt;Stuart&lt;/a&gt; - more labouring, moral support.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ashbysoft.com/articles/martin/&#34;&gt;Martin&lt;/a&gt;, &lt;a href=&#34;https://www.ashbysoft.com/articles/robert/&#34;&gt;Robert&lt;/a&gt; &amp;amp;
&lt;a href=&#34;https://www.ashbysoft.com/articles/joseph/&#34;&gt;Joseph&lt;/a&gt; - enthusiasm and construction.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#&#34;&gt;Angela&lt;/a&gt; - design, tea making &amp;amp; painting.&lt;/li&gt;
&lt;li&gt;Clem - yet more labouring, gophering..&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A big thank you to everyone, if you feel I have forgotten you please
&lt;a href=&#34;mailto:phil@ashbysoft.com?subject=Conservatory&#34;&gt;email me&lt;/a&gt;
and it shall be corrected!&lt;/p&gt;
&lt;h1 id=&#34;the-theory&#34;&gt;The Theory&lt;/h1&gt;
&lt;p&gt;&amp;ldquo;We need more space!&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Ring any bells? Well with our size family we need all the space we can
get, especially when the youngest leaves our room. Right now moving home
is simply out of the question - a five bedroom property costs 3-4 times
as much as our present 4-bed home did 5 years ago - madness! We had been
thinking about a conservatory on and off for a couple of years and now
it made sense as the cheapest way to get more space for the &amp;lsquo;stuff&amp;rsquo;
that accumulates around children (and Phil), freeing up bedroom space
for beds! In addition, Angela wants to grow more exotic plants and
fruits (bananas), Phil is keen to make the house more &amp;rsquo;eco-friendly&amp;rsquo;,
using solar energy from a conservatory for spring/autumn heating - so we
went for it!&lt;/p&gt;
&lt;h1 id=&#34;start-by-digging-a-hole&#34;&gt;Start by digging a hole..&lt;/h1&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;hole.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/theconservatory/hole.jpg&#34; width=&#34;320&#34; height=&#34;240&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;This photo was taken at the end of April, two weekends into the project,
and two weeks before the kit of parts arrived from our chosen
conservatory company &lt;a href=&#34;https://www.balticpine.co.uk/&#34;&gt;Baltic Pine&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Actually Phil should have started digging about a month before, because
there was a &lt;strong&gt;lot&lt;/strong&gt; of rubble in there that needed removing to the skip
(two skips eventually..)&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h1 id=&#34;now-fill-it-in-again&#34;&gt;Now fill it in again..&lt;/h1&gt;
&lt;p&gt;Having dug a nice hole, fill it in with freshly mixed concrete. To a
neatly marked out level - or failing that until you run out of ballast..
:)&lt;/p&gt;
&lt;p&gt;Buy some more ballast, then some more cement. Then spend another weekend
shovelling it into a mixer..&lt;/p&gt;
&lt;p&gt;NB: &lt;em&gt;Always&lt;/em&gt; hire a cement mixer - even for &amp;lsquo;just one&amp;rsquo; bag of
ballast..&lt;/p&gt;
&lt;h1 id=&#34;build-a-wall&#34;&gt;Build a wall..&lt;/h1&gt;
&lt;p&gt;..or get a nice chap down the road to build one for you, after you&amp;rsquo;ve
been to several builders merchants trying to find one that has the
required type of bricks (a condition of the planning permission of
course!)&lt;/p&gt;
&lt;p&gt;Cheers Ron!&lt;/p&gt;
&lt;h1 id=&#34;relax-&#34;&gt;Relax :)&lt;/h1&gt;
&lt;p&gt;OK. So at this point we took a holiday - things stopped for a couple of
weeks while we enjoyed the delights of Kent.&lt;/p&gt;
&lt;h1 id=&#34;paint-some-woodwork&#34;&gt;Paint some woodwork..&lt;/h1&gt;
&lt;p&gt;Time to unpack the kit of parts that arrived in mid-May, and see just
how many bits there are (eek!). Then sort out those that will be going
up first and set to work with the wood stain. Nice.&lt;/p&gt;
&lt;h1 id=&#34;see-if-the-frames-fit&#34;&gt;See if the frames fit..&lt;/h1&gt;
&lt;p&gt;A scary bit. Is the wall the right size? Is everything square? Where
does this bit go? Have I sawn off the right end? Phew.&lt;/p&gt;
&lt;h1 id=&#34;build-the-floor&#34;&gt;Build the floor&lt;/h1&gt;
&lt;p&gt;Yup - more concrete! Lovely. Only this time we&amp;rsquo;ve added a damp proof
membrane, underfloor polystyrene insulation, steel reinforcing mesh and
it&amp;rsquo;s all got to be done inside the walls, then levelled off with a
batten. We chose to fix some guides to the walls first (a good idea -
thanks Dad!).&lt;/p&gt;
&lt;p&gt;It was tricky, we ran out of ballast yet again and it was hot, so the
cement dried out very quickly - however hosepipes are great! We finished
off with a plain cement screed (a thin layer on top of the concrete) to
make everything smooth.&lt;/p&gt;
&lt;p&gt;By this time the builders merchant / hire firm knew what I wanted as I
walked in the door - actually they were getting a little worried about
my project and asked if everything was ok, which was nice of them!&lt;/p&gt;
&lt;h1 id=&#34;get-some-help-then-some-more&#34;&gt;Get some help, then some more.&lt;/h1&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;baseframe.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/theconservatory/baseframe.jpg&#34; width=&#34;320&#34; height=&#34;240&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;At this point lots of people are needed to stain the woodwork, drill the
wall fittings, trim the end frames, apply the sealant, balance the
frames, drill the pilot holes, put in the screws, read the manual
(again!) until you get this:&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h1 id=&#34;put-up-the-roof&#34;&gt;Put up the roof&lt;/h1&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;roof.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/theconservatory/roof.jpg&#34; width=&#34;320&#34; height=&#34;240&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;The most complicated bit of any wood conservatory is the roof - in our
case a beautifully made pine frame (I am on commision if you buy one!)
with double glazed panels, pre-built in the factory, and reassembled on
site by yours truely, which &lt;em&gt;must&lt;/em&gt; be put back together exactly right or
the glass won&amp;rsquo;t fit - ulp!&lt;/p&gt;
&lt;h1 id=&#34;glazing-the-roof&#34;&gt;Glazing the roof&lt;/h1&gt;
&lt;p&gt;Today we put in some of the glass panels - and thankfully they fitted
nicely!&lt;/p&gt;
&lt;p&gt;Update: Unfortunately the aluminium opening roof window was the wrong
size - bah. Spent 2 months chasing the supplier for the right size one.&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h1 id=&#34;the-finished-article&#34;&gt;The finished article!&lt;/h1&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;done.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/theconservatory/done.jpg&#34; width=&#34;320&#34; height=&#34;240&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;It&amp;rsquo;s done (nearly)! All the windows are in, the doors are fitted, and
the electrics are installed. Which of course means I can have lots of
flashing Christmas lights strung up round the roof to show it off at
night :) It does however need the dripping box gutters sorting out -
serve me right for putting a join along the bottom of the lining :(&lt;/p&gt;
&lt;p&gt;This picture was taken at 08:34 on Dec 3rd 2003 - chilly isn&amp;rsquo;t it?&lt;/p&gt;
&lt;div class=&#34;float-clear&#34;/&gt;
&lt;h1 id=&#34;would-i-do-it-again&#34;&gt;Would I do it again?&lt;/h1&gt;
&lt;p&gt;&lt;Phil draws breath though his teeth&gt; Weeeeeelll&amp;hellip; maybe. If so, I
would try and design the footings such that the concrete could be
delivered ready mixed (however this means ordering at least 1 cubic
metre of the stuff at a time), and I&amp;rsquo;d open all the packages as they
are delivered and check the sizes of everything! I&amp;rsquo;d also line any box
gutters with both the bitumen-like flashing strip I used here, and a
butyl liner to ensure it doesn&amp;rsquo;t leak.&lt;/p&gt;
&lt;h1 id=&#34;snow-update-2004&#34;&gt;Snow update! (2004)&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m glad to report that after the recent snow falls here in Feb 2004,
that my roof construction holds up, and the gutters didn&amp;rsquo;t leak after I
sealed them with liquid rubber back in November. Angela has also been
busy painting the walls, and filling it with plants - infact it almost
looks habitable, now where did I put that floor tile catalogue&amp;hellip;.&lt;/p&gt;
&lt;h1 id=&#34;and-finally-a-floor-2005&#34;&gt;..and finally.. a floor! (2005)&lt;/h1&gt;
&lt;figure class=&#34;float-right&#34;&gt;&lt;a href=&#34;floor.jpg&#34;&gt;&lt;img src=&#34;https://www.ashbysoft.com/articles/theconservatory/floor.jpg&#34; width=&#34;320&#34; height=&#34;240&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;It&amp;rsquo;s nearly June 2005, so the structure has been up almost two years,
and all that time I&amp;rsquo;ve been meaning to tile the floor. No really, I
have. Honest.&lt;/p&gt;
&lt;p&gt;Well I finally discovered a long weekend, at the start of half-term when
we weren&amp;rsquo;t rushing off to do stuff as a family - so I laid the floor -
yay!&lt;/p&gt;
&lt;p&gt;PS: That slightly sticky up tile in the left foreground? It got fixed
last week, and I grouted it all, with more help from Stuart - ta.&lt;/p&gt;
</content:encoded>
    </item>
    
  </channel>
</rss>

