<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andrew O'Rourke</title>
    <description>The latest articles on DEV Community by Andrew O'Rourke (@fogs).</description>
    <link>https://dev.to/fogs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3467%2Febbc8b13-8d4c-4439-a3f9-ab6ba46d18c5.png</url>
      <title>DEV Community: Andrew O'Rourke</title>
      <link>https://dev.to/fogs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fogs"/>
    <language>en</language>
    <item>
      <title>Telex: A Rust-Based PBX</title>
      <dc:creator>Andrew O'Rourke</dc:creator>
      <pubDate>Thu, 24 Nov 2022 17:07:37 +0000</pubDate>
      <link>https://dev.to/fogs/telex-a-rust-based-pbx-57b4</link>
      <guid>https://dev.to/fogs/telex-a-rust-based-pbx-57b4</guid>
      <description>&lt;p&gt;This post is a follow on from &lt;a href="https://montagne.uk/learning-rust" rel="noopener noreferrer"&gt;a previous post&lt;/a&gt; on my personal blog I've written about learning Rust. While I was going through the initial "Hello, world!" phases I had a horrible idea for a first project:&lt;/p&gt;

&lt;p&gt;"&lt;a href="https://www.asterisk.org/" rel="noopener noreferrer"&gt;Asterisk&lt;/a&gt; is terrible! How hard could it be to write a PBX from scratch?"&lt;/p&gt;

&lt;h4&gt;
  
  
  Project Goals
&lt;/h4&gt;

&lt;p&gt;Now, I've been pretty bad so far at documenting my projects so far, I've only written a single blog post on my Space Station 13 project. Hopefully I can be more proactive about this one.&lt;/p&gt;

&lt;p&gt;The initial goal for this project was to not even handle any calls, I only wanted to be able to point a softphone at my local IP address and have the PBX successfully reject the registration. This would prove that the software can at least talk to a real phone!&lt;/p&gt;

&lt;p&gt;Incidentally, the name comes from both the &lt;a href="https://en.wikipedia.org/wiki/Telex" rel="noopener noreferrer"&gt;Teleprinter Network&lt;/a&gt; and a contraction of Telephone Exchange.&lt;/p&gt;

&lt;h4&gt;
  
  
  What does a PBX do exactly?
&lt;/h4&gt;

&lt;p&gt;So, uh. Back to the actual project! Modern PBXes do two things: They handle the out-of-band signalling and handle the media (voice, video) streams.&lt;/p&gt;

&lt;p&gt;The former involves actually placing, receiving and terminating calls. This is done using a protocol called SIP (Session Initiation Protocol), which is a lot like HTTP. By sending requests to and from the phone and PBX, the phone can authenticate itself, register itself to receive calls, and actually do the whole telephone thing. There are extra things on top that support things like text messaging, presence etc. If you're really interested in the nitty-gritty, look at &lt;a href="https://www.rfc-editor.org/rfc/rfc3261" rel="noopener noreferrer"&gt;RFC 3261&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The latter is done by SIP instructing the phones to blindly send media via RTP (Real-time Transfer Protocol) to some destination in the ether. This isn't something I am currently worrying about, as the PBX can tell the phones to send media packets to each other directly.&lt;/p&gt;

&lt;p&gt;SIP can be performed over TCP, but usually both SIP and RTP are both performed over UDP, which has &lt;a href="https://dwarffortresswiki.org/index.php/DF2014:Losing" rel="noopener noreferrer"&gt;!!fun!!&lt;/a&gt; networking implications.&lt;/p&gt;

&lt;h4&gt;
  
  
  Building The Foundations
&lt;/h4&gt;

&lt;p&gt;The first thing I went about doing is building representations of the SIP requests and responses. This is where the lack of hierarchical inheritance started to mess with my brain! I dug out my copy of Wireshark and a copy of the RFC and started pulling together example exchanges between the softphone on my desktop, and the Asterisk PBX on my home server.&lt;/p&gt;

&lt;p&gt;This involved writing a lot of boilerplate, but it allowed me to pull together a structured SIP request from a string. With all of the cases for the headers and the string conversion logic, the file exceeded 200 lines. Handily, Rust easily allows you to define functionality in other files - so I pulled out the implementations for converting to/from strings and validating into their own files, making it easier to organise.&lt;/p&gt;

&lt;p&gt;Rust does support metaprogramming for doing this all for you, macros, but unfortunately it's not a simple string comparison for headers as they can contain dashes, which enums cannot. Additionally headers are case-insensitive, and SIP also defines shortened versions of the headers to help fit larger requests inside the maximum UDP packet size.&lt;/p&gt;

&lt;p&gt;The next issue to tackle was supporting both TCP and UDP connections, since SIP can happen over either. TCP requests require you to send a response back across the same connection, whereas with UDP each request must fit inside a single packet (limited to around 1454 bytes normally). To support this, I had to pull the handler code out into its own file and write wrapper code to handle TCP and UDP differently.&lt;/p&gt;

&lt;p&gt;I ended up making the handler work with streams, pulling lines one-by-one from input in order to keep things consistent. This involved, in UDP's case, putting the string into a buffer and feeding that into the request handler. Eventually, though, I had it all to the point where responses were being sent for each request.&lt;/p&gt;

&lt;p&gt;However, the softphone ignored all of the responses.&lt;/p&gt;

&lt;h4&gt;
  
  
  Debugging Black Box Issues
&lt;/h4&gt;

&lt;p&gt;Debugging this issue was incredibly frustrating. All I had to go on was comparing the exchanges of data between my softphone and Telex, and between my softphone and &lt;a href="https://www.asterisk.org/" rel="noopener noreferrer"&gt;Asterisk&lt;/a&gt;. The &lt;a href="https://www.rfc-editor.org/rfc/rfc3261" rel="noopener noreferrer"&gt;RFC&lt;/a&gt; is an incredibly dense technical document covering a lot of edge cases and desired behaviour, and it's hard to see the wood for the trees.&lt;/p&gt;

&lt;p&gt;To start off with I was just trying to respond with &lt;em&gt;503 Service Unavailable&lt;/em&gt;, in order to try and get the softphone to abort trying to register from the outset, since that would mean it was communicating. No dice, it kept trying to send requests over UDP until eventually timing out. I then tried changing the response to a &lt;em&gt;401 Unauthorized&lt;/em&gt; in order to prompt the phone into providing credentials. Nada.&lt;/p&gt;

&lt;p&gt;The second issue I considered is line endings. SIP defines that all line endings are &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/CRLF" rel="noopener noreferrer"&gt;CRLFs&lt;/a&gt;, but my responses were just LF, in line with *nix standards. Changing all my calls to manually insert &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/CRLF" rel="noopener noreferrer"&gt;CRLFs&lt;/a&gt; also did not do the trick.&lt;/p&gt;

&lt;p&gt;After leaving it for a couple of evenings I came back to it and went through the headers with a fine toothed comb, referring to the &lt;a href="https://www.rfc-editor.org/rfc/rfc3261" rel="noopener noreferrer"&gt;RFC&lt;/a&gt; to see which were required by the specification. Eventually I found an anomaly, the &lt;em&gt;Via&lt;/em&gt; header was being sent back from &lt;a href="https://www.asterisk.org/" rel="noopener noreferrer"&gt;Asterisk&lt;/a&gt; despite there being no proxies in-between. I decided to give it a go and just send back the same header in the response as in the request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxlii2yrzpuin8vtj1vc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxlii2yrzpuin8vtj1vc.png" alt="Screenshot of Wireshark showing a second SIP registration with auth" width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bam! That did it! The softphone immediately sent a second request with an authorization header! Telex, not having any concept of authentication, sent a &lt;em&gt;401 Unauthorized&lt;/em&gt; response &lt;em&gt;again&lt;/em&gt; in response and the softphone immediately gave up and stated that registration failed. It worked!&lt;/p&gt;

&lt;h4&gt;
  
  
  Going Forwards
&lt;/h4&gt;

&lt;p&gt;Now that Telex is actually communicating with the softphone I can work on actually supporting persistent state such as registrations and calls. As previously mentioned I'm going to avoid messing with RTP media and just instruct the phones to send media directly to each other.&lt;/p&gt;

&lt;p&gt;The eventual roadmap though is building a basic, functional PBX that I can slowly work on extending to add more and more functionality. I highly doubt there'll be much interest in the project, &lt;a href="https://www.asterisk.org/" rel="noopener noreferrer"&gt;Asterisk&lt;/a&gt; is a well established and mature piece of software with enterprise support - but it's fun to build something saner, and to have something to work with that isn't just a freemium front for Digium.&lt;/p&gt;

&lt;p&gt;If you're interested in seeing the code, I've thrown it up on GitHub &lt;a href="https://github.com/AndrewMontagne/telex" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If I write another post on Telex, I'll link to it down here.&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>It's okay to not be okay</title>
      <dc:creator>Andrew O'Rourke</dc:creator>
      <pubDate>Mon, 31 Jul 2017 17:22:34 +0000</pubDate>
      <link>https://dev.to/fogs/its-okay-to-not-be-okay</link>
      <guid>https://dev.to/fogs/its-okay-to-not-be-okay</guid>
      <description>&lt;p&gt;&lt;em&gt;DISCLAIMER: I am not a medical professional. I'm just someone who suffers from depression. Always seek help from a mental health professional if you are suffering. This post is also written in the context of UK employment law.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Foreword
&lt;/h3&gt;

&lt;p&gt;I'm not quite sure whether this article fits on dev.to,  but I've had this rattling around in my head for the better part of a few months, but I've never quite been brave enough  to commit it to paper. I apologise if this article is a bit intense, but it's a bit of an outpouring from my heart.&lt;/p&gt;

&lt;p&gt;I've been suffering from depression and anxiety for the better part of two years, but I'm on the road to recovery. It has definitely affected me in the workplace, and I would like to share some things which have made coping with it easier for me.&lt;/p&gt;

&lt;p&gt;The intended audience of this post is for those who also suffer, but I hope it helps improve the wider awareness of mental health issues in the community as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Remember you are not alone.
&lt;/h3&gt;

&lt;p&gt;I mean this in two ways: You are not the only person in the world who feels like this, and there are people out there who care about you. It's easy to forget this when you are suffering. Put it on a post-it somewhere on your desk as a reminder, or have a photograph of a loved one or your family. Surround yourself with people who complement you, instead of those who detract from you.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Be honest with your colleagues.
&lt;/h3&gt;

&lt;p&gt;This was one of the hardest things for me to do, but if your co-workers don't know that you're suffering, they can't be there for you. A lot of stigma towards depression comes from a lack of understanding, and if you're honest with your colleagues that you're struggling with your mental health, they can start to understand and help you.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Depression is real.
&lt;/h3&gt;

&lt;p&gt;Linking to the above, a lot of stigma towards depression manifests as being told to "man up" or being told to "cheer up". Don't listen to it, depression is real, and it claims tens of thousands of lives a year in suicides. In the United Kingdom, a mental health condition is considered a disability if it has a long-term effect on your normal day-to-day activity [1], and you are entitled to support from your employer [2]. Don't let people belittle your suffering.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Cut back on the caffeine.
&lt;/h3&gt;

&lt;p&gt;Seriously. Cut back on the caffeine, or cut it out entirely. Withdrawal can be a hard process to go through, and it can take a serious amount of willpower, but constant ups and downs caffeine gives you makes it a whole lot harder to cope with the rest of things. Cutting down was one of the best things I did recently, and it has given me a lot more energy in my downtime to do things I enjoy.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Have an understanding manager.
&lt;/h3&gt;

&lt;p&gt;This isn't always possible, but it is probably one of the best assets you can have in a workplace environment. I'm blessed with having a manager who has worked for me before in a previous job, and understands my situation. Help your manager understand your position in one-to-one's, and figure out what you can do for each other to make things easier.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Take five.
&lt;/h3&gt;

&lt;p&gt;If things are getting on top of you, take a break. Walk around the office, or go down the street to a corner shop for a cold drink. Some employers provide spaces for people to have some quiet time to themselves, take advantage of those if available. Try to clear your mind of troubles and stay centred. Don't let work consume you, and don't bury yourself in work to hide how you feel.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. It's okay to not be okay.
&lt;/h3&gt;

&lt;p&gt;Please don't suffer in silence. If you're struggling, seek help from a medical professional, talk to charities such as &lt;a href="http://www.mind.org.uk/" rel="noopener noreferrer"&gt;Mind&lt;/a&gt;, the &lt;a href="http://www.samaritans.org/" rel="noopener noreferrer"&gt;Samaritans&lt;/a&gt; or even your parents.&lt;/p&gt;

&lt;p&gt;Don't ever give up, there's light at the end of the tunnel. You matter. ðŸ’™&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.gov.uk/when-mental-health-condition-becomes-disability" rel="noopener noreferrer"&gt;When a mental health condition becomes a disability, gov.uk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gov.uk/when-mental-health-condition-becomes-disability" rel="noopener noreferrer"&gt;Reasonable adjustments for disabled workers, gov.uk&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>workplace</category>
      <category>mentalhealth</category>
    </item>
    <item>
      <title>Setting up a Git server in three simple steps</title>
      <dc:creator>Andrew O'Rourke</dc:creator>
      <pubDate>Sun, 02 Apr 2017 15:18:12 +0000</pubDate>
      <link>https://dev.to/fogs/setting-up-a-git-server-in-three-simple-steps</link>
      <guid>https://dev.to/fogs/setting-up-a-git-server-in-three-simple-steps</guid>
      <description>&lt;p&gt;This is a little thing I discovered which is pants-on-head simple to do, but is probably not known by a lot of people: How to host your own Git remotes on any *nix box with &lt;code&gt;sshd&lt;/code&gt; and &lt;code&gt;git&lt;/code&gt; installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A development machine with &lt;code&gt;git&lt;/code&gt; installed.&lt;/li&gt;
&lt;li&gt;A server machine with &lt;code&gt;git&lt;/code&gt; and &lt;code&gt;sshd&lt;/code&gt; installed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Instructions
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Step 1
&lt;/h4&gt;

&lt;p&gt;Create a git repository on your development machine, you can skip this step if you already have a repo you want to upload.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;16:01 andrew@hermes Development&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;sample &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;sample
16:02 andrew@hermes sample&lt;span class="nv"&gt;$ &lt;/span&gt;git init
Initialized empty Git repository &lt;span class="k"&gt;in&lt;/span&gt; /Users/andrew/Development/sample/.git/
16:02 andrew@hermes sample&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"# Sample Project"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; readme.md
16:02 andrew@hermes sample&lt;span class="nv"&gt;$ &lt;/span&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
16:02 andrew@hermes sample&lt;span class="nv"&gt;$ &lt;/span&gt;git commit
&lt;span class="o"&gt;[&lt;/span&gt;master &lt;span class="o"&gt;(&lt;/span&gt;root-commit&lt;span class="o"&gt;)&lt;/span&gt; 4612ba6] Initial commit.
 Committer: Andrew &amp;lt;andrew@hermes.local&amp;gt;
 1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
 create mode 100644 readme.md
16:02 andrew@hermes sample&lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 2
&lt;/h4&gt;

&lt;p&gt;Log on to your server and create the git remote.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;16:04 andrew@hermes sample&lt;span class="nv"&gt;$ &lt;/span&gt;ssh andrew@tesseract.local
16:05 andrew@tesseract ~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;git &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;git
16:05 andrew@tesseract git&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;sample &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;sample
16:05 andrew@tesseract sample&lt;span class="nv"&gt;$ &lt;/span&gt;git init &lt;span class="nt"&gt;--bare&lt;/span&gt;
Initialised empty Git repository &lt;span class="k"&gt;in&lt;/span&gt; /raid/home/andrew/git/sample/
16:05 andrew@tesseract sample&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;logout
&lt;/span&gt;16:06 andrew@hermes sample&lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 3
&lt;/h4&gt;

&lt;p&gt;Add the new remote to your git project and push.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;16:12 andrew@hermes sample&lt;span class="nv"&gt;$ &lt;/span&gt;git remote add origin andrew@tesseract.local:git/sample
16:12 andrew@hermes sample&lt;span class="nv"&gt;$ &lt;/span&gt;git push &lt;span class="nt"&gt;--set-upstream&lt;/span&gt; origin master
Counting objects: 3, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Writing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;3/3&lt;span class="o"&gt;)&lt;/span&gt;, 228 bytes | 0 bytes/s, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Total 3 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reused 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
To tesseract.local:git/sample
 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;new branch]      master -&amp;gt; master
Branch master &lt;span class="nb"&gt;set &lt;/span&gt;up to track remote branch master from origin.
16:12 andrew@hermes sample&lt;span class="nv"&gt;$ &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That's it. All you need to have a git remote is a bare repository on a remote host and ssh. You can now even delete your local repo and check it out again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;16:12 andrew@hermes sample&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ..
16:14 andrew@hermes Development&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; sample
16:14 andrew@hermes Development&lt;span class="nv"&gt;$ &lt;/span&gt;git clone andrew@tesseract.local:git/sample
Cloning into &lt;span class="s1"&gt;'sample'&lt;/span&gt;...
remote: Counting objects: 3, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Total 3 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reused 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
Receiving objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;3/3&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
16:14 andrew@hermes Development&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;sample/readme.md 
&lt;span class="c"&gt;# Sample Project&lt;/span&gt;
16:14 andrew@hermes Development&lt;span class="nv"&gt;$ &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>git</category>
      <category>server</category>
    </item>
    <item>
      <title>Hi, I'm Andrew</title>
      <dc:creator>Andrew O'Rourke</dc:creator>
      <pubDate>Wed, 22 Feb 2017 18:15:38 +0000</pubDate>
      <link>https://dev.to/fogs/hi-im-andrew</link>
      <guid>https://dev.to/fogs/hi-im-andrew</guid>
      <description>&lt;p&gt;I've been coding for 12 years (half my life!), but only 3 years in a professional environment.&lt;/p&gt;

&lt;p&gt;I started out coding because I am lazy, writing scripts to perform menial tasks on my behalf; it grew from there and now I write software for a multinational financial services firm - mostly APIs.&lt;/p&gt;

&lt;p&gt;I've written in a wide variety of languages and environments due to my curiosity, including - but not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PHP 4,5 and 7 - For all it's flaws I still love it&lt;/li&gt;
&lt;li&gt;Lua - Mostly video game modding&lt;/li&gt;
&lt;li&gt;Python - Still learning!&lt;/li&gt;
&lt;li&gt;Java - Dislike it, but it pays well&lt;/li&gt;
&lt;li&gt;Objective-C - Got me my first job as an iOS developer&lt;/li&gt;
&lt;li&gt;Objective-C++ - Never again&lt;/li&gt;
&lt;li&gt;C, C++ - Hard, but rewarding when it works&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm a bit of a jack of all trades, master of none, but I enjoy tinkering - especially trying to come up with a simple solution to a complex problem.&lt;/p&gt;

&lt;p&gt;You can also find me on Twitter as &lt;a href="https://twitter.com/AndrewMontagne" rel="noopener noreferrer"&gt;@AndrewMontagne&lt;/a&gt;, if you are so inclined.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
