Steve Streza

Software developer, comic book writer, video creator, hobbyist located in Seattle, WA.

I’m almost always coding personal projects for fun, to build automations for myself or learn new skills like server-side Swift or React Native or machine learning. But while that’s great for learning, and while there’s nothing wrong with learning for the sake of learning, it hasn’t led to much being finished. Instead, I have a pile of projects in my work folder (about 300 to date) and maybe 10-20% are usable. Aside from code, I’m learning maker skills like 3D modeling/printing, circuits, and woodworking, and those projects I definitely want to finish. It’s one thing for code to rot in a forgotten project folder, it’s another thing for a desk to be half-built taking up space in the garage.

Being stuck at home for 2020, I’ve wanted to finish more things, and head into 2021 getting more done. When I look at the personal project graveyard, I see some trends that are nearly universal.

  • Often, the project ends up with some amount of pursuit of Perfect Engineering. Coming up with the ultimate architecture, or constant refactoring, or wasting time building something like I would at a job.
  • Often times, I’m working with Swift which, while a great language for professionals building apps, makes for a very bad platform for hacker hobby projects. CI tools require constant maintenance, and while the language has finally started to become stable from an API perspective, frameworks built for them like SwiftUI and Vapor are on shifting sand foundations that change often, and cannot be relied on.
  • Most of these die after two months or so. I might pick them back up again down the road, but it’s almost always for similarly periods of time. And if I do, there is time and energy wasted on relearning the old code base, refactoring things, getting the project running again on Swift updates, etc.

On a software engineering team, the first two are absolutely not problems. Investing time into architecture and anticipating problems pays off as less engineering time and fewer errors in production. Engineering teams can afford to spend people’s time to keeping Mac-specific build bots updated with the latest versions of Xcode, and can budget time for language changes and framework updates. But these are distractions whern you’re making a hobby project.

In the last month, I’ve tried two projects with a far scrappier approach. Instead of letting scope creep and architectural purity have their way, I gave myself a short time window to get the thing done, and then force myself to move on. The first was scoped for two weeks, and the second was done over the four day Christmas weekend. I had a clear goal of what I wanted the thing to do, and a short amount of time to make it work.

That means cutting corners at every turn. I used singletons and globals. I had dependencies talking to each other through direct communication or a single pub/sub messaging bus rather than go through clean interfaces. For a mobile app, instead of fancy patterns, I just crammed my view controllers full of functionality and connected them to each other. For a web app, I used basic server-side rendering and a single no-framework no-bundler JavaScript file for client-side UI control; no Webpack or React or GraphQL wasting time with setup and adding architectural complexity. By and large, I would be embarrassed to ever let anyone see this code, or turn into a pull request.

But in both cases, I finished ahead of time, and the thing exists. It works, and I can use it. And perhaps a bigger benefit, my brain can let it go when it’s done, and give my full focus to relaxing or doing housework or exercising. We talk a lot about work/life balance, and perhaps hobby/life balance is just as important.

I think this is how I’m going to approach personal coding projects for now. Scrap something together within a time box, and never mind how it’s built under the hood. I’m sure I’ll keep working on some long running projects, and I’m sure I’ll find ways to iterate on Thing 1.0 and add stuff to them. But by starting from this foundation going into projects in 2021, I can hopefully actually get more of them done.

In case anyone is concerned, this is not a security vulnerability in SwiftNIO, TLS, or anything else. This is merely a debugging feature I wanted to make more obvious.

I’ve been somewhat fascinated with SwiftNIO lately. There’s something magical about getting code to work at the wire protocol level, and SwiftNIO makes it easy to do it safely and efficiently. I’ll save talking about it in much depth here, as I’m still very much figuring that out as I go, but I wanted to share a tip I had to figure out that I couldn’t easily find an answer for without some creative searching. Note: This post will be generally useless to you unless you’re already using NIOSSLContext and TLSConfiguration.

I came across Project Gemini recently, a simple hypertext protocol without all the tons and tons of baggage that the web has built up over the last few decades, and decided to give it a spin with SwiftNIO. Within a day, I was able to get a basic client implementation up and running, but doing so required some debugging.

Much like HTTP, Gemini runs with a request/response model, and I ran into a problem where I wasn’t sure if the server was receiving my requests, sending a response, or if something in my SwiftNIO code was not working properly. Normally when doing something at the wire protocol level, you would use a tool like Wireshark, but the trick is that Gemini requires ALL traffic to be TLS-encrypted. This means that, on its own, Wireshark can’t break the encryption (which is a very good thing!).

Fortunately, I’m not the only one who has needed to break TLS encryption for debugging reasons. TLS encryption requires both the client and sender to agree on encryption secrets, and if you have those,, Wireshark can decrypt the data. Many tools like curl and some browsers support writing these secrets to a file using the environment variable SSLKEYLOGFILE, but I don’t think SwiftNIO’s TLS library supports this by default.

Instead, SwiftNIO exposes an API to access the important secrets as data. When setting up your TLSConfiguration.forClient(), you can pass a closure to keyLogCallback. This will get called periodically as part of TLS negotiations, and is equivalnet to the SSKEYLOGFILE output you’d get from curl and friends. Just write this to a file somewhere using whatever API you like, e.g. FileManager().createFile(...) if running on a Mac and make sure you’re appending and not overwriting. Make sure not to ship this!

wireshark tls preferences

Once this file is written somewhere, open Wireshark and go to Preferences. Open the Protocols section and scroll all the way down to TLS. At the bottom of that pane will be a textbox that says something like (Pre)-Master-Secret log filename, and here you put the path to the file you wrote out earlier. Wireshark will automatically monitor that file for updates, and with any luck, you should see decrypted traffic start to show up in Wireshark’s logs.

In the end, my bug was that when I was writing the request to the SwiftNIO Channel, it wasn’t flushing it. So ultimately I just had to change channel.write(...) to channel.writeAndFlush(...) and everything started working. Once Wireshark was decrypting the data, I was able to see that the request was simply never making it to the server I was connecting to, and that it started working just fine with that code change.

Update: Johannes Weiss of the SwiftNIO core team has pointed out another approach for capturing packets: NIOWritePCAPHandler. If you add this to your channel pipeline after the SSL handler, you can have it write out .pcap files which can be read by Wireshark or tcpdump. An example of this can be found in the swift-nio-extras repository. I completely missed this when hunting for answers, and this looks like it can be similarly helpful for debugging TLS-encrypted network traffic.

I self-host a lot of the tools and services I use on a daily basis, meaning that rather than relying on iCloud or Dropbox or GitHub, I run a comparable (usually open-source) service on a server I control, either in the cloud or out of a server in my house. One thing that has been missing from that setup has been a tool to manage documents (receipts, tax forms, bank statements, etc). I recently stumbled onto Docspell and have been trying it out in that role for the last few days. The only problem is that it didn’t have an iOS app to use to upload receipts and documents to it. Rather than try to make an app myself, I saw that there was a simple HTTP POST API for uploading documents, which was compatible with the iOS Shortcuts app.

So I built a shortcut to do that. When you add it to your Shortcuts app on an iPhone or iPad, it’ll ask you a few questions, like what your upload API URL is and what kind of document it’ll prompt you for (e.g. if you wanted a shortcut specific to receipts). It’ll default to having the name “save to Docspell”, but you can change that to something else like “save a receipt”.

There are four main ways to use this:

  1. You can tap it as a button from the Shortcuts app or widgets. It’ll ask you the name of the thing you want, and then prompt you to either select a file or capture some photos with the camera.
  2. You can ask Siri to “save to Docspell” (or whatever you named it), and it’ll prompt you for those same things.
  3. You can use the share button to save stuff from across your device. Attachments in mail, downloaded PDFs, screenshots, or really anything that could be treated as a file. In theory you can even share webpages to it and it should make an archive of the page (though my server times out when I try this).
  4. You can use it as an export target for other workflows, meaning if you wanted to use a Shortcut to generate a PDF, you could then feed it into the Save to Docspell shortcut and upload it there.

When you run it without input (#1 and #2 above) it’ll ask whether you want to upload a file or take some photos with the camera. If you take multiple photos, it’ll stitch them into a PDF for upload. All photos will be converted to JPEG, even if your phone is set to save as HEIC by default, and the orientation will be fixed to make sure OCR works. If you select a file, you can use the phone’s file browser to pick one from your device, iCloud, or any storage providers (e.g. Nextcloud) that you might want to export from. And it’ll notify you when the upload is successful, using a message directly from the API, so it can’t fail silently unless there’s a problem on the server. You can also setup multiple copies of the workflow with different public API upload URLs and names, so if you wanted one for receipts and a different one bank statements.

Link

WWDC Should Stay Online-Only


Apple took WWDC online-only this year as a result of COVID-19. After 30-some years of the conference taking place between Santa Clara, San Jose, and San Francisco, there wasn’t precedent for this. While parts of WWDC (namely the sessions) had been easy to access online for several years, others like labs and live events were limited to on-site attendees only.

Last week we found out that, really, not much was missing. The keynote/state of the union still happened at the same times, but were pre-recorded around Apple’s campus. Sessions were released daily during the conference as videos of people talking over slide decks, rather than as presenters on stage in a conference hall. Labs were still held, but were done via teleconference and appointment. Even the Apple Design Awards and the lunch-time special guest events still happened. What was really missing was just the in-person face time from thousands of developers in one place, and the occasional event like the WWDC Bash.

But what was remarkable to me was how much better the week was as a whole. I attended WWDC in person from 2006 to 2015, and remotely since then, and this year’s conference was dramatically improved over both the onsite and online experience. So much so, that I don’t think WWDC should return as an in-person conference. Here’s why.

Read More

This is a notice that I have created a new PGP key as of May 19, 2020. The old key was not compromised, but all future PGP usage should rely on the new key as of this date. The new key was created in a secure environment and is trustworthy in all places where the old key was trusted previously.

Read MoreLink

Final Fantasy VII Remake is Looking Incredible


I’ve been hoping for a remake of Final Fantasy VII since the mid-2000s. Since they made a movie out of it with Advent Children, it seemed like a dream too good to ever come true to see its beautiful dieselpunk world revisited in video game form unencumbered by the technological limits of the PlayStation (and the Super Nintendo it was originally destined for).

When they announced it in 2015, I was ecstatic at how they were presenting it, but certainly had my concerns that they’d ever be able to really pull it off. Shifting away from its turn-based roots to something more action-oriented seem like a huge gamble, one that would require revisiting so many core assumptions about how the game played. The new tone being darker and more intimate would also recontextualize many of the original’s campier vibe. Final Fantasy as a single-player series wasn’t exactly faring well, with the XIII games not prioritizing gameplay as high as cinematic fidelity. And even if you got everything right, you still have to please fans of one of the highest rated games of all time by bringing this work to the present without sacrificing what made it great to begin with.

Time was also not kind to this project. About a year and a half after its announcement, with mostly silence from the producers, its development was effectively soft-rebooted, citing quality concerns. While it was definitely a good idea to ensure the game was as good as we all wanted, it signaled the game would take even longer to emerge. In the meantime, Final Fantasy XV finally came out… in a sense. Being stuck in development hell for so long, it cut out a bunch of story pieces and moved them to CG movies and anime shows. Additional chapters would keep coming out to fill out the story, and are still being developed to this day. But the game was at least mostly well received, even if I thought it was pretty boring to play, much like the XIII series was for me.

So with all this stacked against it, Final Fantasy VII Remake finally emerged in 2019, three and a half years later, and… looked incredible. More trailers would come out, people posted hands-on reports of playing it at conventions like PAX West, and it seemed like maybe this was going to work out. It did get delayed, but only by about 5 weeks, which usually indicates some last minute critical bugs slipping past a GM build date.

While the full game won’t be out for another month, yesterday they posted a free demo of the game. And so far, after running through the demo three times, it looks like they actually pulled it off.

They perfectly captured the ambiance of the world and scenes, while modernizing everything about the game itself. Visually, the world is stunning, enriched with detail in every corner. Movement is fluid and natural, and perfectly segues between action, battle, and cutscenes many times throughout. The soundtrack is on another level, reimagining classics from the original with new life. The characters bring soul and charm to the opening reactor attack, cutting through the super serious nature of what you’re doing (even if the writing was a little cheesy at times).

But the battle system is on another level from what I could’ve imagined. This is, in every way, a leap over anything Final Fantasy has ever tried. Each character gets their own fighting style, with special moves and modes to switch between. Cloud is either dancing around with a sword or getting up in the bad guy’s face to deal massive damage. Barret’s much more about long distance and taking out enemies at different vertical levels, which might be the first time we’ve seen that (outside of maybe Tactics). While in battle, you can switch from real-time to mostly paused to select abilities, but you can also set shortcuts mapped to the L1 button, which I believe is very similar to Kingdom Hearts. It also steals the Final Fantasy 13 staggering system to drive down an opponent’s ability to keep fighting.

Abilities are not the fire-and-forget spells of JRPGs past, but rather something that depends a lot on positioning, distance, and timing. If you’re 20 yards away from a bad guy, your skill is going to miss, but if you’re close and another enemy jumps in front of you, you’ll hit both. This helps break the monotony of RPGs where you quickly fall into a rhythm of knowing what your best spells are and spamming them until the battle is over. Each encounter requires situational awareness and competence with your party’s skills. Boring encounters is usually poison for an RPG for me, so this is an incredible thing to feel when playing the demo.

Overall, I’ve played the demo three times and had a blast each time through. There’s still a lot we don’t know about the game, including how other characters will play, how much of the story is covered, and how many episodes there will be or when they’ll be released. But so far, Final Fantasy VII Remake looks like it will be the new benchmark of the JRPG genre. The demo has incredible production and polish to it, and hopefully that carries through the full release. It’s been truly remade, and as a fan of this game since it came out, I cannot wait to play the full thing (in between sprints of Animal Crossing: New Horizons).

Your move, Persona 6.

The Paywalled Garden: iOS is Adware


Over the years, Apple has built up a portfolio of services and add-ons that you pay for. Starting with AppleCare extended warranties and iCloud data subscriptions, they expanded to Apple Music a few years ago, only to dramatically ramp up their offerings last year with TV+, News+, Arcade, and Card. Their services business, taken as a whole, is quickly becoming massive; Apple reported $12.7 billion in Q1 2020 alone, nearly a sixth of its already gigantic quarterly revenue.

All that money comes from the wallets of 480 million subscribers, and their goal is to grow that number to 600 million this year. But to do that, Apple has resorted to insidious tactics to get those people: ads. Lots and lots of ads, on devices that you pay for. iOS 13 has an abundance of ads from Apple marketing Apple services, from the moment you set it up and all throughout the experience. These ads cannot be hidden through the iOS content blocker extension system. Some can be dismissed or hidden, but most cannot, and are purposefully designed into core apps like Music and the App Store. There’s a term to describe software that has lots of unremovable ads: adware, which what iOS has sadly become.

If you don’t subscribe to these services, you’ll be forced to look at these ads constantly, either in the apps you use or the push notifications they have turned on by default. The pervasiveness of ads in iOS is a topic largely unexplored, perhaps due to these services having a lot of adoption among the early adopter crowd that tends to discuss Apple and their design. This isn’t a value call on the services themselves, but a look at how aggressively Apple pushes you to pay for them, and how that growth-hack-style design comes at the expense of the user experience. In this post, I’ll break down all of the places in iOS that I’ve found that have Apple-manufactured ads. You can replicate these results yourself by doing a factory reset of an iPhone (backup first!), installing iOS 13, and signing up for a new iCloud account.

Apple Music

ios adware apple music 1

When you open the Music app for the first time, it shows you an empty library and a bit saying that you can get music from the iTunes Store. So you head over to the search tab (ignoring the “Search By Lyrics” ad for Apple Music), and search for an artist, and find that your library is empty, but that Apple Music search tab sure is full of lots of exciting stuff. You navigate down to the song you want to listen to, and you get greeted with a fullscreen popup ad for Apple Music, one which went out of its way to disable support for iOS 13’s new swipe-to-dismiss gesture.

ios adware apple music 2

Leaving search, there are three other tabs at the bottom: For You, Browse, and Radio. The “For You” tab is a sneaky ad, offering to help you find new music based on your tastes. Tapping the big red button takes you to a signup screen for Apple Music. Nowhere on this screen was it stated to be a subscription feature.

ios adware apple music 3

Under Browse, you find a whole selection of songs, artists, playlists, and other general curated music selections. Tapping into basically anything will take you to a fullscreen Apple Music ad.

ios adware apple music 4

In Radio, we finally have something we can tap that doesn’t trigger an Apple Music ad! Beats 1 can be played seemingly without subscribing to Apple Music, and some of the older interviews are playable. I say “some”, because while tapping on that interview of A Boogie Wit Da Hoodie will play, tapping on the entry for A Boogie Wit Da Hoodie under the “In Case You Missed It” section will bring up another fullscreen ad.

As a bonus, it stops whatever you’re playing, as the audio player switches to the track you selected before the server tells it that it can’t be played without a subscription. I think this is a bug more than malice, but it highlights how the app is designed for the subscriber, not the person who doesn’t want Apple Music.

ios adware apple music 5

So Browse and For Now are entirely Apple Music ads. Radio has some free content but that largely exists to pull people into Apple Music, and Search will happily pull you in to Apple Music if you tap the button. Almost this entire app serves to be an ad for Apple Music. There is a setting in the Settings app to hide Apple Music (next to an ad for Apple Music, of course), but that only does so much.

The Browse and For Now tabs are hidden, and some of the Apple Music-exclusive stuff in Radio is hidden. But every radio station except for Beats 1 is still present, all which trigger an Apple Music ad. After you quit and restart the Music app, the search bar changes the “Apple Music” search results to “Radio”, but the autocomplete largely populates from Apple Music, and some of the search results can return playlists that take you to Apple Music. It helps, but ads are still there to be stumbled into.

ios adware apple music notifications

If you subscribe and then cancel, Apple sends invasive push notifications asking you to re-susbscribe. These are on by default without a permission request. This is, of course, against the rules they lay out for other developers.

Push Notifications must not be required for the app to function, and should not be used for advertising, promotions, or direct marketing purposes or to send sensitive personal or confidential information.

Apple TV+

ios adware apple tv

The TV app opens with Apple’s standard summary screen, leading with an ad talking about Apple TV+. The home screen is chock full of TV+ ads and ads for shows on TV+. If you have existing iTunes Store shows, or streaming apps like Netflix or Crunchyroll setup, you might see shows you’re watching under the “Up Next” section. But no matter what you have, the Apple TV+ ads are huge and inescapable. Again, the TV app’s notifications is enabled by default with no permission request.

Apple News+

ios adware apple news

Another app that has its notifications turned on by default, this is how many people will interact with this service. Tapping notifications doesn’t take you to a web browser, but directly into the News app. If you open a story on one of Apple’s partners like the Wall Street Journal, the screen it takes you often has a large banner ad at the top of the screen for the Apple News+ service. This seems to be intermittent, but it cannot be dismissed, hidden, or disabled.

If you look through the News app itself, you will see a plethora of stories in the Today feed. Some of these will trigger the same ad shown above; there is no indication on the feed itself. Some will actually have a full paywall in front of them preventing access without signing up; these do have a tiny Apple News+ logo beneath them, but it’s far enough below that it almost looks like it belongs to the next section.

And of course, in the dead center of the tab bar, is the News+ tab. Leading off with a large ad at the top of the feed, it lists stories and publications similar to the Today feed. Most of these stories are paywalled, but not all, so people may end up going there and hunting for stories they can read. This tab cannot be hidden, ever.

Apple Card

ios adware apple card

After you set up your iPhone, you get a home screen with at least one badged icon, on Wallet. Opening this takes you to a giant ad that’s nearly half the screen for Apple Card. Fortunately it is dismissable. But every time you try to add a credit/debit card to Apple Pay, you are asked if you want to sign up for Apple Card instead.

Apple Arcade

ios adware apple arcade

The first three tabs of the App Store app are Apps, Games, and Today. These tabs don’t have much in the way of ads, aside from some Apple Arcade games that might appear in Games and Today. However, Apple Arcade gets an entire tab all to itself, which has a huge in-feed ad for the service, and of course a whole pile of games advertising it. Compared to other games and apps, Apple Arcade games get more prominent visual treatment, larger videos, and bigger download buttons. This tab, like News+, cannot be turned off.

App Store Search

ios adware app store search

And of course, almost anything you search for in the App Store has a large ad at the top of your search results. This isn’t an ad for an Apple-run service, but it is a way they make money by extorting developers and showing you the wrong thing. If you search for a specific app, you will often not see that app in the first slot, unless the developer has paid for the privilege.

Conclusion

Apple wants to grow their services business with drastic increases year-over-year. This means they are going to aggressively push more services into more places (including deeper into macOS and tvOS, which are also slowly having adware trickled into them). Apple TV+, News+, Arcade, and Card are all new this year, and are already strongly advertised in iOS. Apple Music has existed for a few years, and its level of advertising in the app is pervasive. As time goes on, these ads are going to get worse, not better.

Of course, Apple has a right to tell users about their services, and try to convince you to subscribe to them. And you might disagree with my assessment that some of these are ads at all. Individually, most of these instances aren’t insidious by themselves. But when you look at them together, they paint a picture of how Apple is making the user experience provably worse to boost growth at all costs.

This issue is not going to get better. Apple is going to expand its services, both breadth and depth, and the adware problem is only going to get worse, unless people call out Apple for what they’re doing. And yet, this issue is rarely talked about, likely because many of the people who cover Apple inevitably subscribe to some or all of these services. Gadgets like smart TVs and ebook readers are frequently criticized for their annoying, invasive advertisements despite their (often large) upfront price. It’s time for the tech community to recognize that Apple is no longer designing their products for a great experience, but as upsells to get you into the paywalled garden.

One of my earliest memories of awe when learning how to program computers as a kid was wondering how the computer takes bits in the CPU and turns them into an image on a screen. When you don’t know how most of the system works, it’s easy to conclude that it is basically magic, and that the knowledge was arcane to the point of being inaccessible without tons of background in engineering and science.

As I grew up, this question never really left my mind, and really grew into the more abstract question of how a computer works at every level. Once you get into the high level of software and languages like C and Swift, you can abstract away a lot of the questions into programming language theory and ignore things like transistors and voltage. But peeling back the curtain to reveal what is going on in the circuitry lies a world that is both simple in its principles and ever complex in the myriad of tricks used to keep this wrangled chaos ticking in utter precision.

I started watching Ben Eater’s incredible YouTube series on building a computer on breadboards a couple years ago. I’ve watched the whole thing end-to-end multiple times, and have built (or tried) a couple of the modules, including the clock and the ALU. I went from knowing very little about electronics to having a fairly broad understanding of how circuits work, at least in theory.

On the other side, I’ve tried writing video game console emulators, notably a Game Boy emulator in Swift which works well enough to understand how a higher level system works with all its pieces put together. The emulator is largely unusable (hence why it doesn’t exist in an open source form) but it can run the start of a couple games, generate some graphics and sound, and process user input. Over the years I’d heard about things like Verilog and VHDL being used to define hardware in code. And in the last year or two I’ve gained an understanding of what FPGAs are (especially thanks to the MiSTer project and its focus on cycle-accurate emulation).

So in my ever expanding pursuit to learn how each piece of the computer works, I’ve picked up an FPGA development board, the DE10-Nano, and have begun using the Intel Quartus software to learn how to program it using Verilog. So far, I’ve gotten a couple small and ultra-basic projects working, namely getting an LED to blink based on an internal 50MHz clock and a clock divider, and a basic unclocked two-bit adder. As I continue going down this route, I have a number of project ideas I want to try, including:

  • emulating Ben Eater’s breadboard computer
  • a video generator that outputs something to HDMI
  • an analog to HDMI video converter and scaler, akin to the OSSC
  • an HDMI to analog video converter, so I can play PC games like Undertale on my old CRT TV
  • a Dreamcast VMU clone
  • a basic graphics card
  • a RISC-V CPU
  • some kind of module for my modular synthesizer

Will I be successful at actually building any of these? Who knows! But in the end, I’ll get a few steps closer to understanding how computers truly work at the silicon and chip level. And the journey is definitely more valuable than the destination.