The Boston Diaries

The ongoing saga of a programmer who doesn't live in Boston, nor does he even like Boston, but yet named his weblog/journal “The Boston Diaries.”

Go figure.

Friday, January 01, 2021

The upside is that 2020 is over—the downside is that COVID-19 is not over, murder hornets are a thing, and the election is still contentious

All I can say is—thank God it's Friday a new year!

HAPPY NEW YEAR!


The forced march of progress

When I first wrote the Lua module for libtls, I had issues with using TLS_API to version the code, so I ended up using using LIBRESSL_VERSION_NUMBER instead and mandating at least LibreSSL 2.3.0.

But now that I'm switching away from LibreSSL, I can't rely upon LIBRESSL_VERSION_NUMBER anymore. After some thought, I have decided to no longer support versions of libtls prior to 20180210 (or LibreSSL 2.7.0). The non-LibreSSL libtls versions I've found all seem to be newer than 20180210, so that shouldn't be much of a prooblem.

Saturday, January 02, 2021

When one IP address fails

I wrote my own gopher server several years ago. And it works fine for my own uses, But I could not load gopher://raymii.org/. I could use telnet (the gopher protocol is very easy to use by hand). I could use nc. But my client could not connect.

I finally dived into the problem and I found the issue—not all the addresses for raymii.org work! My code would call getaddrinfo(), which returns a list of addresses, and my code would just use the first one returned. Only in the case for raymii.org not all the addresses accept connections. And that's an issue that I've never encountered before.

The fix was easy—attempt to connect to each address and return when the first one connects.

Wednesday, January 06, 2021

It's finally the Twelfth Day of Christmas!

By the Twelfth Day of Christmas, my true love has gifted me:

I now have here 140 people, 34 of which are playing loudly, 66 are prancing about loudly, and 40 complaining that the noise is making it difficult to milk their cows. Speaking of which, there are 40 cows milling about constantly mooing, and making such a mess on the floor. There are 184 birds flying about, honking, calling, cooing and otherwise making more of a mess on everything but the floor, to the point where it's wise not to eat the pears without a thorough cleaning (and possibly peeling). The 40 golden rings aren't quite enough to make up financially for all the damage caused so far.

I think next year I'll just ask for a pair of socks.

Friday, January 08, 2021

Notes about the first time I tried a S'more

For some unknown reason, Bunny came into The Computer Room with a S'more in hand for me. This was my first experience with a S'more.

“Um, did you slay the Stay Puft mashmallow man?” I asked.

“Okay,” said Bunny, “the marshmallows were kind of big. Do you like it?”

“Like it? I can't even get a hold of it.”

“Would a fork help?”

“Wait a second,” I said. “Let me flip the plat over and see if I can get it that way … ”

“Wow! That marshmallow sure is sticky stuff.”

“There we go.”

“Do you like it?”

“Mmmmm mm'm mmmm.”

“Pardon?”

“Iths okay. Messy, but okay.”

“So it didn't knock your socks off?”

“I'm not wearing socks, but yes, if I was wearing them, this wouldn't knock them off.”

“Oh.”

“It's okay. A bit too sweet for me, but I don't hate it.”

“But at least you tried it.”

“Yes,” I said. “At least I tried it.”

Tuesday, February 16, 2021

Today was not a good day

I walked into the Computer Room at Chez Boca to a pair of unpowered computers and a UPS that was turned off. Okay, perhaps a brownout of something and the squeal got to Bunny so she did as I instructed and just turned off the UPS. I went to turn it back on and … nothing. It did not turn on.

That was not good.

But even though the UPS might not turn on, the “surge protection” side might still work until I get a replacement. The Apple Mac I have turned on, no issues. The Linux box, my main development system, did not.

That was even less good.

Okay, perhaps it's too much draw for a nearly dead UPS. Next step, a replacement UPS from Best Buy.

“Yes, can I help you?”

“Yes, where are the UPSes?”

“The back wall over there to the left, with the car stuff.”

Odd, but … “Okay, thanks.”

Nope, just car stuff over by the back left wall. I corner a clerk and ask again.

“Where are the UPSes?”

“The what?”

“A UPS.”

“A …?”

UPS. You plug the computer into it, then plug that into the wall.”

“Oh! A battery backup!”

“Oh, is that what you young hipters are calling UPSes these days?”

Pricy, but I have a new UPS.

The illustrations didn't indicate that you had to connect the black wire to the battery before the red wire to the battery, but perhaps I should have known that prior to learning the hard way with a large pop. Fortunately, no magic smoke was released, and when I plugged the UPS into the wall outlet, it seemed to be fine.

I plugged in the Linux box and … it still didn't come on.

XXXXX­XXXXX!

I wasn't terribly upset—I do have backups and even if the computer died, the harddrive could still work on a new machine. It was just the severe inconvenience of it all.

I then recalled a weird premonition I had last night. The weather forcast for today was thunderstorms, and I had a notion to shut the computer down “just in case.” But I thought better of that—after all, the UPS should be good, right?

Ha ha.

It was then I received the news about Uncle Dale.


Uncle Dale

I found out today that my Uncle Dale died.

Much like with Undle Ed, it's mixed news—sad that he is no longer here, but relieved since he too, was suffering from a neurological disease for years (but a different one from Uncle Ed).

Dale married my Dad's sister Kay, and they lived about two miles from my grandparents house, so I spent a lot of time there as well. And what really stood out about their house was not the garage, but this giant black walnut tree in the backyard that made running around in your barefeet a rather dangerous endevour (the walnuts would fall and slowly decompose into the ground, making for a very bumpy backyard). This was a thing because of the pool they had in the backyard, a rare thing indeed in Michigan.

But what really stood out to me about Dale, aside from Dale himself (being I think 6′2″ or 6′4″) was his love of family and sailing. Every year he and the rest of his family would drive up to Higgins Lake with catamaran in tow. I do recall riding it once, only because I wasn't into the whole “family camping thang” he and his family did every year (roughing it for me is the lack of A/C in the hotel room).

He also taught me how to ride a bike. I was probably seven or eight at the time and Dale took it upon himself to teach me how to ride in the most effective way he knew how—by placing me on a bike on the sidewalk in from of the house (which ran parallel to a 4-lane road) and shoving hard. All I had to do was keep upright and avoid falling into traffic, the large blue mailbox or the utility poles. I learned how to ride a bike in three days.

Effective … yes. Safe? Probably not.

But I did learn quickly.

So here's to Uncle Dale. And much love to Aunt Kay, and my cousins Joshua, Aaron, Jordan, Caitlin and Ethan.

Wednesday, February 17, 2021

But not enough atmosphere to actually stop

I'm feeling a bit better after the events of yesterday.

Now, seeing how the Perseverance Mars rover is expected to land tomorrow, I present “Seven Minutes of Terror”—yes, that video is about the Curiosity Mars rover landing, but they're using the same method for Perseverance, an insane method involving parachutes, rockets, and a crane.

Insane, I tell you. Insane.

Monday, February 22, 2021

Lightsabers and Pitfall!

My hetero life mate Hoade finally got around to mailing my Christmas birthday Valentine's Day gift, and I must say, much fun. The first item in the package was the Activision Flashback Blast gaming system, an Atari 2600 in a modern game controller (technically, the games are stored in the HDMI interface that the game controller connects to), and of the twenty games included, I've only heard of half of them, the standout one being Pitfall! The one standout game I never heard of (and by “standout” I mean “WTF was Activision thinking?”) is Crackpots, a kind of reverse Space Invaders, but instead of bug-eyed aliens marching down towards you, it's actual bugs crawling up towards you. Interesting take on the genre, but still a WTF moment the first time I played it.

In fact, not having instructions makes these game all the more fun. Back in high school and through college, my friend Bill and I would often … um … aquire … games and attempt to play them without knowing how to play. I still recall playing Barbarian: The Ultimate Warrior with Bill and both of us falling over laughing when suddenly and rather unexpectedly, one of us somehow managed to chop the head off the other player.

The other gift Hoade sent was a “Lightsaber™ Ice Pop Maker.” A kit of four small lightsabers (two modelled after Darth Vader's saber, and two moddeled after Luke Skywalker's second, green lightsaber) and a mold to make four pops at a time.

[My hand, holding up a Darth Vader Lightsaber™ Ice Pop that isn't quite lit up all the way] “I find your lack of lightsaber … disturbing!”

As a test, we used cranberry juice for two of them (one for Darth's, one for Luke's—just to see how the green LED interacts with the red cranberry juice) and ginger ale for the other two. I'm not sure if we left them in the freezer long enough, because the first two I attemped to pull out broke apart. The third one came out (after running hot water over the mold) but Bunny and I learned that we should have used flat ginger ale—the carbonation caused large pits in the “light” portion of the lightsaber. And as you can see in the image above, the light doesn't quite go all the way through.

We have ideas for other attempts.

Anyway, I want to thank Hoade for the gifts. They were much appreciated and caused some great merriment here in Chez Boca.

Wednesday, February 24, 2021

4

I have a Gmail account that I don't use for anything other than

  1. having claimed seanconner@gmail.com as an email address;
  2. seeing what spam Google lets through its famed “spam filtering process” (hint: quite a bit actually, and I suspect Google gets paid to deliver it);
  3. seeing email for other Sean Conners who's friends/family don't know that seanconner@gmail.com doesn't go to the Sean Conner they know.

That last category is just a by-product of getting in early enough with Gmail, and after all this time, I'm still surprised at receiving email addressed to other Sean Conners (latest one: a betting pool to see when a pile of snow known as “Mt. Pfeiffer” will melt completely away).

So I load Gmail today and get:

We’re sorry, but your account is temporarily unavailable. We apologize for the inconvenience and suggest trying again in a few minutes. You can view the Google Workspace Status Dashboard for the current status of the service.

If the issue persists, please visit the Help Center »

Try Again Sign Out

Show Detailed Technical Info

And when I clicked on “Show Detailed Technical Info” I got “Numeric Code: 4”.

Woo hoo!

Way to go, Google! Wonderful technical detail! That helped a lot!

Tuesday, March 09, 2021

Christmas in March—The Clockwork Gift

On Christmas, one of the gifts I received from Bunny was a small flat box, about 7″ by 7″ and an inch thick—perhaps a CD, but it was no CD. No, there was a small grey pouch with a clock winding key, and two pictures of a grandfather clock (technically, a “grandmother clock” as it's not quite 6′ (2m) in height; both are a type of “longcase clock”).

“It's currently being restored,” said Bunny. “So sorry it's not here in person.”

“Wow!” I said. “It looks just like the one I had as a kid!” Yes, it's true. I was the only kid I knew in high school with a longcase clock in their room. It belonged to my maternal grandparents. When my grandfather died and my grandmother moved in, the clock came with her. My Mom wasn't all that keen on clock, what with all the constant ticking. I, on the other hand, loved it. I did not mind the ticking at all (and that probably explains why I don't mind using the IBM Model M keyboard).

After my Mom died, my uncle (Mom's brother) came down to help move his mother to live with him, and he ended up taking the clock as well. Sigh.

Bunny knows I have a thing for grandfather clocks, as I tend to fawn over them when we're antique window shopping. So it's wonderful that she decided to get me one for Christmas, even though it wasn't here on Christmas.

Josef & Joseph certainly took their time with the restoration, but they wanted to make sure not only it worked, but it worked flawlessly! It finally arrived at Chez Boca today.

[A grandmother clock from Colonial Mfc. Co.] I'll take this tick tock over TikTok any day.

Oh, there were plenty of logistics in getting it home. And way more in getting it set up, spending way over an hour getting various shims under the feet of the clock to get it level. It turns out that even out by 1° from true will eventually bring the pendulum to a stop, and the chimes won't always strike true.

So now it's quietly ticking away (and it's not nearly as loud as one would expect), keeping time quite nicely. It's a nice feeling to know I'll have a time-keeping piece that will survive the next Carrington Event.

Wednesday, March 10, 2021

Notes on an overheard conversation while passing by a building

“Oh! That building is so hideous! It's … what? Monstrous?”

Brutalist.”

“That's it! Brutalism!”

“But it's not quite Brutalism.”

“No, this building has windows.”

Thursday, March 11, 2021

Place your bets!

I just checked my Gmail account and I received an update on the Mt. Pfeiffer situation five days ago—apparently it is still melting so I guess there's still time to place a bet as to when it will ment completely away.

There's also about 50 recipients to that email, and I'm wondering if I'm supposed to be related to the other four Conner's who received this email. I supposed I should notify the sender, especially given this disclaimer at the bottom of the email:

This message is intended only for the use of the addressee(s) and may contain information that is PRIVILEGED and CONFIDENTIAL. If you are not the intended recipient(s), you are hereby notified that any dissemination of this communication is strictly prohibited.

If you have received this communication in error, please erase all copies of the message and its attachments and notify us immediately.

Your email address and contact information will be stored within XXX's Customer Relationship Management platforms (CRM) and Communication Management Systems and may be used by XXX for lawful business purposes. XXX does not share or sell your contact information. Details about how we use your information and your rights are contained within our Privacy Policy (click here to view our Privacy Policy).

But if I notify the sender of their mistake, I won't get closure! I'm now emotionally attached to Mt. Pfeiffer's fate! Oh the dilemma!

Wednesday, March 17, 2021

Is there a reason for an indulgence of lepcrechauns on the front lawn? And who replaced the grass with clover?

I'm in the Computer Room. Bunny is in the family room watching TV. I suddenly hear a tune that sounds eerily familiar—I know this music! It's from a TV show, but I can't remember which one. I rush out, only to find it's a commercial using the music.

Darn!

But it's so familiar! I grab my phone and fire up Shazam. “Excuse me,” I say, as I grab the remote from Bunny to rewind and watch the commercial over again. Shazam listens, and then says “Dave Allen At Large.”

That's it!

Dave Allen was an Irish commedian and my friend Bill and I would watch his TV show when we were in high school. I haven't thought about him or his TV show in years! And yet for some odd reason, I was reminded of him today.

I wonder if it has anything to do with the lepcrehauns on the lawn?

Oh, I've got to go—dinner is ready, corned beef and cabbage—wait a minute …

Thursday, March 18, 2021

Leave it to the phone companies to make simple ideas complex

These telephone DNS records are typically expected to contain a record with the type NAPTR. NAPTR, generally speaking, is intended to map addresses (more properly URNs) to other types of addresses. For example, E.164 to SIP. So the NAPTR record, typically, would provide an address type of E2U+sip which indicates ENUM (E.164 number mapping) to the SIP protocol.

Fascinatingly, the actual payload of an NAPTR record is… a regular expression. The regular expression specifies a transformation (with capture groups and the whole nine yards) from the original address (the E.164 number) to the new address type. In theory, this allows optimization of NAPTR records at higher levels of the hierarchy if components of the original address are also used in the new address. This is one of many areas of DNS that are trying perhaps too hard to be clever.

Computers Are Bad: can I get your number domain

I'm very surprised I haven't mentioned NAPTR records before, because I have to deal with them at The Corporation. The service we provide to our customers, the Oligarchic Cell Phone Companies, is to translate a phone number, such as “867-5309” to “Jenny,” and that is done via DNS using NAPTR records. I was surprised at first, because I was expecting the Oligarchic Cell Phone Companies to use some esoteric and proprietary protocol to handle such information, but nope—it's via DNS. One complication here is that each phone company keeps its own database of numbers to names, and you have to negotiate with, and more importantly, pay, each one to query their data. Now, because The Corporation has all these contracts in place, all an Oligarchic Cell Phone Company has to do is pay us to get access to the name databases of the other Oligarchic Cell Phone Companies.

A classic middleman situation here.

But getting back to the article. The author uses the example +18002662278 as an example of an E.164 global number (where E.164 is a standard from ITU), but the example is a bad one, because 800 numbers are not global numbers! You can only dial 800 numbers from North America, so to present +18002662278 as a global number is incorrect. This is an issue for us, because Project: Sippy-Cup has to deal with both global and “local” numbers (where “local” means—intra-country code calling). and yes, we get a ton of 800 numbers sent in as global numbers (then again, we get an amazing assortment of garbage numbers from the Oligarchic Cell Phone Companies, including all zeros, all ones, numbers with international dialing prefixes, short codes, service codes, and it wouldn't surprise me if we get ZIP codes from time to time—you'd think the Oligarchic Cell Phone Companies would filter out such garbage, but hey, they're the Oligarchic Cell Phone Companies, they don't have to care).

I also agree with the author about the use of regular expressions in the NAPTR record. It complicates the spec and in the decade I've been working at The Corporation, I've yet to see anyone use the regular expression transformation, and in the source code parse NAPTR records is this comment from the original developer: “Skip the insanely stupid regexp pattern; we are ignoring it.”

The name lookups are not using the “E2U+sip” addressing, but “E2U+pstndata:cnam” addressing, based off a draft standard from twelve years ago. And reading that specification is a hoot in the light of the harsh reality of … um … reality. It defines the pstndata: scheme as:

pstndatauri  = "pstndata:" datatype ["/" telephone-
subscriber ] ";" content
datatype     = "cnam"
             ; Other datatypes can be defined by adding
             ; alternative values.
content      = [ mediatype ] [ ":base64" ] "," data
mediatype    = [ type "/" subtype ] *( ";" parameter )
data         = *urlchar
parameter    = attribute "=" value

where "telephone-subscriber" is imported from RFC 3966
[19], "urlchar" is imported from RFC 2396 [20], and
"attribute" and "value" are imported from RFC 2045 [21].

LIES! ALL LIES!

Okay, it's not quite that bad, but having dealt with all three RFCs mentioned, I'm not sure the author of the specification carefully read the them, or considered deeply how they might interact. The definition of telephone-subscriber contains not only the “phone number” but also parameters separated by semicolons! I have code to parse telephone-subscriber but I can't use it here because in reality, it conflicts with this definition (why yes, the whole notion of parsing this data came up recently at work, why do you ask?) It's always fun when reality trumps theory (no, not really).

So as the author states, “DNS does handle phone numbers!” But it's not quite as simple as IP addresses.

Tuesday, April 27, 2021

A quick note about the GNU Debugger

Just a quick note here—you can still debug a program using gdb if the debug information exists in the executable, even if gdb doesn't have access to the source files. It will still print out filenames and line numbers, and you can still examine the contents of variables. I just spent an hour with TS debugging an issue with “Project: Lumbergh” on our lab machines, running gdb in one terminal, and an editor in a second terminal following the files and line numbers given by gdb.

Not quite the optimum experience, but at least it was doable.

I'm also not sure what it says about “Project: Lumbergh” that the issue turned out to be a configuration issue—the configuration was legal at one time, but not with a newer version of the code. I think the codebase is slowly turning into a big ball of mud.

Friday, April 30, 2021

An update on the enterprise time tracking system the Corporate Overlords make us use

I fill in my time card once a week. I've finally convinced myself not to be annoyed by The Process because they pay me to waste my time with a less-than-fast input process. But the latest wrinkle in The Process is logging in. Each time, I get the “Remember this computer” option once I log in, and each time, I hit “Remember this computer.” I don't know if it's the site itself, or the Windows laptop I have to use being so locked down I can't change anything, but the site never remembers the computer, and every week, I get an email from the time tracking system that it registered a “new login” from an unknown computer and that if it wasn't me, contact the IT desk blah blah.

Every-freaking-time!

And here I thought computers were supposed to make our lives easier …

Saturday, May 01, 2021

What I did on my April vacation from the blog

It's been awhile since I last posted (never mind the previous posts—those were actually written today but pre-dated to earlier in the week because I'm lazy). Back in the last week of March, my hosting company changed data centers and because of “technical issues” the IP address my server has had for the past … um … 13 years? 15 years? A long time in any case, the IP address of my server has changed. I was a bit aprehensive about the change because of email (I'm going from a very clean IP address to an address of unknown provenance) and of course I had an email issue—but it wasn't with Gmail, oddly enough, but with Bunny's email provider (the Monopolistic Phone Company).

Sigh, here I am, unable to email a person that is 20 feet away from me! The horror!

All I got was that my IP address was on some realtime black list somewhere. Which one, I had no idea, because the Monopolistic Phone Company was mum on which list they use. I tried querying over 800 different black lists and only found one that listed my IP address—in Brazil! I find it odd that the Monopolistic Phone Company was using a realtime black list from Brazil, but hey, you never know.

It took a month, but now my emails get through the Monopolistic Phone Company's servers, and right into Bunny's junk folder. Progress!

There was also the DNS issues that took about a week to clear up. As part of the move, my hosting company's DNS servers were also changing IP addresses, and those had to be updated with the hosting company's registar which took some time to clear up.

But as of now, things seem to be back to normal around here.


An update on the Mt. Pfeiffer situation

Just in case anyone was interested in the Mt. Pfeiffer situation, I have to inform you that it had melted completely away by 8:45PM Eastern, March 18TH, with Aunt Betty TXXXXX winning the pool with a guess of 4:15PM Eastern.

I should note that I have no Aunt Betty and have no idea who she is. But hey, I'm happy she won the betting pool!


Extreme car alarm system, Delray Beach edition

In the parking lot of The Girls Strawberry U-Pick Ice Cream Shop and Animal Petting Farm (no, really! It's all that and more in the middle of some suburban sprawl—we went for the ice cream and were quite impressed) Bunny and I saw this angry pig in the windshield of a nearby parked car.

[A toy stuffed pig in the windshield of a parked car, looking mighty angry] “Come on!  Just a few steps closer!  I dare ya!  Just come another step closer …”

I guess pigs are this year's trunk monkey.

Wednesday, May 05, 2021

The unmasking of a numbers station

It only took a little over fourteen years but finally someone wrote to me about my numbers station on the web.

From
XXXXX­XXXXX­XXX
To
rparker@numbersstation.info, sean@conman.org
Subject
Re: Leaderboard
Date
Thu, 06 May 2021 00:48:42 +0100

Hello, Sean,

I'm not sure how your mail server is set up for "rparker", but I've successfully found your main page, so I'll copy the message I've sent to this fictional character :)

On 2021-05-05 18:30, jonn@doma.dev wrote:

Hello, rparker!
Learned from numbersstation from SMOG mag [This is a now defunct on-line zine and referenced the Gemini version of the site. –Sean].

Only today figured I should check out the HTTP version and got some hints like the fact that it _is_ a challenge (thanks for "mystery" keyword!), this E-Mail address and COORDINATES!

I wonder how many people have reached out to you with the answer to the mystery, are there more puzzles to come and if so, is there some sort of leaderboard?

Great job, BTW, interesting stuff right there. I tried to make my own ARG some ten years ago, but it didn't go way past stegging a torrent file into a PNG.

Looking forward to your response,
kindest regards,
jonn.

I don't want to give away any clues, but the coordinates spoken of in the web page are not part of the puzzle—they just point to some random spot in Boca Raton (and I've changed them to point less randomly at Boca Raton). The email address rparker@numbersstation.info was picked to mask my identity (and was an intentional choice, that's all I'll say about that). And aside from that one post fourteen years ago, it is also listed on my projects page, so it's not like it was completely hidden.

Now I'm just curious if anyone can decode the message.

Friday, May 07, 2021

Extreme lawn ornaments, Boca Raton edition

Who knew Brevard was such a trend setting place? Who knew cow lawn ornaments are a thing now, in Boca Raton of all places?

[A life-sized plastic cow munching on astroturf] “Don't hate me because I'm a trend-setter.”

Tuesday, May 11, 2021

Notes on an overheard conversation at a restaurant with the TV turned to a tennis match

“Oh come on! Just serve the ball already! This is like watching a pitcher!”

“What?”

“Look at her! Bouncing the ball up and down like that. It's like watching a baseball pitcher!”

“Pitching isn't easy. Both leagues will now have designated hitters for their pitchers.”

“Really?”

“Really.”

“Why not have designated hitters for other positions?”

“What?”

“Yeah, a designated hitter for the catcher, first baseman, short stop …”

“They change catchers all the time.”

“Like they don't change pitchers?”

“Look, pitching is a specialized art. You don't want them getting hurt while batting. Just the other day one got hit bad with a baseball.”

“So anyone can be the catcher then?”

“Well … no … ”

“So why not designated hitters for catchers?”

“Because … ”

“Well?”

“Shut up!”


Extreme statuary, Delray Beach Edition

Bunny and I stopped at The Girls Strawberry U-Pick Ice Creme Shop and Animal Petting Farm again (don't judge us! You'd do the same!) and this time we took a stroll out back of the shop. While one should always be wary of the Spanish Inquisition I did not expect this:

[A human-sized statue of an Easter Island moai.] “What?  You expect me to say something like ‘Ooom poppa chikamaga wana sing gow / Do lomma sinnigama mana ching jow / Inimana choogamaga wana sing gee / Finimana foonimana one is now free?’  Wrong culture dude!”

It was a lot smaller than I expected. And you can buy these things? How expsensive was it to ship it all the way from Easter Island?

Wednesday, May 12, 2021

What's in a name?

I was watching this video on a 400 year old recipe for buttered beere when a word was used in an unusual context: “conner.” Or rather, “ale conner,” in the context of an official checking the purity of the beer. Curious, I decided to break out my copy of the Oxford English Dictionary (the compact edition, two oversized 2,000 page tomes) and sure enough:

Conner1 … [OE. cunnere, agent-n. from cunninan, ME. CUN to prove, try, examine. … ] One who tries, tests, or examines; an examiner, inspector; esp. in ALE-CONNER. q.v.

Huh. Well, let's q.v. then …

Aleconner … [f. ALE + CONNER, OE. cunnere a trier.] An examiner or inspector of ale: ‘An officer appointed in every court-leet, and sworn to look to the assize and goodness of bread, ale, and beer, sold within the jurisdiction of the leet.’ Philips 1706. ‘Four of them are chosen annually by the common-hall of the city; and whatever might be their use formerly, their places are now regarded only as sinecures for decayed citizens.’ Johnson 1755. Still a titular office in some burghs.

And there are usages going back to 1350.

1350!

Interesting … I come from a family of bureaucratic inspectors. Or maybe not … there's this definition:

Conner2 … One who cons or diligently studies. 1809 W. Irving … A great conner of indexes.

A conman or a scholar. Huh … given the current science replication crisis both meanings could equally apply here. I guess my choice of domain is more appropriate than I thought.

Wednesday, June 02, 2021

The point of writing software seems to be writing tests for the software, not in running the software

I've been stuck in testing hell the past few weeks, what with the changing of the old guard, and the new guards crew are heavy into the whole “unit test über alles” religion. I understand the reason behind testing, and unit testing in particular. The few times I've tried unit testing, it has been helpful, but …

  1. I think it works best when you start out with unit testing in mind;
  2. it works best with a module or library;
  3. you test at the boundary of the module or library and not the implementation;
  4. you do have tests for your tests, right?

That last bit might sound a bit glib, but it is a real concern. Even Knuth is quoted as saying, “beware of bugs in the above code; I have only proved it correct, not tried it.” I even joked about having to test our tests with both my current (but soon-to-retire) manager and his (soon-to-me-my) manager, because our current regression test has 15,852 individual tests (not all of them might be valid—hard to say, since the tests are automatically generated).

Project: Lumbergh” was not written with unit tests in mind. Or more specifically, it is a unit. The whole thing. And it's complicated because not only does it implement our business logic (which over ten years has gotten quite complex) but because it has to query multiple databases at the same time across the network (“at the same time” because it has to do its job as a phone call is being made). How does one deterministically test delayed (and/or dropped) queries?

Another issue—“Project: Lumbergh” sends a message to “Project: Cleese” in some circumstances (“Project: Cleese” handles an HTTP notification on behalf of “Project: Lumbergh” because trying to add a TCP connection in a program that deals with UDP would have taken too much engineering time) and we need to check if “Project: Cleese” was notified. I solved that one by mocking the HTTP endpoint that “Project: Cleese” talks to with two interfaces, one for “Project: Cleese” and one for the regression test to query. The issue there is the regression test might ask the mock if it received a request from “Project: Cleese” before “Project: Cleese” gets the notification from “Project: Lumbergh” (a classic race condition). I got it working reliably, but now the regression tests takes over twenty minutes to run, instead of the two-plus minutes (even on the happy path, and I'm not entirely sure why).

It seems like management is more concerned about the tests rather than the product.

Friday, June 04, 2021

Alas, the Optimus Maximus keyboard was more about aesthetics than usability

As much as I wanted the Optimus Maximus, the price of $1,600.00 kept me from buying one, which according to this review was a Good Thing™ (and that Youtube channel is nothing but keyboard reviews—amazing!).

Monday, June 07, 2021

The little details you don't think about when playing D&D

I've been meaning to post this for quite a while, but I've been lax in doing so. Anyway, for my D&D buddies a few videos: one that asks the age old question, “can you go to the toilet in medieval armor?” The second one covers misconceptions about inns, accommodations and taverns in medieval times. These are interesting, but I'm not sure if I'm going to do that level of detail when running my “every-two-week” D&D game.

This last video is mind blowing (at least to me)—fast food in ancient Rome. It's odd to think that “fast food” is as old as Rome—MCROMVLVS anyone? But yes, Roman Empire fast food.


Inconceivable!

Wlofie, via Me­Linked­Insta­My­Face­Book­We­In­Gram­Space, sent me to A Mind is Born, a 2½ minute demo program (a program that display some mind-blowing graphics and music) done on the Commodore 64. The impressive thing here isn't that it's done on the C-64, nor the graphics, nor the music, but that he did all that in less than 256 bytes!

For reference, the above paragraph is 351 bytes in size (or 521 if you include the HTML markup). That is inconceivable to me that one can even do something like that with so little.

Inconveivable!


We had to leave it with an agreement to disagree on the details for the time being

There is definitely a culture clash at work with regard to testing. I was involved with a four hour discussion about our current regression test with the newer members to the department. The new manager, AG, was saying the regression test should test all the paths in the code. I was saying, yes, that is possible, but many of the new tests would slow the regression test down to a crawl. Then CZ would chime in saying it should be possible to test without slowing down to a crawl. Both AG and I countered that some of the tests involve a timeout, because how would one otherwise test a negative? CZ said we could check the logs, since the logs are logged in a particular order, but I countered that our previous regression test (which runs with the Protocol Stack From Hell) takes over five hours because it checks the logs to ensure we don't miss a log. Using the logs to check to see if something happened isn't deterministic, because the check might come before the action is even logged, and you are still trying to test a negative (in this case, something that should not happen, did not happen, across a distributed, multi-process system) and that slows down the regression test.

We had to leave it with an agreement to disagree on the details for the time being.

Also discussed was a reversion of code in “Project: Lumbergh.” I felt the reversion reverted too much and involved parts that weren't part of “Project: Lumbergh.” CZ felt that was fine, because the changes to the other parts were a part of “Project: Lumbergh” if only indirectly. I countered that in that case, he should have reverted the changes in a different repository that the regression test lives in because that too, indirectly relates to “Project: Lumbergh.” CZ said no, it's in a different repository and thus, shouldn't be reverted. I retorted that the changes he reverted weren't part of “Project: Lumbergh” directly, just as the regression test isn't part of “Project: Lumbergh” directly, and it's only a historical artifact of how our stuff was developed that “Project: Lumbergh,” “Project: Wolowizard,” and “ Project: Clean-Socks” (plus a few others I haven't mentioned) all share a single repository, and that our other repository contains “Project: Sippy-Cup,” “Project: Cleese,” “Project: Seymore” and our current regression test.

We had to leave it with an agreement to disagree on the details for the time being.

Also related to the repositories, we also had a discussion about the versioning software we use. I mentioned I prefer git but we're stuck with SVN for the moment, with the only thing I like about SVN is the ability to checkout a subdirectory in a repository—it's certainly not because branches are easy, or SVN tags make any sense to me. CZ likes SVN for it's ability to easily branch and tags and hates git, except for git's ability to stash files (we still haven't moved from SVN to git).

We had to leave it with an agreement to disagree on the details for the time being.

I have a feeling this is going to be a rough few months.

Tuesday, June 08, 2021

So I wonder—are there unit tests for the various unit test frameworks out there? How are they tested?

Still writing tests. I added checks to see if something that's not supposed to happen didn't happen and I'm only running it over the tests that may actually do the thing that's not supposed to happen (3,456 tests). Doing so adds three seconds of overhead to each test … multiply … carry the one … and hey! Only three hours to run this test run! And oh look! It found something that wasn't supposed to happen did happen!

It's going to be fun reporting at the next meeting that running the full regression test will now take over 13 hours. I'm thinking I'll be tasked with coming up with a different approach to the regression test.

Remember kids! Tests are more important than the program! Testing! Über alles!

Update on Wednesday, June 9th, 2021

Hmmm … it took 259 minutes, 57.5 seconds (4 hours, 20 minutes) to run through the 3,456 tests, so each test took around 4½ seconds, not 3 seconds. Things aren't looking so good for this regression test …

Wednesday, June 09, 2021

You know, walking into Mordor might be simple after all

Yesterday, I said the full regression test might take over 13 hours. In light of the results of running just a partial test, it turns out the full regression test will take over 19 hours! The jokes on me though—when I said it would "be fun reporting at the next meeting" I wasn't expecting my new manager to double down on the regression test. Seriously, he asked “Can you run it in parallel?”

Words fail.


“The job of a programmer is to produce test cases.”

So last night I ran a subset of the regression test in 4½ hours and got a few errors where something that shouldn't happen, happened (and it's this “checking for not an event happening” that takes the time). Well, it wasn't a bug in the code being tested, but a bug in the regression test (Surprise! Surprise! Surprise! Only not really). I think that says more about our business logic than it does about CZ or me; both of us attempted to validate this part of the business logic in the regression test, and we both got it wrong.


And about parallelizing the regression testyes, it's possible. But doing so on the spot isn't. The easy solution is to run the regression test on multiple machines—nice if you have them. The other option is to parallelize the run on a single machine and the code just isn't set up to do that. I'm not saying it's impossible, but it will take engineering effort, and more importantly, testing! Funny how testing your test cases isn't talked about that much.


The slowdown of the regression test is due to “proving a negative”—that is, checking for something that's not supposed to happen did not happen. And in a distributed system like ours, that's not easy to test—a check could happen before the event due to any number of reasons, and how long do you wait to ensure that what shouldn't happen didn't happen?

The other issue to why it will take so long to run is just the sheer number of tests that are run. My “retiring any day now” manager has never been happy with the “shotgun” approach I took to generating the tests—I basically generate thousands of combinations of conditions, most of which “should” never appear in production. But one of those “should never happen” things did happen about seven years ago and well, the less said about that the better. So at least my “shotgun” approach does have the effect of testing for a lot of “I don't know” conditions (most of which are misconfigurations of data from provisioning). And each test we add could potentially double the number of tests cases. I'm sure there's a way to reduce the number of test cases, but to the TDD acolytes out there (and the new management team does appear to follow TDD tenents), “one does not simply reduce the number of test cases.”

Sigh.

And the regression test rolls on …

Thursday, June 10, 2021

Just more grumblings about testing while sitting on a deployment

It's 2:17 am as I'm typing this, sitting on a phone bridge during a deployment of the new “Project: Lumbergh” and I'm glad to know that I'm not the only one with a clicky keyboard. My comment about it brought forth a brief conversation about mechanical key switches, but it was short lived as the production kept rolling out. It's sounding a bit like mission control at NASA. So while I'm waiting until I need to answer a question (happened a few times so far), I thought I might go into some detail about my recent rants about testing.

It's not that I'm against testing, or even writing test cases. I think I'm still coming to grips with the (to me) recent hard push for testing über alles in our department. The code was never set up for unit testing, and for some of the harder tests, like database B returning results before database A, we did manual testing, because it's hard to set such a test up automatically. I mean, who programs an option to delay responses in a database?

It's especially hard because “Project: Lumbergh” maintains a heartbeat (a known query) to ensure the database is still online. Introducing a delay via the network will trip the heartbeat monitor, taking that particular database out of query rotation and thus, defeating the purpose of the test! I did end up writing my own database endpoint (the databases in question talk DNS) and added an option to delay the non-heartbeat queries. But to support automatic testing, I now have to add some way to dynamically tell the mocked database endpoint to delay this query, but not that query. And in keeping with the theme, that's yet more testing, for something that customers will never see!

Then there's the whole “checking to ensure something that shouldn't happen, didn't happen” thing. To me, it feels like proving a negative. How long do we wait until we're sure it didn't happen? Is such activity worth the engineering effort? I suspect the answer from management is “yes” given the push to Test All The Things™, but at times it feels as if the tests themselves are more important than the product.

I'm also skeptical about TDD in general. There's this series of using TDD in writing a sudoku solver:

  1. OK, Sudoku
  2. Moving On With Sudoku
  3. Sudoku: Learning, Thinking and Doing Something About It
  4. Sudoku 4: Disaster Narrowly Averted
  5. Sudoku 5: Objects Begin to Emerge

Reading through it, it does appear to be a rather weak attempt at satire of TDD that just ends after five entries. But NO!—this is from Ron Jeffries, one of the founders of Extreme Programming and an original signer of the Manifesto for Agile Software Development. If he gave up on TDD for this example, why is TDD still a thing? In fact, in looking over the Manifesto for Agile Software Development, the first tenent is: Individuals and interactions over processes and tools. But this “testing über alles” appears to be nothing but processes and tools. Am I missing something?

And the deployment goes on …


“99 failing tests in the queue! 99 failing tests! Check one out, grind it out, 98 failing tests in the queue!”

So I'm facing this nearly twenty-hour long regression test and I had this idea—instead of querying the mocked end point if it did its thing or not, have the mocked endpoint check to see if it did its thing or not.

I now send the mocked endpoint the testcase itself (along with a query flag of true or false). The mocked endpoint will save this information, and set a queried flag for this testcase to false. If it is queried, it updates the queried flag for the given request. At the end of the regression test (and I pause for a few extra seconds to let any pending requests to hopefully finish), the mocked endpoint will then go through the list of all the testcases it was told about, and check to see if the query flag and queried flag match—if not, it logs an error.

Sure, now we have two error logs to check, but I think that's better than waiting nearly twenty hours for results.

I got a baseline time for the subset of the regression test without the mock checks—35 seconds. I'm trying to beat a time of 4 hours, 30 minutes with the mock checks.

The new method ran the subset in 40 seconds. The entirety of the regression test, 15,852 tests, took just a few minutes—about the same as before.

I can live with that.

Now all that's left is to write the validation logic—I still don't have it down yet.


Just adding a bit more fuel to the dumpster fire

The idea of the scrum framework is to organize a development process to move through the different project cycles faster. But does it always incentivize the right behaviours doing so? Many of the users who joined the debate around the question on Stack Overflow have similar stories of how developers take shortcuts, get distracted by their ticket high score, or even feign productivity for managers. How can one avoid these pitfalls?

That the question has been migrated from our workplace exchange to the software engineering one shows that developers consider concerns about scrum and its effectiveness larger than the standard software development lifecycle; they feel its effect on their workplace as a whole. User Qiulang makes a bold claim in their question: Scrum is turning good developers into average ones.

Could that be true?

Via Comment at Hacker News, Does scrum ruin great engineers or are you doing it wrong? - Stack Overflow Blog

Despite Betteridge's Law of headlines I'm inclined to answer “yes.” Especially since it appears to me to involve processes and tools over individuals and interactions

Tuesday, June 15, 2021

Back in the Motor City

Ten years later and the prospect of another 24-hour drive to Motown just doesn't sound appealling anymore, my hatred of flying nonwithstanding. So when I was invited to another counsin's wedding a few weeks ago, I decided perhaps it was best to fly this time. And since it has been sixteen years since I last flew, my flying budget was pretty large. It was an easy decision to opt for comformt over price—direct flight, first class, and whatever hoops to speed through Securithy Threater.

And that's how I found myself at 10:30 am sitting at gate D-2 at the Ft. Lauderdale-Hollywood International Airport, watching the line for Starbucks snake clear across the terminal, everybody head down staring at their smart phones, or looking straight ahead talking into the air. Bunny and I were waiting to board the plane for an hour and a half, and that line for Starbucks never got any shorter.

The flight itself was uneventful. I used to fly the Ft. Lauderdale-Detroit flight every year as a kid to spend the summer with my paternal grandparents. Flying back then was way different than today. First off—this was just prior to the airline deregulations, so the various arlines had to compete on service, not price. Everybody was allowed to go to the gate, so family and friends could wait with you there, and family and friends could meet you at the gate on the other side. I do think there was some security—at least a metal detector, but nothing like the security theater of today. But it wasn't cheap—the cost of flying my 10 year old self, adjusted for inflation, is what I paid for a first class ticket to fly myself this year.

I don't think I want to know the price of a first class ticket back in the day.

The service on the flight? It was okay. I mean, a snack box of cheese, crackers and some gummi bears pales to actual meals I remember eating, but the entertainment center in the seat? A wide selection of movies, music, and live flight tracking? That would have blown my 10-year old mine back in the day.

On the down side, the pre-flight safety dance was not performed by the crew, but instead shown on the said entertainment center, after two mandatory airline commercials. Seriously.

I also found it amusing that airplanes still have no-smoking indicators. How long has it been since one could smoke on a plane? Thity years? Fourty years? I wonder at what point they'll finally be removed.

Another change I noticed—now that each seat has a built-in entertainment center, there's no longer an in-flight magazine or Sharper Image catalog.


Extreme euphemistic emesis containment system, Delta Airlines edition

[A Delta airlines vomit bag with the label of “Baby Care”] Oh, so this is this years euphemism for this bag—okay then!

Wednesday, June 16, 2021

What's a vacation without a bit of surealism?

It seems I only have these odd encounters when on vacation. I was walking towards the lobby of the hotel as half a dozen people, probably early 20s, maybe, were walking the other way. The one in front stops, and asks me directly, “What's your first name?”

I notice he's wearing a name tag attached to a lanyard, and in large bold letters is his name: XXX.

“Sean,” I say. “I see your name is—”

“And what's your last name?” he blurts out before I can finish.

“Conner.”

“Cool! What's your middle name?”

“Patrick.”

“Thanks.” And the group starts walking down the hall.

It was then I noticed the familiar yellow of a school bus through the front door of the lobby.


Extreme empty shelves with draconian limits, Livonia, Michgan edition

Bunny and I were at a drug store when I came across this section of empty shelves:

[Some empty shelves with multiple signs on it that all say “All SquishMallows Limit 1 per household per day NO HOLDS”] Oh great!  Now I'm gonna have to hit the SquishMallows black market to get my fix!

I have no idea what “SquishMallows” are, but whatever they are, stores in the area are unable to keep them on the shevles, even with draconian restrictions. Man, the Barbarians in this area! Keeping the SquishMallows off the shelves like that!


For a recipe that my aunt Kay never made, it was quite good

Bunny and I met with my aunts Kay and Jan at Plymouth Roc, a restaurant partly owned by Kay's son Jordan, who is also the groom in the upcoming wedding on Friday.

As we were leaving, Jordan came from the kitchen, bearing a bowl of candied walnuts. “Here you go,” he said. “I made it from my mother's recipe.”

“I never made this!” said Kay.

“But my customers don't know that,” Jordan said.

“Jordan!”

Thursday, June 17, 2021

So much food today, oh so much food

I don't recall the last time I ate at the Mexican Village, but it's been something like 30 to 35 years. It is my second favorite place to eat, Buddy's being my first. I missed eating at Mexican Village ten years ago, and I wasn't about to miss it this trip. So Bunny and I drove the 25 miles between there and the hotel.

I will say that one thing I do not miss are the Detroit roads—it's like one extended pot hole half-repaired. Ka-thunk ka-thunk ka-thunk bud-a-bud-a-bud-a-bud-a-thunk ka-thunk. The entire way! And back again!

Anyway, other than the road conditions, the trip was mostly uneventful. Things have changed in the 30+ years since I last visited Mexican Village, and let's just say the junction between I-75, I-96, and the Ambassador Bridge is a snarled mess under construction and half-blocked off. And the neighborhood there is … um … shall we say, economically challenged and slowly being reclaimed by nature. It's an odd mix to say the least.

But one oddly maneuvered U-turn in an otherwise abandoned lot later, we arrived. And the place hasn't changed at all in the past 30+ years. I even recogized the same art work on the walls. Amazing!

Way too much food. Just way too much food.

A few hours later, and we were off to an after-rehearsal dinner at The Honey Hole in Plymouth, Michigan. We had the entire restuarant for the party as the groom-to-be, my cousin Jordan, was also a part owner of the place (and is still in the process of reopening the place now that Michigan is slowly opening up). His brother Aaron, owner of the Westwind Brewery in Elkhart, Indiana, was curious about the brewing possibilities in the basement (it's Michigan—every building has a basement, and it's something I sorely miss, living in South Florida), When we were given a tour of the basement, it was clear that brewing beer was not an option, unless you hired a bunch of Hobbits (or Oompa-Loompas—they would work just as well).

And then the food arrived. Way too much food. If this keeps up, I might have to use a baby care bag.


Extreme murals, Plymouth, Michigan edition

The Honey Hole building is coverned in murals. On one side of the building is this bit of mural:

[A larger than life little girl standing on a step ladder, back to the viewer, looking into a hole, with some bees buzzing around her] If I didn't know better, these “honey bees” look more like “killer hornets.”

And on the other side of that wall (inside the restaurant) is this mural:

[A larger than life face of a little girl, staring at a bee on the end of her nose, with honey combs puring out honey all around] There is nothing worse than a bee hive in the walls—you hear all this buzzing yet no bees can be seen, driving one mad.  Please don't ask me how I know this—oh god, I'm getting flashbacks!

It's a neat concept, but it cuts a bit too close to home for me.

Friday, June 18, 2021

A grand day out

What can I say about the wedding ceremony? The bride was beautiful. The groom was hansome. The ceremony moving Vows and rings exchanged. Kisses. Crying. Cheering. Photos. It was great!

Okay, I can say a bit more here—the weather forecast for this week was:

Today's forecast of severe thunderstorms and heavy rain was a bit concerning, given that the wedding was held outdoors. While it did rain last night and a bit this morning, by the time of the wedding, it was party cloudy and clearing up. By the time the event was winding down at the Fox Hills Summerhouse Outdoor Venue it was clear skys as far as one could see.

Officiating the ceremony was Jordan's brother Aaron. Yes, the same Aaron who owns a brewery. If it seems odd for a religeous ceremony to be delivered by a beer brewer, think again (although Aaron isn't a monk, he can officate a wedding ceremony).

Not much else to say about today, other than good luck to the bride and groom.


Extreme marquee, Northville, Michigan edition

The other day Bunny and I were strolling through Northville when I saw this marquee:

[A movie theater marquee with “HAPPY BIRTHDAY KEVIN YODER” displayed] Kevin Yoder?  Wasn't he that small green guy in “War Stars” or something?

It appears that one can actually rent the marquee and have your message displayed to all in Northville. I wonder how much it would cost to say “MY HOVERCRAFT IS FULL OF EELS” and how many people would get the reference?

Saturday, June 19, 2021

Extreme donuts, Canton, Michigan edition

“Tim Hortons? I thought that was a Canadian chain!”

“It is, but the border to Canada is just over there, to the south.”

“South? Isn't Canada north of the US?”

“Mostly, except for Detroit, which darts out over Winsor, Canada.”

[Picture of a chocolate glazed Tim Horton donut] Ignore the less than perfect glaze over the donut—that was due to my man-handling the donut to get a less-than-worthy Instagram picture.

“You know, these donuts don't live up to the hype. They're just okay.”

“Yeah.”

“I think I prefer the donuts from Publix.”

“Don't let them hear you say that—we may not get out of Michigan alive.”

Sunday, June 20, 2021

Extreme pizza, Detroit edition

Of course, I can't come to Detroit and not visit Buddy's.

[A mural, convering the entire side of a building, with the word “Buddy's” on the left, the word “Detroit” on the right, and in the middle, Atlas, with the city skyline of Detroit on his back, contemplating a pan of Buddy's Pizza held in his right arm] ´It's a deep-dish square pizza with the sauce on top, and it's insanely delicious!

You better believe they ship! So there's no excuse not to try this pizza.

And no, they did not pay me to say this. I just think it's that good!


A detour to historical Detroit

My original plan to drive to Buddy's was to take I-275 south to I-96 east to the Davison Freeway, leaving us two blocks south of Buddy's. Then I saw a two mile stretch that wasn't a freeway and had second thoughts (this is Detroit, after all). The backup plan was to then drive I-275 north to I-696 east to I-75 south to the Davison Freeway, but a chance conversation with the front desk revealed that the I-696/I-75 interchange was closed off until I think next year. That meant I went with my original driving plan. I only bring this up, because on the way back to the hotel I caught sight of the “Shrine of the Black Madonna Cultural Center and Book Store / Art Gallery” (the street view from Google). Despite the sign being so fantastic, this is for real and I spent some time going down a historical rabbit hole.

Not only had I never heard of this organization, but its history is mixed with that of the Detroit Riots of 1967, which I had heard of from my grandparents. I also learned that Gordon Lightfoot's song “Black Day in July” was about the Detroit Riots, and the song was banned in 30 states (although I do recall hearing the song as a kid—either because it wasn't banned in Michigan, or my parents had the record, but I do distictly remember that song).

And to think that a chance glance of an odd sign on a building could lead to such an interesting rabbit hole, only because my preferred route to a Detroit restaurant was under construction.

Monday, June 21, 2021

IT'S STILL DAYLIGHT OUTSIDE!

It's our last full day here in Michigan and because we're a) on vacation, and b) lazy, we got a late start on the day (“breakfast” was around 3:00 pm). Around 8:00 pm, Bunny got an idea—we should get some sub sandwiches and store them in the room fridge for when we eventually get hungry. There's a Meijer across the street, and from the web site it appeared they had a deli section. I mean, if Publix sells subs, then Meijer might sell them.

Driving across the street (we drove, in case they did not, in fact, sell subs, we could try elsewhere) was easier said than done. And while the Meijer was still open, the deli counter, sadly, was not. Plan B—Subway. A quick Google search revealed half a dozen Subway shops within five miles, all but one still open.

One.

IT'S STILL DAYLIGHT OUTSIDE!

Buy hey, it was only a few miles away.

And it was closed!

Did I mention it was still daylight outside? Close to 9:00 pm by now, and the sun is still shining in the sky. Bunny noticed a Kroger was in the shopping center, and they were open!

But alas, their deli section was closed.

What is with this town? IT'S STILL DAYLIGHT OUTSIDE!

Yes, we did get some food from a nearby Arby's, but still, IT'S STILL DAYLIGHT OUTSIDE!


Extreme deals in realestate, Detroit edition

You can probably pick this place up for a song:

[A two story house, long since abandoned, sans windows, in downtown Detroit] There's a great cross-breeze through the house.

It's a bit of a fixer-upper, but the lots on either side are completely empty, so you won't have to contend with noisy neighbors.

Of course, there's quite a bit of that in Detroit—a house in need of some DIY TLC in a sea of empty lots.

Tuesday, June 22, 2021

Notes on a public announcement at the McNamara Terminal of the Detroit Metropolitan Wayne County Airport

“Will Mu Wang please report to gate A-48. Mu Wang, please report to gate A-48. You left your ID there. Mu Wang, please report to gate A-48. Or, you know, Wang Mu. You left your ID at gate A-48.”


Travelling 1,200 miles, only to get stuck at the gate

The differences between the Ft. Lauderdale-Hollywood International Airport and the Detroit Metropolitan Wayne County Airport are night and day. The Ft. Lauderdale airport is U-shaped; the Detroit airport is two linear terminals, each nearly a mile in length. Hopping through Security Theater was trivial in Ft. Lauderale; it was a nightmare at Detroit. I mean, if you don't want people to use the plastic bins for the contents of pockets, then why are they even there? Stop berating people who use them! The gates at Ft. Lauderdale were loud and crowded; in Detroit—blissful silence. And no Starbucks at the gate.

At least Detroit provides an elevated tramway to traverse the nearly mile-long terminal. That was fun to ride.

The flight back was uneventful the entire way, until we got to the gate at Ft. Lauderdale. The jetway malfunctioned, and we were stuck on the airplane. Everybody was getting up to retrieve overhead luggage and then it was announced that we all had to sit back down because they were planning on taxing the plane to a different gate. So everybody sat down, several minutes of non-movement passed, then suddenly, the jetway moved into place (or someone, or someones shoved it into place) and we could disembark.

And that was really the only issue we encountered. At least it happened on the ground and did not involve the airplane.

Also, it appears the line at the Starbucks had finally cleared. That's nice—took only a week.


Why did I not get the memo?

Okay, who forgot to tell Bunny and me about the underground tunnel with a color-changing LED light show synchronized to music at the Detroit Metropolitan Wayne County Airport? We had over an hour to kill!

Aaaaaaaaaaaaaaaaaaaaarg!


A few last observations about our trip to Detroit

When Bunny and I arrived in Detroit we had our choice of two mid-sized cars to rent—one a Kia, and one a Chevy. Given that we'd be driving in and around Detroit the only safe choice was the Chevy.

It wasn't a bad car. I already drive a Chevy Impala, so the controls were more or less the same. But unlike my car, our rental car had WiFi! I never tried it out, but it was odd to thing that a car could also be a WiFi hotsopt.

Weird.

Also, this is the first car I've driven that had a push-button start. There was no key—or rather, the only thing we had was a fob, and I never had to take it out of my pocket to unlock the car. Just having the fob near the car, and hitting a button on the door handle was enough to do that. The only times I had to remove the fob from m pocket was to lock the car, and to unlock the trunk.

The only issue I had with the car was the steering wheel—it was a bit too low for me, and I had issues with getting into and out of the car. I had to scrunch up my right leg every time.


The only “computer” I took with me was my iPad and an iPad-specific keyboard. I can do everything I want to with it, even if he keyboard really isn't much of a keyboard. The iPad is an older model, and as such, it's not receiving any updates anymore, but again, that's okay because the majority of sites I visit still work. In fact, Facebook reports that the browser on the iPad is too old to suppprt (what? Really? Come on! It worked … um … two years ago just fine! What eldritch horrors hath JavaScript released upon us now?) but even so, Facebook wants my attention so bad it still provided a cut-down Facebook experience.

And you know what?

It was much faster, lighter, and easier to use than the normal C'thulian JavaScript version they normally serve up. How about that? Score one for obsolete browsers!

Thursday, June 24, 2021

The avionics compartment on an Airbus 350

It makes sense that there would be a number of computers on a modern airplane to handle the avionics, but I was still surprised at the size of the avionics compartment on an Airbus 350—it's like a mini-datacenter below the cockpit! There appears to be quite a bit of computing power on that airplane. I wonder if part of that is involved with any on-board entertainment systems?

Thursday, July 01, 2021

I finally get the regression test working, just in time to rewrite the entire thing

I finally got the validation logic working! And it only took me … um … a bit longer than I expected.

I just took it slow and steady. First assumption—the code was correct, the regression test wasn't. Second, start with the one known condition required to pass the test. Check the failures, and add another condition. Repeat as needed, spending sometimes a bit too much time trying to figure out the common cause of “failure” (as reported by the incorrect regression test). It came down to, depending upon how you count, six or eighteen conditions (there are a base five, plus any one of three other conditions) for when Project: Lumbergh sends a message to Project: Cleese. Some might say the logic is too complicated. I might even agree. But then, I'm not the one defining the business logic here.

Now I can continue with adding the new tests, and it's here that I might have to rethink how the regression test works. Maybe a secondary regression test that tests some of the non-business logic stuff, like making sure we handle the database replies out of order (A returns, then B, or B returns, then A). I don't know, it's something I have to think about.

Friday, July 02, 2021

A small heads up to my D&D group

Some background: I've been running the “every-other-week” D&D game for two years now, and my players are suspicious of everything I toss out.

So I have to wonder what it says about me that most of the ideas from Probably Bad RPG Ideas (link via Kirk Israel) actually sound fun. You know, like “the big bad of your campaign—the quest-giving innkeeper from the starting tavern.” Or “rolling a natural 1 on any skill check counts as a natural 20 on an opposite skill check (i.e. a 1 on Persuasion counts as a 20 on intimidation, etc.).”

That can be fun.

And funnily enough, this idea: “a D&D item that gives a really high bonus to a choosen stat, but it also makes you brutally honest about absolutely everything,” is something I already do (as my group knows all too well). And I was a player in a game where “Disney is secretly run by a True Fae because the two elements of Arcadia are stories and contracts so by using complex contracts to get control of all stories it can become the most powerful being in Faerie” (and as a side note—isn't that true already?).

And perhaps I shouldn't mention this one because my players already know about the tarrasque (using the D&D spelling here) beneath the city but (if you are a player in my game—skip this bit) it's too good not to contemplate: “make the tarrasque closer to its mythic origins by saying if hit with a ranged touch attack by holy water, it's now your best friend and fetches you slippers and rolls over so you can pet its belly.”

Monday, July 05, 2021

A reimplementation of a web idea in Gemini

Way back in the day, “ping servers” were popular and I added support for it to mod_blog, only to remove it a few years later when the one I was using (the most well known one—I think it was weblogs.com but it's been over fifteen years or so) stopped working. I then removed the support from mod_blog because I didn't feel it was worth keeping a feeature around I didn't use.

Then about a week or so ago, a similar service just started up for Gemini based blogs, and given that I serve up my blog via Gemini I figured I could support that feature again. But as I started, I had an idea—instead of hardcoding support for Antenna in mod_blog, why not support the idea of a “hook” (like git)? It would be easier to write a script to update Antenna (since I already support TLS and Gemini URLs in Lua) than to try to do that all in C.

It wasn't that hard. One function to execute a script and some judicious calls to said function and I have a way to notify external services of new updates.

I wish I had thought of this concept back then. It would have saved me the trouble of adding, and later, removing, code to support various notification sites as they came and went.

Ah well … live and learn.


It's still a sane library for decoding DNS packets, but now it's a sane library for encoding as well

It's software update day here at Chez Boca. In addition to an updated mod_blog, there's also an updated SPCDNS—version 2.0.0!

It only took about ten years (and about four years after it was first requested) but the library now supports full encoding of 30 DNS records. The reason I didn't include such support intially is that the encoding of DNS domain names in the records is not straightforward. It uses a scheme to compress the data such that it's easy to parse, but not so easy to encode without allocating memory which is something I wanted to avoid. A result is that there is a hardcoded limit to the number of domain names that can be encoded, but just how many domain names is … hard to say due to the compression scheme. And because of this, the encoding routine does use a bit more memory than it previously did.

That, and an API change with the Lua wrapper (returning an integer error number instead of a string error message) is why I decided to make this a 2.0.0 release. Users at the C level shouldn't see any change though.

Tuesday, July 06, 2021

Thanks, Facebook!

Even though I can automatically notify Antenna, I still manually update Face­Me­Linked­Insta­My­Space­Book­We­In­Gram by hand. Yes, it's annoying. Yes, I hate it. Yes, most people don't bother to check the website, or subscribe to the ATOM feed (or the RSS feed or even the JSON feed) but they sure as XXXX use Linked­Insta­My­Face­Me­We­In­Gram­Space­Book.

No, I'm not bitter.

Anyway, as I was updating the link on Facebook, I just now received a notification of a message from 2016!

Um … yeah.

There's a reason why I still use email.

Wednesday, July 07, 2021

To unit test or not to unit test, that is the question

There are two parts of your code. Code that can be unit tested and code that can't be unit tested.

Code that can't be unit tested is simple. Any code that has to touch IO can't be unit tested. Period. Any code that doesn't touch IO can be unit tested. It's that simple.

Keep ALL IO segregated from the rest of your code. Keep IO functions and methods super small. Do not inject IO polluted objects into other parts of your code.

Nothing should ever be mocked. Period. If you don't agree you likely don't under... | Hacker News

In hindsight, this is obvious. The issue I have with unit testing projects like “Project: Lumbergh,” “Project: Sippy-Cup” or “Project: Cleese” is that they're nearly all IO with very little logic (with the caveat that “Project: Lumbergh” implements all the business logic interspaced with IO).

With that said, even though the author also stated not to mock at all, I do. We have a few network services that “Project: Lumbergh” relies upon, and I have written my own versions of those services that basically respond with a canned answer for a particular query. It was easy since the services speak a common protocol (DNS in this case) and I don't have to implement the logic of those services to determine the answer.

I also decided to implement a new regression test and keep the one I have working as a separate test. This way, it'll be easier to implement tests like “data source B replies, data source A times out.” I'm also keeping each test in its own file, so adding new ones should be way easier and hopefully, we won't end up with another 16,000 tests.


The search engine for text-heavy web sites

The Marginalia Search Engine (link via kontakt) is a fresh approach to search engines. Instead of Page Rank it uses a different method that probably does a better job than Google:

As a consequence, the closer to plain text a website is, the higher it'll score. The more markup it has in relation to its text, the lower it will score. Each script tag is punished. One script tag will still give the page a relatively high score, given all else is premium quality; but once you start having multiple script tags, you'll very quickly find yourself at the bottom of the search results.

Modern web sites have a lot of script tags. The web page of Rolling Stone Magazine has over a hundred script tags in its HTML code. Its quality rating is of the order 10-51%.

Marginalia Search - Notes on Designing a Search Engine

The more markup, the lower the score. Javascript and the score falls through the floor. Neat.

And from the few tests I ran, it seems to be a pretty decent search engine for what I'd use it for.

Tuesday, July 20, 2021

There are reasons for operators

One particular area of software complexity is the degree to which unclear code can have unnoticed side effects, an effect that in his most recent blog post, Drew DeVault coins "Spooky code at a distance". Of the two example he gives its the first, of operator overloading, that I think is of greater interest and raises the question about what even the point of operators is and whether they make the code unnecessarily ambiguous.

All this is to say, do we really need them? Would it not be better to avoid mutation and to be explicit. If you want to add two numbers then call an add function. If you want to concatenate strings then call a concatenation function. If you want to define your own conditional subroutines, I guess use a lazy language, but then name them. I think its [sic] important to be explicit about the intent of code even if the behaviour is the same as it is easier for others to read and understand and will ultimately lead to fewer bugs. That seems to make sense, right?

Are Operators Even Necessary?

There's a reason why languages have operators—it makes the code easier to reason about. For instance, is this bit of code:

/* Why yes, the "=" is an operator as well */
fassign(&xn1,fmul(fmul(fadd(fmul(A,yn),B),xn),fsub(1.0,xn)))
fassign(&yn1,fmul(fmul(fadd(fmul(C,xn),D),yn),fsub(1.9,yn)))

or this?

xn1 = ((A * yn) + B) * xn * (1.0 - xn);
yn1 = ((C * xn) + D) * yn * (1.0 - yn);

(also, spot the bug!)

Drew comes down on the “no-operator overloading” camp because he finds it harder to debug potential issues, performance or otherwise. But that's a trade-off he's willing to make—others might make the trade-off the other way. For instance, I found it much easier to implement the Soundex system in LPeg, which uses (or maybe abuses?) Lua's operator overloading capability. I traded development time (well, minus the time it took me to get used to LPeg) for a bit of runtime and potential difficulty in debugging. There is something to be said for conciseness of expression. I can't find a source for this, but I have heard that the number of lines a programmer can write per day is constant, regardless of language. The above equation is two lines of C (or really, any higher level langauge) but in assembly?

	movss   xmm0,[yn]
	mulss   xmm0,[A]
	addss   xmm0,[B]
	mulss   xmm0,[xn]
	movss   xmm1,[const1]
	subss   xmm1,[xn]
	mulss   xmm0,xmm1
	movss   [xn1],xmm0

	movss   xmm0,[xn]
	mulss   xmm0,[C]
	addss   xmm0,[D]
	mulss   xmm0,[yn]
	movss   xmm1,[const1]
	subss   xmm1,[yn]
	mulss   xmm0,xmm1
	movss   [yn1],xmm0

Eight times the lines of code, which seems about right for assembly—not hard, just tedious. I would think if Robert wants to use functions over operators, it's easy enough to just do it. I do wonder though, how long until he goes back to using operators?


A most persistent spam

I'm wondering what's up with this spam?

From
Aleksandr <info@s9.mirengo.ru>
To
info@conman.org
Subject
Предложение
Date
Tue, 20 Jul 2021 22:39:01 +0000

Здравствуйте. Вас интересует продвижение сайта? Напишите мне в Skype пожалуйста WhatsApp/Viber владельца сайта и передайте мое предложение. Мой Skype для быстрой связи: mayboroda_aleks Преимущества при сотрудничестве со мной:

Я предоставляю отчетность, какие и где были куплены ссылки на Ваш сайт, какие есть ошибки на сайте, которые нужно исправить, увидеть реальный рост позиций сайта и многое другое. С уважением, Aleksandr, SEO специалист в области продвижения сайтов. Мой Skype для быстрой связи: mayboroda_aleks

I mean, yes, it's spam. It's in Russian. And I've been receiving this exact email for well over a year now. Usually two or three times a week. I tried rejecting it via the IP address (via my greylisting daemon) but to no avail—the source IP changes too often. I'd reject the domain, but that changes constantly too. The name? Always “Aleksandr.” The subject line? Always “Предложение.” Yes, I could just automatically delete the email upon receiving it, but I'd much rather reject it as soon as possible rather than accepting it to then just delete it.

But all that aside, I can't figure out the angle here. Is Aleksandr really that hard up for work that he'll spam anybody for work? (yes, I ran the email through Google Translate) Even people who don't speak Russian? Or is this a smear campaign against Aleksandr? Trying to drive him (her?) out of business? I can't tell.

There's no virus in the email. And even though there's an HTML version of the message included, there are no malicious links, as there are no links.

So I'm at a complete loss as to the game going on here.

Update on Wednesday, Debtember 22ND, 2021

Wisdom of the AncientsI did find a solution, but it might not be one you can use.

Friday, July 23, 2021

I'm surprised the Secret Service did not shut them down immediately

I recently read in The Transylvania Times (the paper of record for Brevard) that past issues have been digitized up through early 1975 and are available online. Way cool! So I picked an arbitrary issue to look through, January 9TH, 1975 and learned a bit of the history of the bed and breakfast we stay in, and some ads for movies I've never heard of but it was page 14 that left me speechless—it was an add for printing jobs done by the Transylvania Times:

We Print Anything But Money—

But Our Presss Has Even Proved Itself Capable Of Doing That!

The Transylvania Times. (Brevard N.C.) 1931-current, January 09, 1975, SECTION A, Page 14, Image 14 · North Carolina Newspapers

It left me speechless, but only because I was laughing so hard.

Tuesday, July 27, 2021

The meetings will continue until morale improves

There is a strong cultural difference between how we (and by “we” I mean the team I work on) used to handle testing and how we handle testing now. Today's conversation du jour involved the checking of SIP headers and could we just simply compare the returned SIP message back with a “golden copy.” I countered that there are some fields, like the Call-ID: header that change per call. I was then asked about the custom headers we produce. The one header specifically talked about looks something like:

P-Foo-Custom: e=0; foo=this; bar=that; andthis=nothing

“The subfields,” I said, “don't have a set order. They can appear in any order.”

“Why?”

“Because of an implementation detail of Lua—that particular field is populated from a Lua hash table, and Lua doesn't guarantee any ordering on the hash table.”

“But … but … couldn't you add an option to keep an order?”

“The order shouldn't matter! Any client should be able to handle those subfields in any order.”

“But … but … couldn't you add code to maintain an order?”

“That would be yet more code to lock down what should be an implemetation detail! And I do parse those headers when checking.”

“But … but … you could just compare against a ‘golden copy!’”

“I already parse and check the subfields!

Oh.”

I also get the feeling that the tests are assumed to be 100% functionally correct and any deviation MUST be a problem in the code being tested. The notion that the test COULD BE WRONG just doesn't come up. We went down a deep rabbit hole today where the issue turned out to be a misconfiguration in “Project: Sippy-Cup” only it took over an hour to resolve it. Again, the test was incorrect, not the code (and the original regression test, which had the misconfiguration, passed every test—again, from what I understand reading up on this, you aren't supposed to test the tests, right?

Then there was the “That test failed!”

“Oh, that's just me playing with the new regression test framework—it's not a valid test.”

“But it failed! We must investigate.”

I have to adjust to the fact that I have a new job.

Thursday, July 29, 2021

I wonder how the unit test cultists would deal with the testing I do

I thought that as long as I'm going to such lengths to get “push-button testing” implemented, I might as well mention some of the techniques I've used just in the off chance that it might help someone out there. The techniques I use are probably only relevant to the stuff I work on and it may not apply elsewhere, but it certainly can't hurt to mention it.

So I don't have unit tests (whatever they are) per se, but I do have what is referred to as a “regression test,” which tests “Project: Sippy-Cup,” “Project: Lumbergh” and “Project: Cleese.” The reason is that taken individually, each of those projects can be considered a “unit,” but to, say, test “Project: Lumbergh” alone would require something to act like “Project: Sippy-Cup” (which feed requests into “Project: Lumbergh”) and “Project: Cleese” (which is notified by “Project: Lumbergh” in some circumstances), so why not run those as well? “Project: Lumbergh” also talks to two different DNS servers for various information about a phone number, so when running it, I need something to respond back. I also need an endpoint for “Project: Cleese” to talk to, so what's one more process? Oh, “Project: Lumbergh” will also talk to cell phones, or at least expect a cell phone to request data in some circumstances, so I have a “simulated cell phone” running as well.

Each test case is now a separate file, which describes how to set up the data for the test (the two phone numbers, what names, what feature we're testing, etc) as well as what the expected results are (we get a name, or the reputation, or a different phone number, depending upon what's being tested). This way, we can have the regression test run one test, some of the tests, or “all the things!” The regression test will read in all the test cases and generate all the data required to run them. It then will start the seven programs with configurations generated on the fly, and start feeding SIP messages into the maelstrom, recording what goes on and checking the results as each test runs. And when a test fails, the test case information is recorded in an output file for later analysis.

So far, nothing out of the ordinary. That's pretty much how the previous regression test worked, except it generated all 15,852 test cases. But it's how I test some of the wierder border cases that I want to talk about.

First up—ensuring something that's not supposed to happen didn't happen. In some circumstances, “Project: Lumbergh” will notify “Project: Cleese,” and I have to make sure it happens when it's supposed to, and not when it's not supposed to. I've already mentioned part of my solution to this, but the updated version of that is: the regression test has a side channel to the fake endpoint that “Project: Cleese” talks to. Before each test, the regression test will send that component the test data and whether it should expect a request or not. The fake endpoint will simply record this data for later use. If a request is made for that particular test case, it will also be noted for later. Once the regression test has finished running all the tests and waited a few seconds for any last second requests to clear, it “runs” one more test—it queries the fake endpoint for a count of requests it actually received and compares it to the number the regression test thinks should have happened (and output success or failure). Upon termination of the regression test (as everything is being shut down), the fake endpoint will then go through its list of tests it received from the regression test, and record any discrpancies (a query that was supposed to happen didn't, or a query that wasn't supposed to happen, did). This is recorded in another file for later analysis (which is why I send over all the data to the fake endpoint—just to make it easier to see the conditions of the test in one place).

Second—“Project: Lumbergh” talking to multiple DNS servers. It will generally send out both requests at once, given the rather demanding timing constraints on us, so we have to support reply A coming before reply B, reply B coming before reply A, reply A timing out but getting reply B, and reply B tming out but getting reply A. How to test for those nightmare scenarios automatically? Oh, “Project: Lumbergh” also maintains a continuous “heartbeat” to these services, and if those replies don't get though, the servers will be taken out of rotation by “Project: Lumbergh” and once the last one is gone, “Project: Lumbergh” effectively shuts down. The nightmare just got worse.

Well, again, I have written my own fake endpoints for these services (not terribly hard as the data is fixed, and it's not like I'm going for speed here). And again, I added a side channel for the regression test to communicate to the fake endpoints. After starting up the these fake endpoints, the regression test informs the endpoints what entry is considered the “heartbeat” so no delay what so ever will ever be applied to that query. Then before any test is run, the regression test will inform the endpoints how long to delay the response—all the way from “no delay” to “don't even respond” (except for the “heartbeat”—that will always happen) as it's part of the testing data.

Yes, it all works. Yes, it's a pain to write. Yes, it's a bunch of code to test. No, I don't have XXXXX­XX unit tests or regression tests for the regression test—I'm only willing to go so far.

I just hope we don't have to implement 100% test code coverage, because I'm not looking forward to forcing system calls to fail.


“Would love to hear about your prior development method. Did adopting the new practices have any upsides?”

[The following is a comment I made on Lobsters when asked about our development methods. I think it's good enough to save, and what better place to save it than this here blog. So here it is.]

First off, our stuff is a collection of components that work together. There are two front-end pieces (one for SS7 traffic, one for SIP traffic) that then talk to the back-end (that implements the business logic). The back-end makes parallel DNS queries [1] to get the required information, muck with the data according to the business logic, then return data to the front-ends to ultimately return the information back to the Oligarchic Cell Phone Companies. Since this process happens as a call is being placed we are on the Oligarchic Cell Phone Companies network, and we have some pretty short time constraints. And due to this, not only do we have some pretty severe SLAs, but any updates have to be approved 10 business days before deployment by said Oligarchic Cell Phone Companies. As a result, we might get four deployments per year [2].

And the components are written in a combination of C89, C++98 [3], C99, and Lua [4].

So, now that you have some background, our development process. We do trunk based development (all work done on one branch, for the most part). We do NOT have continuous deployment (as noted above). When working, we developers (which never numbered more than three) would do local testing, either with the regression test, or another tool that allows us to target a particular data configuration (based off the regression test, which starts eight programs, five of which are just needed for the components being tested). Why not test just the business logic? Said logic is spread throughout the back-end process, intermixed with all the I/O it does (it needs data from multiple sources, queried at the same time).

Anyway, code is written, committed (main line), tested, fixed, committed (main line), repeat, until we feel it's good. And the “tested” part not only includes us developers, but also QA at the same time. Once it's deemed working (using both regression testing and manual testing), we then officially pass it over to QA, who walks it down the line from the QA servers, staging servers and finally (once we get permission from the Oligarchic Cell Phone Companies) into production, where not only devops is involved, but QA and the developer who's code is being installed (at 2:00 am Eastern, Tuesday, Wednesday or Thursday, never Monday or Friday).

Due to the nature of what we are dealing with, testing at all is damn near impossible (or rather, hideously expensive, because getting actual cell phone traffic through the lab environment involves, well, being a phone company (which we aren't), very expensive and hard to get equipment, and a very expensive and hard to get laboratory setup (that will meet FCC regulations, blah blah yada yada)) so we do the best we can. We can inject messages as if they were coming from cell phones, but it's still not a real cell phone, so there is testing done during deployment into production.

It's been a 10 year process, and it has gotten better until this past December.

Now it's all Agile, scrum, stories, milestones, sprints, and unit testing über alles! As I told my new manager, why bother with a two week sprint when the Oligarchic Cell Phone Companies have a two year sprint? It's not like we ever did continuous deployment. Could more testing be done automatically? I'm sure, but there are aspects that are very difficult to test automatically [5]. Also, more branch development. I wouldn't mind so much this, except we're using SVN (for reasons that are mostly historical at this point) and branching is … um … not as easy as in git. [6] And the new developer sent me diffs to ensure his work passes the tests. When I asked him why didn't he check the new code in, he said he was told by the new manager not to, as it could “break the build.” But we've broken the build before this—all we do is just fix code and check it in [8]. But no, no “breaking the build,” even though we don't do continuous integration, nor continuous deployment, and what deployment process we do have locks the build number from Jenkins of what does get pushed (or considered “gold”).

Is there any upside to the new regime? Well, I have rewritten the regression test (for the third time now) to include such features as “delay this response” and “did we not send a notification to this process.” I should note that is is code for us, not for our customer, which, need I remind people, is the Oligarchic Cell Phone Companies. If anyone is interested, I have spent June and July blogging about this (among other things).

  1. Looking up NAPTR records to convert phone numbers to names, and another set to return the “reputation” of the phone number.
  2. It took us five years to get one SIP header changed slightly by the Oligarchic Cell Phone Companies to add a bit more context to the call. Five years. Continuous deployment? What's that?
  3. The original development happened in 2010, and the only developer at the time was a) very conservative, b) didn't believe in unit tests. The code is not written in a way to make it easy to unit test, at least, as how I understand unit testing.
  4. A prototype I wrote to get my head around parsing SIP messages that got deployed to production without my knowing it by a previous manager who was convinced the company would go out of business if it wasn't. This was six years ago. We're still in business, and I don't think we're going out of business any time soon.
  5. As I mentioned, we have multiple outstanding requests to various data sources, and other components that are notified on a “fire and forget” mechanism (UDP, but it's all on the same segment) that the new regime want to ensure gets notified correctly. Think about that for a second, how do you prove a negative? That is, something that wasn't supposed to happen (like a component not getting notified) didn't happen?
  6. I think we're the only department left using SVN—the rest of the company has switched to git. Why are we still on SVN? 1) Because the Solaris [7] build servers aren't configured to pull from git yet and 2) the only redeeming feature of SVN is the ability to checkout a subdirectory, which given the layout of our repository, and how devops want the build servers configured, is used extensively. I did look into using git submodules, but man, what a mess. It totally doesn't work for us.
  7. Oh, did I neglect to mention we're still using Solaris because of SLAs? Because we are.
  8. Usually, it's Jenkins that breaks the build, not the code we checked in. Sometimes, the Jenkins checkout fails. Devops has to fix the build server [7] and try the call again.

Monday, August 02, 2021

I never said testing was bad, just that it's tedious to automate

I might come across as someone who hates testing, if the past two months have been anything to go by, but I've really been complaining about automating the tests, including some rather difficult ones to automate. But honesty compels me state this: the new regression test has found another potential bug.

Because I added code to delay (or entirely block) responses from the various database sources, a few test cases were added to a problematic feature to ensure it's been fixed. The Happy Path™ has been fixed, but there is a Sad Path™ that's been missed. We query two sources, A and B. In the scenario we are testing, the data we want is from B—any data from A is ignored (but we have to query anyway due to “reasons”). So the case of A has no data, B has data is fine. But it's when A doesn't return (or times out), the reponse from B is ignored when it probably shouldn't be (since that data does get back to us). And it would not surprise me if there aren't more cases like this.

Normally, I wouldn't expect this to happen all that much [It doesn't. We have a KPI for that, and I don't think it's worth worring about–the largest spike I've seen over the past month is easly three orders of magnitude lower than our volume; the rest barely show up on the graph. —Sean], and the re-engineering required to handle these casees might be significant since it would require adding more states to the processing state machine. But that's not my call to make.

Tuesday, August 03, 2021

Yak shaving the garbage disposal

The garbage disposal went kaput last night. Bunny just got home with the new unit. How hard can it be to replace it?

[A shot of a kitchen ceiling, which includes a pan rack, and some decorative copper molds flanking a ceiling fan.] Everything is looking up.  Of course, that's easy to say when one is flat on their back on the kitchen floor.

Next time I'm flat on my back on the kitchen floor, I'll make sure not to ask that question.

Removing the old unit was easy enough—pop the circuit breaker to it (just in case), disconnect the drain hose and the hose to the dishwashing machine, twist hard and let it fall. Then remove a small panel on the bottom of the unit, and unwire the power. The only hard bit was pulling the wires out as they were this very thick solid copper wiring.

Installing the new unit? Well, wiring in the power was a bit tough, what with having to manhandle the thick ground wire (and honestly, I thought that was going to be the hardest bit of the job). Then it was just a simple matter of remounting the disposal to the bottom of the sink. The mounting bracket is standard, so I didn't have to install that. It was a matter of lifting the unit, catching some tabs onto a rail and twist!

Half an hour later and I'm flat on my back, garbage disposal still not mounted, and out of ideas. It's that the unit is just heavy enough to be unwieldy, and it was proving to be very difficult to line the tabs up and ensure they engaged with the rails.

Bunny suggested we set the unit on something to help hold it up. What finally worked was a small step stool, several planks of wood and a few shims. Took just a few seconds.

[Picture of a garbage disposal, sitting on some wedges, several pieces of wood, and a small foot stool I couldn't fit into the shot.  Also, there's a drain pipe hanging off the left side of the unit.] See that black thing hanging off the left side?  Yes, that's the drain pipe.  That's going to prove to be problematic in a few moments.

Then the next problem cropped up—the drain pipe out of the garbage disposal was too long, and in the wrong location, to hook back up to the normal plumbing. Inspecting the old unit showed the drain pipe had been cut, and given the new unit was pretty much the same as the old one, I figured I might as well use the drain pipe from the old unit. Only issue here was getting the drain pipe off the new unit.

It turned out I had to unmount the unit.

Sigh.

A few moments to switch out the drain pipe, and then another twenty minutes trying to remount the unit back to the underside of the sink. I think I got very lucky on the first attempt, because the second attempt was not going well.

But eventually I got it.

Then all that was left was to reattach the dishwasher hose, then the drain pipe to the rest of the plumbing and … oh look! That part came off in my hand.

Sigh.

So tomorrow it's off to the hardware store for some new plumbing hose, and we should be all good to go.

“Oh no!”

I was afraid to ask, but did anyway. “What's up?”

“The toilet … ”

Friday, August 06, 2021

I'm not sure what I hate more, control panels or unit tests über alles

I am experiencing culture shock with the new testing regime.

So I had this exchange with the new manager, AG, over email. AG: “In which case or scenario does ‘Project: Sippy-Cup’ send a 480 response code? Please see the attached packet capture.”

I answered, “‘Project: Sippy-Cup’ does not send a 480 response. I checked the packet capture, and the IP address does not appear to be ours.”

AG replied, “Thanks for the information. Can you also confirm that there is no code in ‘Project Sippy-Cup’ to send a 480 response code?”

When I read that, I admit I got a bit upset—I did check the code the first time around! Does he not trust me? But upon reflection, I could see how AG might have thought I didn't check the code to “Project: Sippy-Cup” at all because the packet capture had the incorrect IP addresses. I see I may have to be more explicit in my future responses.

Then during the regularly scheduled meeting AG asked if we had any tests for 480 responses. … What? I replied, “No, because ‘Project: Sippy-Cup’ does NOT send a 480 response.”

AG then asked if there was a list of responses “Project: Sippy-Cup” replies with. Again, the answer is no, not explicitly written down. I then read through the code saying out loud each response code it does return. Then AG asked if there were any tests for any of those responses, like the “version not supported” response?

I'm having a hard time wrapping my brain around a test for

if message.request.version ~= "2.0" then
  info.socket:send(remote,pack_error(message,response.VERSION_NOT_SUPPORTED))
  return
end

Really? Testing the convoluted business logic I can see, but this? What? I got the logic wrong? There's a bug in two lines of code?

So now I have to find a way to inject invalid SIP messages into the regression test.

I swear, mocking system calls is coming soon …

Wednesday, August 11, 2021

A most persistent spam, part II

Shortly after I wrote about the Russian spam from Aleksandr the nature of the emails changed. They are now four attached Microsoft Word files. I'm not sure if they're infected or not, but it matters to me not, because I can't read the darned things since I am Microsoft free. Except for a small handful of emails where they appear to be missing the four Microsoft Word files and it seems they were never included in the email. It was weird enough to do a bit more investigation.

I have a stock pile of these emails now, and I've notcied an interesting thing—all of them are addressed to one of just two addresses. The first one is info@conman.org, a catch-all address that is mentioned in RFC-2142, and the second one is rparker@numbersstation.info, which I've only mentioned once on this blog and one would have to actively search for to even find it elsewhere.

So I have three options before me:

  1. nuke both the info@conman.org and rparker@numbersstation.info addresses as they're not really used;
  2. setup a custom email filter rule that will tell my greylist daemon to reject emails from the IP address (which I did manually, but it changes quite often);
  3. setup a custom email filter rule that will tell the firewall to block the IP address from even connecting.

The first is easy, but I wonder how long until Aleksandr finds another address to spam. The other two are a bit more involved. I think I'll try the first one and see how long that lasts, and only if the spam returns will I mull over the other two options.

Update on Wednesday, Debtember 22ND, 2021

Wisdom of the AncientsI did find a solution, but it might not be one you can use.

Sunday, August 15, 2021

The Dungeons and Dragons 5th Edition Challenge Rating system is deranged

I've been running a D&D5 game for two years and I've yet to come to grips with the “Challenge Rating” system for monsters. There have been times when what I think is a balanced encounter is one sided with the players going “Okay, that must have been the minion—where's the actual boss monster?” and other times when I throw something that should end with a total party kill, but instead is just a “challenging” encounter the party survives.

I think the theory is that a group of four players of level N should be equally matched with one monster of a challenge rating of N. And I read “equally matched” as “a 50/50 chance for either side to be killed.” Whether that's a good reading of the term “equally matched” is debatable, but that's how I'm initially reading it. It makes sense to me—if you have two combatents (and let's face it—D&D involves a lot of combat) of equal skills and equipment, then it should be a 50/50 toss up for the winner. And in plenty of spots in the various D&D tomes I read that four level 1 characters should be an equal match to one CR1 monster.

So I wrote a simulation to test that out. I have four level 1 characters that are pitted against one CR1 monster for 10,000 simulated fights. For the four players, I used the four archetypal types—a cleric, fighter, thief and wizard. For the sake of simplicity, all four will always “run up” to the monster and fight—no ranged attacks are done. I know this isn't completely realistic, but for a “proof-of-concept” it should be good enough.

Anyway, our poor unfortunate victims:

The Cleric
Has an an AC of 14, 1d8+2 HP, no initiative bonus, +1 to attacks, and will do 1d8+1 worth of damage if the attack hits. The Cleric will not attempt to heal any damaged comrades as I don't expect the enounters to last long enough for that to matter.
The Fighter
Has an AC of 16, 1d10+2 HP, +2 to intiative, +2 to attacks, and will do 1d8+2 worth of damage.
The Thief
Has an AC of 13, 1d8+1 HP, +2 to intiative, +2 to attacks, and because of the strategy of the other players (“run up and hit”) the Thief can use their “Sneak Attack” feature to do an addtional 1d6 worth of damage, on top of the 1d4+2 of damage normally done (here, the Thief will always use a dagger).
The Wizard
Has an AC of 10, 1d6 of HP, +2 to intiative and no bonuses to attacks. Normally, wizards would be in the back of the party doing ranged attacks, but because I didn't want the complication of ranged attacks, the Wizard is right up front and close. But I do allow the Wizard the use of two Magic Missiles (the maximum allowed for that spell, which always hit) for the first two rounds (each doing 3d4+3 damage), then Fire Bolt (which does 1d10, but doesn't always hit).

These are pretty bog-standard 1ST level characters. I then went through picking out a few CR1 monsters to throw against the party. The unfortunate enemy victims include:

Animated Armor
Has an AC of 18, 6d8+6 HP, no initiative bonus, +4 to attacks, and does do two attacks of 1d6+2 of damage.
Bugbear
Has an AC of 16, 5d8+5 HP, +2 to initiative, +4 to hit, doing 2d8+2 worth of damage.
Goblin Boss
Has an AC of 17, 6d6 HP, +2 to initiative, +4 to attack, and gets two attacks, the second of which is at disadvantage both of which do 1d6+2 worth of damage.
Half Orge
Has an AC of 12, 4d10+8 HP, no intiative bonus, +5 to attack, which does 2d10+3 damage.
Lion
Has an AC of 12, +2 to intiative, +5 to attack, and does 1d8+3 worth of damage.

And because it wouldn't be D&D without the dragons, there's one dragon at CR1—the Brass Dragon Wyrmling (a baby brass dragon):

Brass Dragon Wyrmling
Has an AC of 16, 3d8+3 HP, no initiative bonus, a +4 to attacks which does 1d10+2 damage, or a breath weapon which can do 4d6 worth of damage if the victim can't jump out of the way (but only has a 1 in 3 chance of regaining per round of combat).

For the Brass Dragon Wyrmling, I decided to have it lead with its breath weapon always, and prefer the use of its breath weapon when it recharges, but if not, do a normal attack.

It's not every CR1 monster, but I think it's a decent list to start with, and it should give me a feeling for how this “Challenge Rating” system is supposed to work.

On with the simulation!

10,000 battles between a 1ST level party and some CR1 monsters
monster TPK% #rounds #lived
Animated Armor 28.23 4 2
Brass Dragon Wyrmling 0.36 3 3
Bugbear 4.81 3 3
Gobin Boss 1.18 3 3
Half Orge 2.56 3 3
Lion 0.72 3 3

Well … [Deep subject. —Editor] I'm not sure what to make of the results. Either the simulation is crap, or the whole “Challenge Rating” system is crap. I've heard that it tends to break down at the higher levels, but even here, it doesn't seem to work. A baby brass dragon is less dangerous than a lion? An empty shell of armor is the most dangerous monster? What?

Okay, about those columns—the TPK column is the percentage time the entire party was wiped out by the encounter. The last column is if the party killed the monster, on average, now many party members were left standing? (rounded to the nearest whole value)

So then I decided to throw some other monsters into the mix. And in keeping with the “dragon” portion of D&D, I found a dragon of CR2, CR3 and CR4 (and used the same strategy I used for the Brass Dragon Wyrmling—leading with the breath weapon). And because I'm just mean, I decided to throw in one of the weakest creatures of D&D into the mix—a single kobold. Behold:

10,000 battles between a 1ST level party and some non-CR1 monsters
monster TPK% #rounds #lived CR
Kobold 0.00 2 4
Black Dragon Wyrmling 27.83 4 2 2
Blue Dragon Wyrmling 71.86 6 1 3
Red Dragon Wyrmling 98.36 6 0 4

To be fair, there is a chance for one party member to be killed by the kobold, as the actual average for the number of party members surviving is 3.93—a single kobold is not a complete cakewalk. And there's a slightly better than 1% chance of killing a baby red dragon as a 1ST level party (better than I expected). But somehow, it still feels wrong that some animated armor is still a bit more dangerous than a black baby dragon.

I guess I'll just have to throw my group (a mix of 5TH to 7TH level characters) in front of an ancient red dragon and see what happens … oh wait, did I mention that out loud?

Wednesday, August 18, 2021

A serious lack of power

I walked into the Computer Room at Chez Boca to a squealing UPS, but unlike last time this happened the computers were still powered up. I shutdown both computers and decided to deal with them after lunch. There wasn't much else I could do at that point, seeing how the power was out for our entire neighborhood.

After lunch, the power was restored, so I went to power up the Linux box and … it didn't come on.

XXXXX­XXXXX­XXXXX­XXXXX­XXXXX­XXX!

I checked the internal cables to make sure none have come loose, evicted multiple dust bunnies, and even changed the CMOS battery just to be sure. But nothing I did made the Linux box power up.

I called my friend Tom Singkornrat (not only is he wise in the way of hardware, but he lives less than a mile away) and he said that it could be one of two possible reasons—it could be a bad power supply, or it could be a bad mother board. He had a spare power supply I could try. Why not?

The only difficult part of the whole procedure was unscrewing the old power supply from the case. Other than that, the new power supply fit right in and it powered right up. Great! But for some reason the keyboard wasn't working …

Update later today …

I found the issue with the keyboard.


The Keyboard situation

Okay, about that keyboard

The setup I have is … not straightforward. I have two computers, a tower running Linux and a Mac mini. I have a single keyboard and mouse plugged into a KVM switch (an industrial 8-port unit I aquired mumblely-mumble years ago), but each computer has its own monitor. I also run Synergy on both computers to allow sharing of the keyboard and mouse across both computers. It will also allow you to move the mouse from one computer to the other (and supports “cut-n-paste” operations between the two computers). It's a neat program and really, the KVM is there when I need to shutdown in the event of a power outtage (and when I boot the systems back up, before I get Synergy running).

The KVM expects PS/2 style connectors, but both computers need a USB converter. This all just works and I rarely have issues.

Until I do.

This time, it turned out to be the cheap USB converter on the Linux system that just … I don't know, gave up the ghost or something (thank God! I was fearful the USB ports might have been blown out). I can work around it with Synergy, but it's a bit of a pain initially (boot one computer, switch keyboard/mouse to other computer, boot that one, switch keyboard/mouse back to get Synergy running). So now that I'm back up and running, I just need to get a new USB converter and maybe this time it'll last longer than a year.


The Lord of the Rings as a D&D game

Ever wonder what The Lord of the Rings would be like as a D&D game? Well, neither did I until I saw this video series:

It starts out with a large group, then due to interpersonal conflicts, the game splits into the role players and the roll players, then they all get back together for the final boss fight.

And Frodo's player never did learn the D&D combat system.

Thursday, August 19, 2021

The case of the regression test regression

So the SVN-git conversion is back on the table. When I worked on this last year, I stopped when it became clear that a critical build server didn't support git. I duly reported the issue, and it's only been fixed in the past few months. Last year, it was delegated solely to me. This year, it's more of a team effort.

For our team, we currently have two main SVN repositories with some duplicate third party packages checked in. We went through the lists to remove the redundencies (a Good Thing™) and I felt that it might be a good time to ensure they're up to date. I spent a week doing so and ran into an odd issue—the old regression test now runs slower! Not thirteen (or nineteen) hours slow but slow enough to be seriously annoying. I was able to isolate the slowdown to some Lua modules (that I wrote cough cough—I didn't think the changes were that bad).

We do development primarily on Macs. My first thought was to either confirm or deny that the Mac was the issue. I ran tests on a Linux laptop I have for work and nope—the slowdown exists on that. I then tried to profile the code (to no conclusive result). I compared the code between the two versions (only five lines changed in the regression test, and all of those were small API changes like fsys.redirect(stdin,fsys.STDIN) becoming fsys.redirect(stdin,io.stdin)). I just could not figure out why the new code was slower.

So then I decided to just time things. I added code to time how long it took to run each test (and to limit the number of tests run—enough to show the issue, but not the entire 15,852 tests) and plot the results.

[Graph of the time to run each test from the old regression test and the new regression test.  The old one is faster.]

The X-axis is the test case number, the Y-axis is time in microseconds (and plotted on a logarithmic scale, otherwise, you wouldn't be able to make out any detail along the lower portion). The new regression test is in green, the old one in red. It's clear that there are a few dozen tests that take a full second to run in the new program, whereas the average (of both, aside from the outliers) seems to be around 5ms. So good, the problem clearly shows up.

Then I timed each section of running a test to see which section is sucking up the time, and eventually, I get this graph:

[Graph of the small segment of the test that is taking all the time.]

[The sharper eyed of you might have noticed the X-axis change—each test is run twice (for reasons). This means the second graph has twice as many entries. Yes, that means the full 15,852 tests are each run twice, for 31,704 requests. —Sean]

This represents the timing of this bit of code:

-- --------------------------------
-- Receive and process NOTIFY
-- --------------------------------

local remote,data = sipsock:recv(10)
if not data then
  return false,"no NOTIFY"
end

The only program that's different is the regression test, not the programs being tested. And it's not like I updated the version of Lua either—that didn't change. The third party code I'm using, yes, to some degree. But the underlying code to sipsock:recv() did not change. Yet it's this bit of code that is consistently slow for a consistent set of tests.

To say I'm a bit perplexed is a bit of an understatement.

Monday, August 23, 2021

I'm a computer illiterate dinosaur. Thanks, Microsoft!

All I needed to do was transfer a file to a fellow cow-orker. That's it. We were in a meeting, via Microsoft Teams. I was using the dreaded Corporate Overlords' mandated managed Microsoft Windows laptop. The file in question was on my work related Linux laptop (it was the first laptop I received when I started working at The Corporation 11 years earlier). So on the Windows laptop, I open up CMD.EXE:

Microsoft Windows [Version 10.0.18363.1621]
(c) 2019 Microsoft Corporation. All rights reserved.

C:\Users\sconner>cd Desktop

C:\Users\sconner\Desktop>scp spc@linux-laptop:work/file-to-trans .
spc@linux-laptop's password:
file-to-trans                        100% 6246KB  10.2MB/s   00:00

C:\Users\sconner\Desktop>dir
 Volume in drive C is Windows
 Volume Serial Number is 267D-3086

 Directory of C:\Users\sconner\Desktop

08/23/2021  06:55 PM    <DIR>          .
08/23/2021  06:55 PM    <DIR>          ..
08/23/2021  07:18 PM         6,395,862 file-to-trans
               1 File(s)      6,395,862 bytes
               2 Dir(s)  436,294,770,688 bytes free

C:\Users\sconner\Desktop>

I then open up File Explorer (sigh … that took entirely too long to find the name of that program), select “Desktop” and … the file is not there.

What?

Is the “Desktop” in the File Explorer not the same as “C:\Users\sconner\Desktop”? When did that happen?

My fellow cow-orker had to talk me through finding the file in question in the File Explorer, because “Desktop” there isn't the same one as “Desktop” in CMD.EXE.

What?

My brain broke.

Anyway, the file found, I then had to be talked through how to initiate a file upload through Microsoft Teams, and on this point, said fellow cow-orker and another fellow cow-orker had to work through how to send the file. Yes, apparently it takes three software developers to initiate a file upload through Microsoft Teams.

And then I had to describe to fellow cow-orkers that yes, this will take some time because I'm behind an honest-to-God DSL connection and NOT a multi-gigabit ethernet connection, because Chez Boca exists outside the service area for anything faster. It took several minutes of convincing them of this.

And the upload failed, probably because I'm behind an honest-to-God DSL connection and NOT a multi-gigabite ethernet connection.

Seriously, how hard is it to transfer SOME BITS?

So, not only did I have trouble with sending a fellow cow-orker a file, I somehow destroyed CMD.EXE's ability to display text as I was writing this entry. WTF? All I was trying to do was find a way to cut-n-paste the text from CMD.EXE and somehow, I manged to XXXX CMD.EXE so bad, it wouldn't show text any more. Several minutes later, I got the text back up (how? XXXX if I know) but now the cursor is missing.

XXXX it! I can deal with that.

<slow-clap>

Way to go, Microsoft!

But when did I become so computer illiterate?

Tuesday, August 24, 2021

All your CPUs belong to us

As if writing software without exploits is hard enough, now we have the most popular computer architecture, the Intel x86 line of CPUs, with a potential hole large enough to drive the NSA through. In a DEF CON talk, Christopher Domas shows how he found an exploit on a particular version of the x86 CPU that allowed him to gain total control over the computer without the operating system even knowing about it. All it involved is one undocumented instruction that enables access to a hidden CPU inside the x86 CPU (or rather, perhaps allow direct access to the underlying core that is simply interpreting the x86 ISA) followed by multiple copies of an x86 instruction that actually feeds instructions directly to this inner CPU that bypass all system checks because this inner CPU has access to everything (from user mode, and if you understand that statement, you know how bad it is).

As mentioned, this is only for a particular x86 implementation, but who knows what evils lurk in the heart of CPUs?

Probably the NSA.


The case of the regression test regression, part II

When you have eliminated the impossible, whatever remains, however improbable, must be the truth.

Sherlock Holmes

When last I left off I identified the slow code in the regression test and it left me puzzled—it was a single function call that did not change between versions. Now, a bit of background: eight years ago [Eight years⁈ Where did the time go? —Sean] [A world wide pandemic. —Editor] [Gee, thanks. —Sean] I wrote a custom Lua interpreter that contains all possible Lua modules we could possibly use at work in order to avoid having a bunch of code to install, which I call kslua (which stands for “Kitchen Sink Lua”). And so far, that's what I've been using to run the regression test.

Faced with the fact that the sipsock:recv() call was taking upwards of a second, I decided update just that module to the latest in the fast version of the regression test as a sanity check. Well, it failed as a sanity check, because the latest version of that module that contains that function ran fast, so my sanity wasn't saved one bit. The only conclusion I can come to is that something else has changed!

Fortunately, somethine else has changed. A bit more background: the regression test is used to test “Project: Sippy-Cup,” “Project: Lumbergh” and “Project: Cleese.” And to run those programs, I need a few more programs that those programs communicate with, and oh hey! There's a program that the regression program runs that also runs via kslua! And through a tedious process of elimination, I finally found a module that causes the slowdown—the network event driver module I wrote. I then went through a tedious process of elminiation to find the exact change that causes the slow down. The “fast” version of the function in question, which is written in C, is:

static int polllua_insert(lua_State *L)
{
  pollset__t *set = luaL_checkudata(L,1,TYPE_POLL);
  int         fh  = luaL_checkinteger(L,2);
  
  lua_settop(L,4);
  
  if (set->idx == set->max)
    /* ... */

and the slow version, which is the next literal version of the code:

static int polllua_insert(lua_State *L)
{
  pollset__t *set = luaL_checkudata(L,1,TYPE_POLL);
  int         fh;

  lua_settop(L,4);
  
  if (!luaL_callmeta(L,2,"_tofd"))
  {
    lua_pushinteger(L,EINVAL);
    return 1;
  }
   
  fh = luaL_checkinteger(L,-1);

  if (set->idx == set->max)
    /* ... */

I got tired of having to write (in Lua):

SOCKETS:insert(sock:_tofd(),'r',handler)

so I changed the code to call _tofd() directly:

SOCKETS:insert(sock,'r',handler) -- the system will know to call _tofd()

The only thing is—the program that calls this only calls this once in the program.

At startup.

Desk, meet head.

So I'm again failing to see how this causes the slowdown. I use the “fast” version and the regression runs fast. I click the version of that module one step forward and it's slow.

It's maddening!

Wednesday, August 25, 2021

The case of the regression test regression, part III

When I last left off I identified the slow code in the regression test and it left me puzzled—it was a single function call that was called during startup and not when the tests were running. Faced with the fact that I had identified (for a second time) that code that did not change was causing a second of delay, I decided to change my approach. Instead of starting with the working, fast version of the code and going forward, I would start with the current, slow version of the code and work backwards. The first point of business—see if I could reproduce the fast code/slow code change with the code I identified as a sanity check. And of course that sanity check failed as both code versions were now slow.

What was that Sherlock Holmes quote? Ah yes, “When you have eliminated the impossible, whatever remains, must be the truth.” Must be the computer hates me.

Okay, so now that the slowdown was not the regression test script, but one of the mocked services. So I did to that script what I did to the regression test script—record how long it takes to handle a query. And of course it always responded in a timely fasion. No second long delay found at all!

So the delay is not in the regression test. The delay is not in the mocked service. I am slowly running out of ideas.

Okay, time to take stock: what do I know? Some queries are taking up to a second to run. They appear to be the same tests from run to run. Okay, let's run with that idea.

I modify the regression test to kick out which test cases are taking over 900,000 microseconds. I then just run those tests and yes, it's consistent. I remove those slow tests, the regression test just flows. If I just run the “slow” tests, each one takes about a second to run.

So now I know it's consistent. What's consistent about them?

Now I start digging into the logs and … yeah … something odd is going on with those tests. It's a path that “Project: Lumbergh” can take, and it's hitting a mocked service that I keep forgetting about. I mean, the regression test starts it up, but otherwise, it's pretty silent (and pretty easy to forget about). I add some logging to this particular mocked service, run the regression test and see that it responds once, then nothing ever again.

I add logging to the “fast” version and yes, it gets hit, and keeps responding.

I check the differences between the two versions:

[spc]saltmine-2:~>diff path/to/slow/version path/to/fast/version
96c93
< nfl.SOCKETS:insert(sock,'r',function()
---
> nfl.SOCKETS:insert(sock:fd(),'r',function()
106c103
< nfl.server_eventloop()
---
> nfl.eventloop()
[spc]saltmine-2:~>

Yeah … just some API updates, like yesterday. But if I run the new regression test while running the older version of this one mock, the new regression test runs as I expected. The delay is actually coming from “Project: Lumbergh” because the new version of this mocked service doesn't respond properly, causing “Project: Lumbergh” to time out, thus the delay I'm seeing.

I think I'm finally getting somewhere, but why is it so hot? And what am I doing in this basket?

Thursday, August 26, 2021

The case of the regression test regression, part IV

Like all bugs, it was a simple fix once identified—it was just identifying the bug that was difficult. The bug was due to a semantic change in an API. Lua has a file interface that includes a read() function, and the parameter it's given dictates how much to read. One of the parameters is “a” (or “*a” if you are using Lua 5.1) that indicates you want to read all possible data until the end-of-file is reached.

I ended up writing my own read() function to deal with network activity. I couldn't just open up a normal Lua file object with a network connection because that doesn't work nicely with event driven programs. An earlier version of my read() function had a different semantic meaning with “a”—it just returned any buffered data. It was in a later change where I aligned the semantics to match Lua's semantics, but forgot to change that bit of code in the one component. And those semantic changes explain the behavior I was seeing yesterday. It only took what? A week? To find the culprit.

Now the regression test with the updated code runs as fast as the previous version.

Saturday, August 28, 2021

A most persistent spam, part III

Earlier this month I nuked two email addresses being spammed by Alekandr and wanted to wait to see how things go. Two weeks later and Aleksandr (all “his” emails came from the same domain but from different subdomains) are still being sent, still being delayed by my greylist daemon only to be rejected because the destination email address no longer exists. I'm surprised that they are still attempting to deliver the emails. Is it that Aleksandr doesn't care if the emails make it or not? I noticed that the IP addresses are changing more often now—is it a test to see if the IP address being used is blocked? Is it a smear campaign against Aleksandr? What is the end game here?


The script kiddies have come to Gemini

Logging of just about anything on a Gemini server is, within the Gemini community, a contentious issue. Most people using Gemini dislike the web and the intensive logging of everything done with in, so of course they go overboard in the other direction. I've never agreed with that viewpoint and I do log information, even potentially personally identifiable information like IP addresses, because of crap like 5.252.227.126 is doing—repeated (and quite maliciously) trying to crawl my Gemini server for exploits.

And it would be one thing if it were well written, did a single scan, not find anything and move on. But it's not well written (hell, even commercial bots aren't well written and well behaved) and it repeately requests the same page over and over again. Until I blocked it, it had requested /index.php over 700 times. A sample:

Requests from a badly written Gemini bot that started just today
count request
722 gemini://gemini.conman.org/index.php
721 gemini://gemini.conman.org/test/torture/index.php
86 gemini://gemini.conman.org/login.php
86 gemini://gemini.conman.org/test/torture/login.php

Among other requests.

And even now, several hours after I blocked it, it's still trying to make requests even though it's now getting the “no such port” error from the server. I just have to wonder if it's just too cheap to run these bots that it doesn't matter if they don't work all that well. Just enough to keep going and finding exploits. And hey, just becuase now we can't get that page doesn't mean it won't exist in 20 minutes, so keep making those requests.

Sigh. This is why we can't have nice things on the Internet.

More broadly though, I'm not sure what this heralds for Gemini. On the one hand, it's popular enough to attract the script kiddies to check for exploits. On the other hand, there's a large number of different servers so exploits for one server won't necessarily imply a globally workable exploit. And on the gripping hand, the fact that it's easy to write a server means the likelihood of an exploitable server is high.

But hey! Gemini hit a milestone! Script kiddies have hit the scene and now we have to contend with their crap! Woot!

Monday, September 06, 2021

Expanding a program from the past

I will start with a disclaimer: this post might be of interest to only two other people, neither of which read my blog (as far as I know). But it's my blog, and I don't care. I find it interesting. Anyway, on with the post.

I was playing around with an old program that plots a chaotic attractor. I won't pretent to know what the chaotic attractor is supposed to represent, but I find it fun to poke around the program from time to time. It revolves around two equations that interact with each other:

xi+1 = (Ayi + B) xi (1 - xi)
yi+1 = (Cxi + D) yi (1 - yi)

with the resulting image x and y values plotted on the graph between 0,0 and 1,1:

[Graph of output where A=2.4376, B=1.5624, C=0.8659 and D=4.0] Yup, still looks like an alien French horn.

But then I got wondering—why the unit square? Thirty years ago I never questioned that. It should be easy enough to find out—just change the output range a bit:

[Same output as before, except ¼ the size due to the extended range] And I can just hear Grover, way off in the distance, yelling “Far!”

Cool! I now have the range from -1,-1 to 1,1 working. So whereas before, I would have seen:

[For those curious, this is A=-0.4369, B=-1.6109, C=-3.1058 and D=-1.5358] Crashing waves?  Overlapping mountains?  Just a bunch of white dots in a black background?

I can now see the full extent of this particular result:

[Same as above, only from -1,-1 to 1,1] Perhaps a transdimensional tri-cornered hat?  I don't know, it's a Rorshach test on acid!

And otherwise dull plots in the 0,0 to 1,1 range are now full of detail:

[I don't have correct values for this plot—it's too chatoc to reproduce.] When I came across this image, I recorded the values of A, B, C and D. But at the time, I was running with the output and control windows as large as they could get, but the values I recorded were only to four decimal places. Upon trying to revisit this shape, it wasn't what I originally saw. That means I didn't record the values correctly, or more likely, due to the chaotic nature of these things, the results are so dependent upon upon the actual values that four decimal places aren't enough. It was such a result in the 60s from scientist Edward Lorenz that lead to the creation of Chaos Theory.

I am now left to wonder if this would have affected the research this program supported?

Wednesday, September 08, 2021

A map to a four dimensional space

In addition to expanding the output of an old program, I have also been expanding the mapping of the chaotic system (and like the last post, this post will have a very limited audience but again, I don't care). So this image:

[A plot of a chaotic system] I'm not even sure how one plays this alien French horn.

is generated by iterating these two equations:

xi+1 = (Ayi + B) xi (1 - xi)
yi+1 = (Cxi + D) yi (1 - yi)

with the following values:

This image:

[Horizontal axis is A from -4 to 4; vertical axis is B from -4 to 4] It looks like something you might see on a Star Trek episode accompanying a ton of technobabble.

is a type of map where one can find chaotic attractors. It's a 2-dimensional slice of a 4-dimension space, where the horizontal axis is A, which runs from -4 (on the left) to 4, and the vertical axis is B, which also runs from -4 (on the bottom) to 4. If you look closely, you can make out a small red cross in the upper right hand area that marks the spot where the chaotic attractor above can be found in said space. Along the bottom, you'll see the four values listed above, with “Ax” marking the attractor location along the horizontal axis, and “By” marking the location along the vertical axis. The brighter the area, the more … um … expansive the chaotic attractor becomes.

But unlike thirty years ago, I decided to slice this a few different ways. If you imaging the above image as a slice through a 3-dimentional cube, this is the image you'd see if you were looking straight down on the cube at a horizontal slice through the cube. Shifting your view to the front, where A still runs left-to-right, C now runs up-down, and we get a vertical slice through the cube:

[Horizontal axis is A from -4 to 4; vertical axis is now C from -4 to 4] A tachyon emission display perhaps?

Looking at the cube from the left side—B values now run along the horizontal, C is still up-down and we get another vertical slice:

[Horizontal axis is B from -4 to 4; vertical axis is C from -4 to 4] A plot of the power output from the dilithium crystals?

In each of those images, you should find a small red cross that marks the location of the attractor.

There are still three more planes we can cut through, although in this case, I can't quite make out the front, side or top. One is the A-D slice (and in each of the following images, you can make out the cross along the top edge):

[Horizontal axis is A from -4 to 4; vertical axis is D from -4 to 4] We're not in Kansas anymore …

The second is the B-D slice:

[Horizontal axis is B from -4 to 4; vertical axis is D from -4 to 4] … reality is breaking up!  Oh no!

And the final one is the C-D slice:

[Horizontal axis is C from -4 to 4; vertical asix is D from -4 to 4] … Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn … aaiiieeeeeeeeee!

Yeah … D ends up being vertical in all three … and that … kind of … makes sense … to me. Or am I going crazy? This is 4-dimensional space we're talking about.

Tuesday, September 21, 2021

Science with explaination

I finally have closure.

Sixteen years ago [Sixteen years‽ Yikes!] I did some experiments with my car's keyless entry fob and found that yes, increased the effective distance of said fob out to about 90′ (30m for those who are Imperially challenged). At the time, I had no clue as to why, but this video (which was released yesterday) has a decent explanation for the phenomenon.


Notes on an overheard conversation while leaving a doctor's office

“There! Your flu shot is over with. That wasn't so bad, was it?”

“What? You didn't hear my blood-curdling screams?”

“No.”

“Hrm. They must have good sound-proofing in the stabity-stab room.”

“I bet it didn't hurt at all. I didn't feel it when I got my flu shot.”

“It was the pain of a thousand suns searing through my skin.”

“That was just the alcohol wipe.”

Friday, September 24, 2021

Great, now I have to train my next manager, part II

It's time for another reorganization at The Corporation! Woot!

I've lost count of the number of reorganizations and for the most part, they rarely affect me, but this time it's different—I'm getting a new manager! It's only been eleven months since my last new manager.

This will be … um … carry the one … the eighth manager I've had at the Ft. Lauderdale Office of the Corporation since starting. And that works out to be … goes into … carry … subtract … 18 months per manager. Not quite to the level of the Defense Against The Dark Arts position, but close enough to leave me worried. I have to wonder if some malevolent force cursed my department's manager position.

Tuesday, September 28, 2021

You could add crypto to gopher, but I think it's a hack

I received the following email today:

From
Trevor Clarke <XXXXX­XXXXX­XXXXX­XXX>
To
sean@conman.org
Subject
Secure gopher comment
Date
Tue, 28 Sep 2021 16:21:10 -0400

I just read your post http://boston.conman.org/2019/03/31.1

About the difficultly of adding TLS to gopher. I don't think it's as bleak as you suggest. A client supporting secure gopher simply sends a TLS client hello packet when first connecting to the server. If it receives nothing or receives something that is not a valid server hello it drops the connection and switches to regular gopher for that server. To minimize the number of failed attempts the client can cache the type of server during a session or persist the status for a period of time before trying again.

As I wrote back, this is already being done by clients as can be seen from my gopher logs:

Sep 28 09:10:44 daemon info 71.19.142.20 gopher remote=XXXXXX.1.36 status=false request="223120101…" bytes=82
Sep 28 09:10:44 daemon info 71.19.142.20 gopher remote=XXXXXX.1.36 status=true request="Gopher:Src:port70/handlers/" bytes=505
Sep 28 16:44:41 daemon info 71.19.142.20 gopher remote=XXXXXX.1.36 status=false request="223120101…" bytes=82
Sep 28 16:44:41 daemon info 71.19.142.20 gopher remote=XXXXXX.1.36 status=true request="Phlog:2004" bytes=533
Sep 28 18:04:43 daemon info 71.19.142.20 gopher remote=XXXXXX.1.36 status=false request="223120101…" bytes=82
Sep 28 18:04:43 daemon info 71.19.142.20 gopher remote=XXXXXX.1.36 status=true request="Bible:" bytes=10647

There's also a trick that servers can do to “seamlessly” support TLS—peek at the initial packet for the start of a TLS connection, and if it doesn't match, then fall back to the normal TCP routine. There's also the posibility of a downgrade attack to prevent the client from successfully using TLS.

I'm not a fan of either of these approaches. On the client side, it makes (potentially annoying) extra requests that for the most part, will be a waste of time as not many gopher servers (to my knowledge) support TLS. And on the server side, it's a hack to peek the initial packet of data (it can be done on some systems, but I don't know if all TCP stacks support peeking at the data before reading the data).

I also mentioned that one of the major complaints about the Gemini protocol, a somewhat reimagining of gopher but with mandatory TLS, is its use of TLS. Go figure—there are people who want to add TLS to gopher, and people who want to remove TLS from Gemini.

Wednesday, October 13, 2021

Alphabet soup

So we have this new project at work, ERAS. It's an ETLA that stands for “ECID ReST API Service,” which itself contains a few ETLAs that, when fully expanded, becomes “Enhanced Caller Identification Representational State Transfer Application Programming Interface Service.” If you have to ask, it's not worth knowing, and if you don't have to ask, I'm sorry.

I don't know whether to laugh or cry.


Notes on an overheard conversation from 25 years ago about TLAs (and yes, this really did happen)

“What was that term you just used?”

“What? TLA?”

“Yes. What does it mean?”

“It's a ‘Three Letter Acronym.’”

“Yes, but what does it mean?”

“A ‘Three Letter Acronym.’”

“… and it means … ?”

“…”

“…”

“Tee—three, el—letter, ay—acronym.”

“But what does … oooooooh!”

“Thank God I didn't mention ETLA …”

“What?”

Monday, October 25, 2021

Notes on an overheard conversation while driving home

“Oh my! The freeway may be an incredible invention, but it was never designed for two objects to occupy the same space at the same time!”

“Physics wasn't designed that way either!”

Sunday, October 31, 2021

Merry Samhain's Day everybody!

                           Jgy__
                         jWW  `""9Wf
                       _#WWW     IW
                      jWWWWW     IW
              __,yyyyyWWWWW     IWyyyy___
         _jyWWP"^``"`.C"9*,J _.mqD:^^"WWWWWWQg__
       jgW"^.C/"    .C'     I    `D.     'D._"WQg_
     jWP` .C"       C'      I     `D._     `D._ "Qg_
   jQP`  .C    ,d^^b._      I      _.d^^b.   `D._ "Qg
  jQ^  .C"   /`   .+" \     I     / "+.   `\   `D.  XQ
 jQ'  .C'   |`  ."    )    _I    (     ".  |    `D.  4#
 Qf  .C     (   (    /    / /\    \     )  )     `D.  Qg
jW   C'      \__\_.+'    / /  \    `+._/__/       `D  jQ
Qf   C         C        /_/    \         D         D   Qk
Qf   C      _  C        \_\____/         D  _      D   QF
QL   C      \`+.__     _______     ______.+'/      D   QF
B&   C.      \   \|    ||     |    ||      /       D   Qf
jQ   `C.      \   |____|/     |____|/__   /      .D'   jW
 TQ   `C.      \._   `+.__________/___/|_/      .D'   jQ`
  9Q   `C.      C.`+._           |   |/.D'     .D'   jQ'
   "Qg  `C.     `C.   `"+-------'   ' .D'     .D'   pW`
    ^WQy `C.     `C.        I        .D'    _.D' yW"
      ^9Qy_`C.    `C.       I       .D'   _.D jgW"
         `9WQgC.__ `C.      I      .D'  _.Dp@@"`
        ilmk `""9WQQggyyyyyygyyyyyQggQWQH""

Ah, it's that time of year again, when the veil between the worlds is thin and we protect our young by forcing upon them a sugar coma so the spirits would have to physically lug them back through the veil. It works, because frankly, who would want to lug a bunch of comatose kids?


Perhaps the time of Trick-or-Treating is now past

Two kids.

Just two measly kids.

Who arrived at our door chauffeured in a van.

What is up with parents these days? Aren't they concerned about the spirits sniping their kids through the thinning veil?

Or maybe … just maybe … there are no kids in our neighborhood! Oh my!

Monday, November 01, 2021

So where do Floridians vacation in winter time?

During the colder seasons, most people head south for vacation. But Bunny and I already live in the south where it's hot and humid, so when we vacation, we head north! Yup, Bunny and I are back in Brevard, staying yet again at the The Red House Inn. Twelve hours of solid driving, then hauling our luggage up fourty-seven million flights of stairs later, and everything hurts, even our hair. But we're here, and we're settled in for a much needed vacation, as we skipped last year due to the human malware going around.

Now, given that I haven't been to the Ft. Lauderdale Office of The Corporation in well over a year, I probably could have just taken two days off (one to drive up here, and one to drive back) and worked remotely from Brevard, but I really need the time off from work to meditate on the cultural differences in development our Corporate Overlords are now pushing down on us.

So yeah, Bunny and I are in Brevard, where it's currently 50° (or 10°C for you Imperially challenged) and for us who hail from South Florida, it's quite brisk (read: cold) indeed.


Extreme parking, Brevard NC edition

Bunny and I were walking through downtown Brevard, killing some time until our reservation at Marco Trattoria when we saw this car just stop in the middle of the road, sit there for a bit, then shut off, and the driver just get out of the car!

[A car that is parked in the middle of Main St.] In the actual rules of Monopoly, there is no monetary reward for landing on Free Parking.

It's not like every street parking spot was taken up, no—there were still spots available. But I guess it was just more convenient to park in the middle of the street.

Wow!

Tuesday, November 02, 2021

Today must be the eighth day of the week

It's a known fact that Brevard rolls up the sidewalks pretty early in the evening. About half the restaurants close by 8:00 pm, the rest about 9:00 pm with maybe one or two open past that (like The Waffle House of course).

So to give us a bit of time, Bunny and I decided to try the new Brevard Diner, which states it's open from 6:00 am to 9:00 pm. We leave about 7:30 pm, and less than five minutes later, we're pulling up to a building sitting in an empty parking lot and no lights on. The front door reads “Open 6:00 am—9:00 pm Seven Days Per Week.”

Sigh.

I guess the human malware has made things a bit more unpredictable around here.


Extreme home renovation, Brevard edition

Two years ago the house across the street from The Red House Inn burned down, leaving a field of smoldering embers. Today, there are four new houses:

[Four newly build houses in a row, all different.] Black wrought iron fencing is the new white picket fencing.

It's not terribly surprising that they went up quite fast, as they were all built by the same developer. But it is surprising that they're all different, and both Bunny and I love that.

Wednesday, November 03, 2021

Extreme service, Brevard edition

While Bunny and I were out for lunch today, we came across this unfortunate soul:

[A skeleton sitting at a lunch counter with an arm outstretched.] “Hello? … Anybody? … At this point I just want a Coke. Also, does anyone know who won the World Series?  Did the Chicago Cubs win?”

On the plus side, the food was good!

Thursday, November 04, 2021

Extreme social bear distancing, Brevard edition

Bunny and I were walking through downtown Brevard when we came across this sign reminding us of our duty to social distance in these times of human malware:

[A graphic showing social distancing as being the size of a bear.] Do NOT offer the bear a Coke. This is only effective against polar bears. Also, I don't have to out run the bear, I just have to offer YOU to the bear.

Also handy to keep in mind: how to survive a bear attack.

Friday, November 05, 2021

Observations of a few oddities at night

A phoenomenon I haven't encountered for years is static electricity sparking in blankets. You just don't get that in Lower Sheol due to the high humidity.

Another odd phoenomenon that has happened twice now here in the The Red House Inn (and it will sound odd, but … ) is the bed shaking in the wee hours of the morning. The first time it happened, I woke Bunny up and she too, could feel the bed shimmying. Back home at Chez Boca, this happens from time to time, but the affect is milder, and is due to freight trains rumbling by (we live a bit over ½ mile (0.8k, again for the Imperially challenged) from the railroad favored by freight trains). But there are no freight trains in Brevard—there are no railroads in Brevard! I'm hoping there's a rational explanation for it besides an earthquake. Anything but an earthquake! I'd even accept a haunting!

But no earthquakes.


Extreme indoor forestry, Brevard edition

For dinner, Bunny and I went to the Jordan Street Cafe in downtown Brevard. We went for the rhubarb pie, but instead we found a tree:

[A live tree inside a restaurant] At least it provides shade against the restaurant lights as it looms large overhead.

In all seriousness, we did go because we heard the rhubarb pie was incredible, but with rhubarb being out of season, it was not to be.

We did have dinner there, and while the food was excellent, the service was … odd. It serves upscale food, but you order it at a counter, then sit and wait for your order. It was a long wait in line as chaos seemed to reign over the place. And it was a long wait for the food to arrive.

In our opinion, the long wait didn't justify the food, despite how good it was.

Saturday, November 06, 2021

Extreme doors of perception, Roanoke, Virginia edition

Bunny and I partook of a secondary road trip today, driving 275 miles to Roanoke, Virginia for our second visit to Black Dog Salvage. Unlike our last visit where the TV cast were out salvaging, this was an “open house” so they were there. Not that we saw much of them—we only saw one TV cast member but he was too busy to stop and chat (although he did say “Hello!”).

We did, however, get lost in a large hallway full of doors:

[A hallway full of doors. No, really, they're stacked on each other] You might think there's a mystery behind every door, but no, it's no mystery—it's another door.

But don't say we weren't warned though:

[Picture of a sign that says “MORE DOORS”] I wasn't kidding when I said there were more doors.

And yes, there were a lot of doors.

[A picture of more stacked doors in the door corridor] But it's the type of place where you could expect “opening” a door might lead to some other world, but I'd rather not let in a despotic queen into our world.

We did manage to find a door that lead out.


Observations of a few oddities, this time on the Intarwebs

Two observations about previous post:

  1. While at Black Dog Salvage Bunny took a picture of me standing next to a large slab of cherry wood (price—a cool $800, and that wasn't the most expensive slab of wood) and then we went on to get lost in the Hall of Doors.

    Once we got back to Brevard, I started noticing online advertising for slabs of wood. I wish I was making that up, but no, I started receiving ads for slabs of wood. I'm hoping it was because Bunny and I watched a few wood working videos on Youtube and not because of a picture Bunny took of me.

    But I'm not holding my breath.

  2. I use Duck Duck Go as my search engine. While I was writing the previous entry, I used Duck Duck Go to search for the Black Dog Salvage Company website. The first link, I click, and I'm redirected directly to some spam pharmacy site wishing to extend my mortgage by 3″ (or 8cm for those Imperially challenged).

    Hmmm, I thought, perhaps they let their domain expire.

    Curious, I go back to a previous entry just to check the link there, and no, it goes to the Black Dog Salvage site.

    Now I'm paranoid. I check the link on Duck Duck Go, and it's https://www.blackdogsalvage.com/. I check the link on the Black Dog Salvage site I'm viewing, and it's https://www.blackdogsalvage.com/. It's the same text! I have no idea what to think! Perhaps some black arts to game the results in Duck Duck Go? I don't know.

Okay, I decided to dig a bit deeper into that last one. I used Google to search for “Black Dog Salvage,” clicked on the obvious result and … ended up at that same sketchy pharmacy site. Now I think that the Black Dog Salvage site has been hacked to redirect people to the sketchy pharmacy site when coming from a search engine, and not something wrong with Duck Duck Go or Google.

Sigh.


Notes on an overheard conversation at the Red House Inn

“Hello!”

“Hello!”

“Where did you get your take out food?”

“A Thai restaurant on east Main street called Love Eat Thai Kitchen. What do you have”

“We got this Mexican food from … oh … it has a weird name.”

“Yea, I think it's a Japanese place downtown.”

“Really?”

“Yeah, on Broad Street just south of Main.”

“That wouldn't happen to be ‘Quixote?’”

“Yes! That's the place!”

Sunday, November 07, 2021

Extreme white squirrels, Brevard edition

Bunny says I was a bit squirrelly today—I'm not sure what she's talking about.

[A picture of me as a white squirrel] Methinks I've spent too much time in Brevard as it appears I'm going native. Great! Now I have to watch out for Captain Willard coming up the French Broad River.

Monday, November 08, 2021

Extreme scurry of white squirrels, Brevard edition

Seriously, Brevard has a thing for white squirrels:

[A scurry of stuffed white squirrels] The invasion of alien white squirrels is nearly complete. We welcome our new white sciuridae overlords!

Tuesday, November 09, 2021

Extreme warning, Brevard edition

Bunny and I decided to check out some stores outside of Brevard, but I think we went a bit too far afield:

[Eight pottery heads, all sitting on metal staffs] “We were just trying to get a head, but there's no body left.”

Even Kim Jong-un seemed to be having second thoughts about coming out this far:

[The pottery bust of what looks like Kim Jong-un on a bed of rocks] “Wow dude! I'm stoned out of my head!”

We felt it best to head back to Brevard.

Wednesday, November 10, 2021

Extreme doors of perceptions, this time Highlands, NC edition

Another day, another mini-road trip. This time, to Highlands, North Carolina. An old friend lives in the area and we decided to drive out to have dinner with them. On the way there, we ended up in a small Mexican restaurant in Rosman for lunch (one of three restaurants in town as it turns out). Not bad, but the town of Rosman (population: 576 as of 2010) makes Brevard look positively metropolitan.

Then onwards to Highlands. Along the way, we came across a salvage place (sans website, else I'd link to it) and stopped. There, I found yet another stash of doors:

[A picture of more stacked doors] It was tempting to think that opening one of these doors would lead to Black Dog Salvage Company in Roanoke, but I think the only thing that would happen is I find more doors … or perhaps let in some pan dimensional beings, and that would be a Bad Thing™.

I'm sensing a theme here.

Anyway, we finally arrived in Highlands at 4:45 pm, which was bad since the entire town rolls up the sidewalks at 5:00 pm on the dot. Fortunately, Bunny's friend was at the restaurant, where a good time and good food was had by all.

After a few hours, it was time to drive back along US-64 to Brevard, in the dark. I had fun driving along the up-and-down widing road, but for Bunny, it was a white-knuckle experience.

Thursday, November 11, 2021

Extreme spices, Brevard edition

Today was a cold, miserable, rainy day here in Brevard, so we didn't get out much. But a few days ago, we did stop by the local Food Lion, the other grocery chain in Brevard. Whereas Ingles is the more upscale type grocery store, Food Lion is your … um … less expensive grocery store. So my expectations were pretty low.

What I was not expecting was to find actual turmeric!

[A picture of fresh turmeric] A mutant carrot or a mutant worm … you decide.

I've never seen fresh turmeric! Much less expect to find it in a … um … less expensive grocery store!

Friday, November 12, 2021

Extreme vinyl records, Brevard edition

It was much nicer today than yesterday so Bunny and I went shopping. At one of the stores, this vinly record caught my eye:

[A picture of the “Barbie Sing-along” vinyl record, with Barbie, Ken, and three kids, one of which is darker than the other two] ♫One of these things is not like the others, / One of these things just doesn't belong, / Can you tell which thing is not like the others / By the time I finish my song?♫

And now I'm curious as to what other horrors could be found in this pile of records?

[A picture of the “Growing Pains” soundtrack] Seriously?  They released a 90s TV show theme on vinyl?  There was market for this?  Who? No!  Wait!  I don't want to know! [A picture of a record with Fonzie on the cover] And you thought William Shatner was bad!

Those were the three worst I found, thankfully. I also found this album from Moms Mabley, a black comedienne popular in the 50s and 60s:

[Picture of Moms Mabley comedy album] A comedy album about Lincoln, Kennedy and King?  By a black woman?  This I have to hear!

Just a bit of triva: she was born in Brevard.

Saturday, November 13, 2021

Extreme parking lot traffic, Asheville edition

Bunny heard about The Vintage Market Days in Asheville, so we headed out today. I will say, getting in wasn't an issue—getting out was:

[a picture of a crowded parking lot] “Is there another way out?” “I don't know, parking lot designers are sadistic bastards.”

That isn't a line of parked cars. No, that's a line of cars attempting to leave the parking lot! It took us about twenty minutes to get out, and it only took us that long because we took advantage of a van that took too long deciding where to go and we cut ahead (to be fair, a number of other cars also cut ahead—we weren't the only ones to do this). I attempted to locate another exit, but the cell phone coverage was a bit spotty and I couldn't get a decent satellite picture of the parking lot in Google maps. Sigh.


Notes on an overheard conversation while driving and listening to Christmas carols

“Well that's an oxymoron!”

“What?”

“The lyric: ‘a winter wonderland!’”

“Oh. That's not an oxymoron.”

“Oh really?”

“Yes—you wonder why anyone would live in a winter land.”

Sunday, November 14, 2021

Extreme taxidermy, Brevard edition

It's our last day in Brevard (we're leaving tomorrow, back towards warmer climes) and we spent the day not doing much of anything.

But a few days ago we went into Mantiques, an eclectic antique shop with a more masculine bent to it, and well …

[A picture of half a taxidermied gazelle—at least it's the front half] I …I don't think leaving the front legs on added anything but disturbing dreams.

I can say with honesty I have never seen taxidermy quite like this.

And with that, we leave Brevard.

Monday, November 15, 2021

Extreme sales position every one is dying for, Brevard edition

Actually, one more picture, caught by Bunny as we were leaving Brevard this morming:

[Picture of a “SALES HELP WANTED” sign in a cemetery] “The customers are quiet and don't complain at all, but if they do, you do have permission to use a chain saw on them …”

It's a bit hard to see, but that “SALES HELP WANTED” sign is in a cemetery!

Yeah.

Anyway, we made it back safely to Chez Boca, and thus ends our 2021 trip to Brevard.

Tuesday, November 16, 2021

At least the vice president of our Corporate Overlords laughed jocularly when I answered “Too short” when he asked “How was my vacation?”

Ah, the first day of work after a two week vacation—6,000 emails to catch up on, mutiple fires actively burning, and the whooshing of deadlines as they fly by breaking the sound barrier. I'm not sure what's worse—this, or the freezing temperatures we left behind in Brevard. Aside from dealing with a week old request to reprovision our lab machines for the Oligarchic Cell Phone Companies, the most pressing fire was dealing with a possible change in “Project: Cleese.”

A proposed change in downstream processing with … oh … let's call it “Project: Waldo,” is stalled because the data needed for “Project: Cleese” to talk to “Project; Waldo” can't be generated fast enough. The data technically isn't needed for the proposed change in downstream processing, but to avoid changing “Project: Cleese” it was decided to generate fake data, and yes, said fake data can't be generated fast enough (seriously).

The fix is easy—it's just the removal of four lines of code (checking for the presence of the data, which now technically isn't needed), the modification of one other line (to deal with missing data), and it will just work. Alas, we're blocked by fellow cow-orker CZ (he works directly for the Corporate Overlords, and has been assigned to my team to make up for loss of employees in my department this past year) because of his extreme discomfort at changing any code outside of what has been planned. As was explained by several people, the changes won't affect the results at all, but CZ has yet to be fully convinced. It's definitely a culture clash between the Corporation and our Corporate Overlords

Yeah, my vacation was too short.

Sunday, November 21, 2021

Bad mood

I was not in a good mood today. It was bad enough that Bunny said I shouldn't be driving, so I ended up abandoning her (and the car) and walked home (for the record—I wasn't upset at her, just stuff that had accumuated over a few days which came to a head while I was trying refuel the car).

Once back home, I took some additional time to cool off by listening to some NIN (the album “Pretty Hate Machine”) at 11. Because 10 just wasn't loud enough.

I'm better now.

Monday, November 22, 2021

And to think I've been spelling my name wrong all along

I've always spelled my name “S,” “e,” “a,” “n.” Have been all my life, and I've been under the mistaken thought that that was the proper spelling of “Sean.” But it turns out, the proper Irish spelling is, in fact, “Seán” if this video is anything to go by.

Also, I learned that Sean Connery was not in fact the first actor to portray James Bond. No, that honor goes to American actor Barry Nelson (who played the spy in 1954!). Sean Connery is not the second actor to portray James Bond either—that goes to South African actor Bob Holness who played the spy in 1957 (for a radio dramatization of Moonraker).

So that makes Sean Connery the third actor to portray James Bond.


Tea, fluoride and brittle bones

I came across this video with the clickbait title of “How Much Tea Can You Drink Before Your Bones Crumble” and I got worried. I drink quite a bit of tea, and now I find out it can cause brittle bones? But having watched the video, the person in question was a lady who drank 150 cups of tea a day (or rather—every day she brewed a gallon of water with 150 tea bags and drank that) who ended up with skeletal fluorosis, caused by an excess of fluourine accumulating in the body.

It wasn't the fluourine in the water that caused the issue (and the video goes into the history of fluoridation—it does prevent tooth decay), but that and an excessive amount of flourine in tea caused the condition. It seems that tea is one of the few plants that will suck up flourine and concentrate it.

But I don't think I have too much to worry about as I don't drink anywhere near 150 cups of tea per day.

At least I hope …

Tuesday, November 23, 2021

Chilling to some 80s tunes

While it usually takes me loud angry music to get out of a bad mood, I should also remember the following music can also lift my bad mood:

For that last one, it doesn't have to be the actual New Order version—these two work as well:

Oh, this is indeed a deep rabit hole I can happily fall into …


Notes about a fragment of “Hotel Hack”

I received a nice email from a reader regarding A Fragment of “Hotel Hack”, written some twenty years ago wherein I mused about hypertext. The sad thing is that most (if not all) of the links I referenced have not survived. Yes, I could go back in and update the links, only for them to slowly rot again over the next two decades. Or perhaps changing the links to point to The Wayback Machine are in order (archived version with most links working—I've long since forgotten what I linked to).

Or perhaps I could change the links to a “director's commentary”—that might be an idea, but the commentary itself would dwarf the scant few paragraphs and might make for an interesting NaNoWriMo entry (even if it's not technically a novel). I mean, the commentary for “making him think he's Ethel Merman” would be something like:

Ethel Merman was a singer and actress in the mid 20TH century, known for her powerful singing voice. The reference here is not to Ethel Merman herself, but to a scene in the movie “Airplane” (1980), where Lieutenant Hurwitz had delusions of being Ethel Merman, and was played by Merman herself, breaking into song as orderlies tried to restrain her.

The movie “Airplane” was itself, a remake of the 1957 drama “Zero Hour!” which did not star Ethel Merman, sadly.

One could do a deep dive on all the references in “Hotel Hack”—Phone Cops, Boys from Bell, Leni's films, hoomei, tons of references to cover.

Maybe one day I'll get a round tuit.


Notes on an overheard conversation

“I have one thing to say about that Max Headroom stuff.”

“And that is?”

“Whatever works. For me, it's Beethoven's Ninth. Turned up to 11.”

Thursday, November 25, 2021

Happy Thanksgiving

I was about to post the ASCII art turkey when I thought I'd better check to see when I posted it last—last year, and back in 2008 and 2006. A quick search for Thanksgiving ASCII art isn't showing much, but I did find this one:

                    _
                   ' _<_\
                  /'/o)o)
                  \ \_/\/  ,-----------------.
        ,.-=--.-. |.(____\ |  Nothing says   |
      ;:_  \  |  `:.`---'  |     "Happy      |
   ,-'  `.  ' \    \\ / |  |  Thanksgiving"  |
 .'  -.   `_      __'|/ '| |  Like a Honey   |
,'     `.     ,,-'  | |  | |   Glazed Ham!   |
|'` .__   ,--'      | '`'\ `-----------------'
`._    _/'        ,/      |        ||_
|  `...'                  |--....,-'__\.__
`     |                 ,' \      -||  -:;
 |   |                `-'  ;       ||_;--"
 `.  |         |           |     ;-''
  `.  \___    /           /-._;,'
    ;,-'  ,  /           /
   /   ,-'_ / _'  |    ,'
  |  ,' ,' / :     \_,,'MJP
  | .'_' ,' ||      '.
  '/',;-' _ /\    --.` ..___
    '      ; .`--.   `\ _>.
         . ,' `\'.     \\'''
          '     -'      '

	-- Art by Michael J. Penick

And yes, I've done the glazed ham for Thanksgiving.

I also noticed I used a variation of “Gobble gobble” as a title last year, 2008, 2004 and 2002.

Well … [Deep subject. —Editor] nothing like blogging for twenty years to make fresh takes on Thanksgiving difficult.

I also don't think I can top last year's post about turkey drops, so I think I'll just leave you with the wish to have a Happy Thanksgiving with those you love, followed by a nice long nap as the tryptophan works through your system.

Friday, November 26, 2021

A most persistent spam, part IV

I recieved an email from new reader Emily asking about Alaksandr, the Russian sendmail spambot that was plaguing me for months. It seems that Emily is having to deal with Alaksandr and asked me for some help, having read my posts detailing the problem.

There wasn't much I could say. “Aleksandr” only went away once I removed the email accounts he was spamming, and a check of my logs showed it's no longer showing up here. But it appears to still be an issue for others. Emily and I still have no idea why someone would spend the time and effort to send such spams. I wish I had answers.

Wednesday, Debtember 01, 2021

Learning to sit back, relax, and enjoy the popcorn

It was decided that I would not change Project: Cleese and that the fake data would just have to be generated faster, despite it not technically being needed (I mean, it's fake data after all).

We are also stalled on an expansion of a current feature of Project: Lumbergh. The team lead has serious qualms about how it's supposed to interact with other features, even though it's not supposed to interact with other features as it's mutually exclusive with the other features. Unfortunately, there are some accounts with this and other mutually exclusive features, in production, and to me, it's clear it's an issue with provisioning of the accounts. But it's not clear to my team leader, nor may manager that this is the case.

And how many accounts are affected? Less than 300 out of 100,000,000. Or in other words, 1 out of 330,000 accounts (0.0003%).

The feature in question currently sends limited information about a call, and of all the “features” we have, this is the most limited in nature. The expansion will add information to bring it closer to par with the other, mutually exclusive features. I personally don't see an issue here, but it's above my pay grade. And now we're in a second round of gathering requirements on this.

I just have to learn to love the process über alles.


“Warthog. Delete word. Warthog. Delete word. Warthog. No, Dameon! Warthog! Duck ewe!”

[The title is a reference to the time Aden Oshea attempted to dictate a book he was writing to a computer. It fits the theme of today's post. —Sean]

We use Microsoft Teams at The Corporation. What I did not know is that The Corporation has tied our desk phones to Microsoft Teams. So when I logged on I noticed I had “voicemail.” I went to check that, and noticed that there was a transcription of the voicemail:

Hello, I'm not sure if this is the right number for XXXXX­XXXXX­XXXX and if it is this is a brother Maynard from the Church of Jesus Christ on Earth Day St and they were clerk and I see that XXXXX­XXXXX­XXXX moved from Jacksonville to the Hollywood area and we are trying to contact her and you live in or about the meetings on the meetings. Uhm, word cheap. It started at 9:00 AM. Uhm we sacrament meeting. Uhm thank you and if this is the right number please give me a call. Again this is brother manner. Me and a phone number XXXXX­XXXXX­XX. Thank you. Bye bye now.

It's a bit of a word salad, but I can see the gist of the message. I listened to the voice mail and yes, it's about as accurate as one would expect from someone with a heavy accent speaking English.

I'm now curious if he ever got a replacement for the Holy Hand Grenade of Antioch.

Monday, Debtember 06, 2021

It's still not easy adding crypto to gopher

I brought up gopher over TLS on the gopher mailing list today, and I learned of at least two new methods one could use to signal the use of TLS. They all have their issues though. So to recap the methods (in no particular order):

Running gopher over TLS over a dedicated port (currently in use)
Older clients will still attempt to use TCP to connect; this isn't enough of a signal to say “all these ports are yours, except 743—attempt no TCP there.” So older clients won't be able to connect, and could annoy operators with useless log messages.
Adding a flag past the port value
Again, older clients will ignore this, and it could possibly break the Gopher+ protocol. This might not be that much of an issue, as Gopher+ isn't that widely used to begin with.
Adding new gopher types for TLS
The the plus side, clients that don't understand the new types will safely ignore them. On the other hand, this could potentially double the number of valid gopher types. A variation on this would be to set the MSB of the type character to indicate TLS, but then you run the risk of using an undefined character, especially given that the majority of gopher sites now return UTF-8 encoded characters, and setting the high bit will generate invalid UTF-8, which will break any existing client written in Python3.
A new type of protocol (currently in use)
This exists—it's called Gemini and there are those who call for TLS to be removed from Gemini (for a variety of mutually exclusive reasons). Go figure.
Peek at the network stream for the TLS protocol(currently in use)
First off, the server would need to peek at the incoming packet to determine if it's a TLS and if so, kick the connection over to the TLS library du jour, otherwise, fall back to the TCP connection. This can fail due to an adversary forcing a regular TCP connection by filtering out the TLS traffic.
Signal TLS via the caps.txt file (currently in use)
There's not much documentation about caps.txt—there's an Internet draft that covers the format, but the actual specification seems to be this file from the creator of the specification. There is a field for TLS, but as it was pointed out on the mailing list, this is subject to a MITM degridation attack to force non-TLS.
Use DNS SRV records
There are several issues with this one—the state of DNS libraries was dismal enough that I wrote my own about a decade ago. Things might have improved since then, but this is something to keep in mind. Also, this is too, subject to MITM attacks, only at the DNS level, which is way easier to pull off.
Switch gopher to using TLS exclusively
Given this is a controversal topic for Gemini, I don't think this is a viable solution for gopher at all.

I think that covers all the methods. I'm of the opinion that gopher over TLS isn't worth the effort.


My blog on gopher is still a second class citizen, but it's getting better

Speaking of gopher, I've made it clear that the gopher version of my blog (as well as the Gemini version of my blog) are second class citizens. Since my last post on this matter, the formatting has improved a bit, but it's not quite there yet (the gopher version is okay at best, but the gemini version could use more work—more on that some other time).

But one thing that has improved is better support for displaying multiple posts. Granted, that feature is not used as much as I thought it would be, but I still wanted gopher and Gemini support. It took a bit of time, but I was able to get it working so now you can view my recent Brevard trip on one page on the web, on gopher, and on Gemini. And now in reverse chronological order: web, gopher and Gemini (well, you could always do reverse on the web since the beginning, it's just now I have support for the other two protocols).

All that's left is really thinking about reformatting the posts when “publishing” for gopher and Gemini …

Friday, Debtember 10, 2021

Working on legacy projects

The Corporate Overlords have assigned me to maintain “Project: Bradenburg.” It's a project my department is responsible for, but I never worked on it. It was written by fellow team member JC who left last year, and the person who was supposed to maintain it (he was assigned to our team shortly after JC left) also left this year. So now it's my turn.

Woot! Legacy code!

Unlike the rest of our code base, “Project: Bradenburg” expects to run on a modern 64-bit Linux system. Okay, cool! I get to learn about running Linux VMs on an Apple Mac book (only took two days, and constant reminders to myself not to throw the laptop across the room, to get the VM installed and running).

Then I attempted to build the system, and that's when I learned the Linux system I'm running is a bit too modern. It took some hacking to get the code compiled, and I'm concerned about how best to integrate the changes I have with the build system.

I'm also learning why people hate make. I've never really got the hate, because I never found make all that difficult to use (especially GNU Make—I find it quite nice to use). But diving into “Project: Bradenburg” really has me questioning JC's … um … design asthetic when it comes to make. I was able to replace six Makefiles comprising a total of 700 lines, with one Makefile of 197 lines, 150 of which comprise the dependency list (automatically generated—leaving 47 lines to do the actual building). I'm sure the Makefile will grow a bit (to cover building a release versus a debug build) but not 500 more lines.

Another thing I'm working on is finding out not only who uses “Project: Bradenburg,” but how they're using it. I know the Corporation uses it, but I do know that JC was working with our Corporate Overlords to have it used elsewhere. I want to rip some stuff out if it (like the internal stack tracing mechanism) but I first want to know if anyone uses the stuff I want to remove.


Notes on an overheard conversation while bringing in the groceries

“What an annoying Christmas display.”

“I tried knocking on the door to tell them their car alarm is going off. No one answered, and the entire house is dark.”

“That can mean two things—they're not home, or everybody is dead.”

“That's morbid!”

“Okay, third option—they're all deaf.”

Monday, Debtember 13, 2021

Maybe another name for this project should be “Charlie Foxtrot”

I'm still diving into “Project: Bradenburg” and I'm amazed that it's being used in production. I found mention of two specific versions of Linux distributions that are known to compile the code, but only one was able to compile the code as is (the other one had a compiler that was too old to use—go figure).

I wanted to start compiling with the version used in production at The Corporation, but it turns out to be difficult to check out that version. We use Subversion, and it appears that the revision used by production isn't in the main line of code, but in some branch. I tried using Fisheye (the Corporation has it installed and integrated into our build system) to find the appropriate branch, but the view for “Project: Bradenburg” was turned off four months ago

I was only able to find the branch by checking out the entire repository (all branches included—it took a while). It turns out that even if I knew which branch the production code was in, it wouldn't have mattered (per the wisdom of the ancients).

Eventually I get the proper version and … it doesn't compile. Two syntax errors and one linking error. Sure, they were easy to fix, but now I'm wondering how this was ever built by our build system to begin with. But that's moot as the build server can't even build the latest version—it can't find the proper target system to build on! It was then I noticed that “Project: Bradenburg” was last built over a year ago.

Woot!

This project certainly is putting the word “fun” in “disfunctional.”


Notes on an overheard conversation while checking the mail box

“I was worried we wouldn't get any Christmas cards this year.”

“I see we got one from Peggy, and … our neighbor across the street actually sent his card through the mail?”

“Yes.”

“He spent 58¢ for a stamp when he could have just walked across the street and put it in our mailbox?”

“Yes. That's the way it's supposed to be.”

Across the street?

“Yes. I'm doing the same.”

“You are wierd, sir.”

“Pththththththththth!”

Tuesday, Debtember 14, 2021

Putting the “fun” in “dysfunctional”

I finally heard back about “Project: Bradenburg” and it's not exactly good news. The Corporation is using revision 4873. The Corporate Overlords are apparently using a custom version of revision 5076 (custom because it contains a one line patch). No one else is using “Project: Bradenburg,” at least for now.

Lovely.

Also, around the time of revision 5076, the codebase started to be converted from C to C++. No reason I can find for the decision, and it's not complete. So now I have to deal with a hybrid C and C++ project, which is currently at revision 5567. Oh, the desire to switch back to the C code base is strong. I'll have to see.

On the plus side, “Project: Bradenburg II: Electric Boogaloo” (yes, an attempted rewrite of “Project: Bradenburg,” which itself was a rewrite of a previous project that never got into production, which was to replace a third party package that didn't quite do what we wanted and was thus patched to Hell and back) can be safely ignored. I also have a few months to figure this mess out.

Ah, what a legacy this code has.

Wednesday, Debtember 15, 2021

There seems to be a qualitative difference between C and C++

I need to decide if “Project: Bradenburg” will be in C or C++. I timed how long it takes to compile the last C version of the codebase: 2.4s. I then timed how long it takes to compile the hybrid C/C++ version: 18s. There's a qualitative difference there. And I should note—it's the C version that's currently in use, not the C++ version. And then our resident C++ expert said that you should start a project in C++, not convert a project from C to C++.

Hmmmmm …

And from the “Puts the Fun in Disfunction Department” I noticed that there are warnings enabled on the compiler command line, only for those warnings to be disabled in the source code (via many #pragma declarations). Oh, and the reason it runs so slow is that the optimization level is set to 0, possibly to make the code easier to debug by looking at the resulting assembly code (I'm guessing).

It's also becoming clear that no one really knows who is using “Project: Bradenburg.”

The fun never stops.

Thursday, Debtember 16, 2021

“Well, there's your problem!”

“Sean,” said Bunny, “do you have a way of testing an electrical outout?”

“Hmm … don't we have one of those outlet tester things? It looks like just a plug, but with a few LEDs on the back showing the status of the outlet. I thought we got one of those.”

“Let me look.” She then goes off for a few minutes, and returns with exactly what I described, still in the package. “This?”

“Exactly!”

We then grab a flashlight as the sun was setting, as the outlet in question was outside. I work my way to the outlet and lift the covers. The bottom outlet was a bit darker than the top one, so I decided to test the top one first. I plug in the device. “Nothing,” I said.

“Okay, now try the bottom one,” said Bunny.

I plug the tester into the bottom outlet. The air was filled with a loud buzzing sound as flames shot out of the outlet, engulfing the tester. Bunny and I were stunned for several seconds, not knowing exactly what to do. Fortunately, the flames died out and the sound stopped. I pulled the tester out of the outlet and we both went back inside.

“I wonder if this tester still works,” I said once we were inside.

“Sean, just look at it!”

I looked at it. the ground pin was slightly blacked at the base; the neutral pin was entirely black, and the hot pin was entirely black and partially melted. Looking at the directions on the package showed the “no lights' condition as “open hot”—the hot contact not connected. And item 3: Refer all indicated problems to a qualified electrician.

Although “flames shooting out of the outlet, destroying the receptical tester” isn't a listed issue, I'm guessing that's enough of a clue we should have the outlet looked at by a qualified electrician.


Twiddling my thumbs

I use The Corporate Overlord's mandated Windows Laptop only for a few things, like submitting my time card and to check how much PTO I have left for the year. So I turn on The Corporate Overlord's mandated Windows Laptop (hereafter named “Satan”) and immediately, my Internet connection is swamped. It's completely unusable. I check, and yes, Satan is sucking up as much bandwidth as computerly possible for doing Bill knows what. It certainly can't be malware, because it's already filled to the brim with anti-virus, anti-malware, anti-anything programs constantly running in the background that I can't do anything about because Satan is completely managed by the Corporate Overlords.

Okay, I think to myself. While I'm waiting, maybe I can see if this thing has Solitaire on it. I always liked playing Solitaire. And yes, it has Solitaire, only now it has ads, (only $14.95 a year to remove ads).

Really, Microsoft? Good lord.

It's been an hour so far, and Satan is still downloading Bill knows what.

I think come January, I'll ship Satan back to the Corporate Overlords. Bill knows I certainly don't use it.

Update just prior to publication

I turned off Satan, and immediately, the network was usable. Not only that, but I was able to log onto the enterprise application from a non-Windows system, so there is no reason I need Satan here anymore.

I'll definitely look into shipping Satan back to where it belongs.

Friday, Debtember 17, 2021

“Well, there's your solution!”

It turns out that Bunny's brother is a qualfied electrician, and even though he's 3,000 miles away, a few pictures and several phone calls were enough for him to walk us through replacing the problematic outlet. The hardest part—kneeling on the granite gravel beneath the outlet. Ouch. But we had everything we needed. I even found a duplicate receptacle tester in my toolbox!

And now the outlet works. But I did state to Bunny that if that outlet ever gives us trouble again, I'm calling an electrician—I'm not kneeling on gravel if I can help it.


C++11 is supported, but not C11 … of course

So I notice that JC used GCC atomic intrinsics for “Project: Bradenburg”. I also found out which distribution we're using for the Linux build servers, so I have that installed as a VM. I'm toying around with going back to C for “Project: Bradenburg,” and given that C11 has support for atomics, it seemed like a way of getting more portable atomics in the codebase.

Of course the Linux distribution we use supports C++11, but it lacks C11 support. Of course it does!

C11 is only a ten year old standard, so let's not rush into things here! But C++11—full steam ahead! It's 10 years old already! Why aren't you using it?

Words fail me.

Wednesday, Debtember 22, 2021

Are we having fun yet? And by “we” I mean “I.” And by “fun” I mean “misery”

Ah, “Project: Bradenburg”—the gift that keeps on giving.

The build server can now find the proper build node, so that's progress. The build fails, however, because of linking errors, which at least validates the issues I'm having on my local machine. I make one small change to the Makefile I know will fix the issue, and the build server didn't pick up the change.

What?

Some investigation, and it appears the build server is pulling the repository from git, and not from Subversion. It appears I did not receive the memo about this (a year and a half ago, I started to migrate our stuff to git, but stopped because some of our Solaris build servers couldn't check the repos out from git. And that's still an issue. But “Project: Bradenburg” doesn't run on Solaris so for that and some other reasons, Ops “moved” the repository to git a few months ago). So now the official build for “Project: Bradenburg” comes from git, and the rest of our official builds for projects in our department are still from Subversion.

Fine. I can deal. I actually prefer git over Subversion anyway.

I get the credentials worked out for the git repository, make my small change to fix the linking issue, only to have another linking issue. Because of course.

I swear, how did this ever compile in the first place?


A most persistent spam, part V

I received an email from new reader Sylvain asking about Alaksandr, the Russian sendmail spambot that was plaguing me for months. It seems that Sylvain is having to deal with Alaksandr and asked me for some help, having read one of my posts detailing the problem (and if you are having déjà vu, it's not a glitch in the Matrix).

I told Sylvain about my solution—removing the email accounts Aleksandr was spamming. I also decided to update each of the posts to point to my solution as it seems others are having similar issues and not finding answers.


Schadenfreude at some badly written bots

Back in October, I removed a whole section of my Gemini site because I got fed up with badly written bots. In the best practices guide there is a section about redirection limits (something that should be in the specification but for some reason isn't). In the section of my site I removed, I had such a test—a link that would always redirect to a link that itself would redirect, ad nauseum. So I would see a new client being tested and perhaps a dozen or two attempts to resolve the link and then it would stop.

But then there were the clients written for automated crawling of Gemini space that never bothered with redirection limits. It got so bad that there was one client stuck for a month, endlessly making requests for a resource that was forever out of reach. I had even listed the redirection test as a place for bots NOT to go in the robots.txt file for the site (also a companion specification).

So because it can be needlessly complex to locate a bot contact address, I was like, XXXX it. I removed the redirection test (along with the rest of the section, which included a general Gemini client test because, well, XXXX it). Why waste my bandwidth for people who don't care?

I only bring this up now because I'm noticing two bots who are attempting to crawl a now non-existant redirection test, probably with a backlog of thousands of links because hey, who tests their bots anyway?

Saturday, Debtember 25, 2021

I think I'm supposed to say “Merry something something,” and something about good wills

.qggL     .gggr.
  PMML    /|MM
  |!MM,  /`|MM   .d/"q,  qgg;+Ml qgg;+Ml vgg. .y.
  | YMM,j' |MM   MM;.jMl |MM` "  |MM` "   qM| j`  
  |  qM#'  |MM   MM|     |MM     |MM       MMg'
.j|.  qF  .+MM.. 'MMbxr` jMM.    jMM.      'MF
                                         x, /
                                         v#'
  .x/--\xxl ,xx               ,gb           .
.dMT    'q| |MM               '"'         .dM
dMM       ` |MM/dMg,  qgg;+Ml qgg  j/"`+  qMM-. qgg/dM#,w#Mb  ,g'`fg,  j/"`+
MMM         |MM  MM|  |MM` "  |MM  MMbx/  |MM   |MM  |M|  MM  `P'.jM|  MMbx/
'MMl      . |MM  MM|  |MM     |MM  .`vMMl |MM   |MM  |M|  MM  ,gP`|M|  .`vMMl
 'vMb...r/` jMM..MM|. jMM.    jMM. +,.,P' 'MMx: jMM..dM|..MM, MM|r+M|. +,.,P'
     ""

[It looks like Sean finally fixed the spelling mistake. It's about time! ---Editor]

Wednesday, Debtember 29, 2021

Still going strong, a week later

Heh, a week later and there are still bots following the endless redirections from my Gemini site that are now long gone. Given the nature of Gemini, there's little in the way of contacting the people responsible that they're wasting time and resources. Perhaps if it's still going on next week, I'll mention IP addresses …


Software can just never be done it seems

I released the Text::Template module several years ago, and it was immediately very successful. It's small, simple, fast, and it does a lot of things well. At the time, there were not yet 29 templating systems available on CPAN.

Anyway, the module quickly stabilized. I would get bug reports, and they would turn out to be bugs in the module's users, not in the module; I would get feature requests, and usually it turned out that what the requester wanted was possible, or even easy, without any changes to the module. Since the module was perfect, there was no need to upload new versions of it to CPAN.

But then I started to get disturbing emails. “Hi, I notice you have not updated Text::Template for nine months. Are you still maintaining it?” “Hi, I notice you seem to have stopped work on Text::Template. Have you decided to abandon this approach?” “Hi, I was thinking of using Text::Template, but I saw it wasn't being maintained any more, so I decided to use Junk::CrappyTemplate, because I need wanted to be sure of getting support for it.”

I started wondering if maybe the thing to do was to release a new version of Text::Template every month, with no changes, but with an incremented version number. Of course, that's ridiculous. But it seems that people assume that if you don't update the module every month, it must be dead. People seem to think that all software requires new features or frequent bug fixes. Apparently, the idea of software that doesn't get updated because it's finished is inconceivable.

I blame Microsoft.

Twelve Views of Mark Jason Dominus

I can't say I haven't myself wished that the industry as a whole just said, “Enough! Let us spend the next year on nothing but bug fixes!” But that's just not going to happen. Why? Because no one will pay for bug fixes, as stated by Bill Gates himself: “There are no significant bugs in our released software that any significant number of users want fixed. … I'm saying we don't do a new version to fix bugs. We don't. Not enough people would buy it. You can take a hundred people using Microsoft Word. Call them up and say ‘Would you buy a new version because of bugs?’ You won't get a single person to say they'd buy a new version because of bugs. We'd never be able to sell a release on that basis.”

But the idea of just arbitrarily increasing the version number every so often does seem silly, but hey—the industry as a whole has this idea that a project that hasn't changed in some period of time is dead and not worth using. It's silly ideas like this that has lead me, over the past five years, to do at least one release per year of mod_blog just because!

(Yes, I actually had enough changes this Debtember to cut two releases to inadvertantly make up for the one I missed in 2019)

I found the above quote from Mark Dominus via a comment to Chris Siebenmann, which itself was linked from a more recent post from Chris Siebenmann. Both posts are worth reading as they go into some depth as to why the industry as a whole wants constant upgrades over stable software.

Obligatory Picture

[It's the most wonderful time of the year!]

Obligatory Contact Info

Obligatory Feeds

Obligatory Links

Obligatory Miscellaneous

You have my permission to link freely to any entry here. Go ahead, I won't bite. I promise.

The dates are the permanent links to that day's entries (or entry, if there is only one entry). The titles are the permanent links to that entry only. The format for the links are simple: Start with the base link for this site: http://boston.conman.org/, then add the date you are interested in, say 2000/08/01, so that would make the final URL:

http://boston.conman.org/2000/08/01

You can also specify the entire month by leaving off the day portion. You can even select an arbitrary portion of time.

You may also note subtle shading of the links and that's intentional: the “closer” the link is (relative to the page) the “brighter” it appears. It's an experiment in using color shading to denote the distance a link is from here. If you don't notice it, don't worry; it's not all that important.

It is assumed that every brand name, slogan, corporate name, symbol, design element, et cetera mentioned in these pages is a protected and/or trademarked entity, the sole property of its owner(s), and acknowledgement of this status is implied.

Copyright © 1999-2022 by Sean Conner. All Rights Reserved.