Sunday, July 01, 2018
Replacing the battery on my iPhone should not require rebooting my Mac
It wasn't as bad as that time 2½ years ago (no, really! you have no idea how bad it was back then) but it still left a bad taste in my mouth. The battery on my iPhone wasn't lasting as long as it used to. I would be lucky get to a day's charge out of it, and I don't really use it all that much (using Shazam was a death sentance for my iPhone—I'd usually get one use out of it before the screen would go dark).
On Thursday, Bunny and I stop by the Apple Store only to find out that a battery replacement would require an appointment, and the first one was for Saturday. Okay, Saturday it is.
At the appointed time on Saturday, we arrive at the store. I will say we didn't have to wait all that long, but on the down side, I would have to leave the phone overnight for the replacement.
Okay, picking it up on Sunday it is.
Today, I got the phone back. It works. I was able to check multiple songs with Shazam with no discernible battery drain, so things are looking up. Until I decide to pull some pictures off the phone.
Usually,
I just plug in the phone to the Mac-mini I have,
run the Photos
app and import them.
Only this time I coudn't.
What should have been a minute operation turned out to be a grueling half hour torture test trying to find out what happened to the “import function” of Photos
.
I was able to finally resolve the issue by rebooting the Mac-mini!
Seriously, Apple? You're better than Microsoft! This shouldn't require a reboot! Come on!
I swear, they really need to bring back Steve Jobs.
Wednesday, July 04, 2018
All's quiet on the holiday front
Right now it's all quiet outside, but I suspect that won't last the day.
So today, after you have read The Constitution, but before you hand over your beer and say, “Watch this!” please remember to be careful. I would hate for this to happen to you:
Notes on an overheard conversation
“So the weather report states thunderstorms for the Fourth.”
“Oh! At night?”
“Mostly the afternoon and ending around 8:00 pm.”
“Darn!”
“Oh, expecting to get out of walking to the Boca Raton fireworks show?”
“No.”
“No?”
“No. I was hoping our neighbor wouldn't blow us all up!”
Neither heat nor rain nor threat of thunderstorms stays the neighbor from the swift lighting of firework rounds
It sounds like Desert Storm outside.
I guess the threat of thunderstorms wasn't enough to deter the neighbor.
Sigh.
Thursday, July 05, 2018
Abandon all hope ye who enter the sucking vortex of ill-marked, multply-named, non-Euclidean roadways known as Orlando
Bunny and I are on the road for a weekend getaway (more on that later). We are headed back into that maelstrom of roads known as Orlando. On the downside, said maelstrom has extended itself a significant distance outside of Orlando and for the first time ever, we missed the turn at Ft. Pierce and ended up on a nearly 20 mile detour.
Then, we nearly ended up missing a service station on the Turnpike—don't ask how that happened. It did. And the maelstrom wrought it's malevolent influence over us to the point where we nearly called the whole weekend off.
And finally, Google Maps directed to the rear of the hotel.
I swear, Orlando is actively trying to kill us.
Singing with scissors
Bunny first proposed this trip several months ago and I was initiallty dubious. I mean, a trip to view barbershop quartets! I was reluctant to go, but Bunny assured me that I was under no threat of losing hair or limbs. No, the only thing under threat was the ears.
We finally arrived at the hotel. As we were walking to our room, it seemed to me that barbershop quartets have shrunk over the years, but the lack of matching outfits, no singing and a definite lack of scissors meant that no, the people I was seeing were in fact Little People milling about. Too many to be conincidental and indeed, there really is a conference of Little People scheduled at the same time and not some Lynchian nightmare.
At least, not yet.
About this hotel
The hotel is quite nice, but it has … a few oddities that I've never seen before. The first, and most innocuous, are all the automatic lights about the place. There's one in the bathroom, one beneath the night stand and the entire garage appears to have motion sensative lights (it certainly got brighter in the garage when I went back this evening to pick up a USB cable I left in the car). It was rather unexpected, but a pleasant unexpectedness.
The next was also unexpected, but to me, not a pleasant unexpectedness. The mirror in the bathroom is nice, large and certainly bright:
But there's this odd greyed out section near the bottom. Here's the not-so pleasant unexpectedness:
It's a television screen! (and yes, when I turned it on, it was tuned to Fox News. CNN wouldn't have been any better)
Really?
First off, are people so addicted to television that one is needed in the bathroom? [Yes. —Editor]. And second, you can't even watch it while sitting on the toilet! You can only watch the television while standing in front of the mirror. That's just … just … weirdly random.
And finally there is this:
A stick. In the elevator. Just hanging there with a sign saying not to remove it. And it's not limited to one elevator. No, each elevator has a stick, hanging on a sign saying not to remove it. They're just there. I don't know.
Groups of people singing four part harmony. Little People milling about. Elevator sticks. Automatic lightbulbs. Television mirrors.
Orlando is weird!
Friday, July 06, 2018
Notes on the epiphany I had on elevator sticks while I slept
It may have been obvious to some, but not to me. It suddenly dawned on me what the elevator sticks were all about. The puzzle pieces were all there, I just hadn't made the connection.
I am not the target audience for using the elevator stick, nor is the staff the target audience. No, the target audience is the Little People, so they can use it to push the elevator button in case they can't reach it.
It's obvious in hindsight.
While I joked about the elevator sticks, it's not something I'm used to seeing. And here they were, just hanging out in elevators with no obvious usage to me, some one who can reach all the buttons. It wasn't until I was sleeping and my subconscience told me an old riddle I heard as a kid: “A man lives in a tall apartment building. On some days, he rides the elevator to his apartment on the 20th floor. On other days, he rides the elevator to the 18th floor and walks up two more flights. Why?”
Oh.
“Yeah. ‘Ooh, ah,’ that's how it always starts. But then later there's running and screaming.”
Don't let the propaganda fool you—Orlando is trying to kill you.
Or at least drive you mad and empty your wallet.
One must always make sure to get the cruelty-free pizza
In the lobby of the hotel is a store by the name of “Market Orlando.” I can only describe it as if hippies-cum-yuppies from Berkeley ran 7-Eleven. Gluten-free, organic, farm-fresh snacks, chips, salads and sandwiches.
Oh, and cruelty-free pizzas. Can't forget those.
It has an extensive wine selection (Napa Valley present!), but the soda selection is pretty much limited to Pepsi and Diet Pepsi (which sucks because I'm a Coca-cola person myself). There's also about a bazillion brands of artisanal water.
Oddly enough, I did not see any granola for sale.
I'm telling you, Orlando is weird! When it's not trying to kill you.
Sunday, July 08, 2018
At the roadways of madness
The sucking vortex of non-Euclidean roadways known as Orlando began it's influence of madness over us hours before we left. We were planning on how best to get back to the Turnpike from the hotel when Bunny and I started arguing yet again. She wanted to follow the torturous path we took to get here, which involved an intricate series of turns and switchbacks while carefully aligning ourselves within certain lanes at certain times. I wanted to follow yet another intricate path of a torturous series of turns and switchbacks while carefully aligning outselves within certain times at certain lanes. Either route lead to madness.
Also at stake was who would be the unfortunate driver to brave the maelstrom of roads until the relative safety of the Turnpike. I don't recall who drove. All I know is we barely made it out alive.
Unrelated, I wish to leave you with a mental image of the most surreal observation I saw on the way out of the hotel: a Little Person and their dog riding a Segway down the hall.
Monday, July 09, 2018
At least now no one has to pay to have their information protected
So I received the following email from my registrar:
- From
- <XXXXXXXXXXXXXXXXXXXXXXX>
- To
- <sean@conman.org>
- Subject
- WHOIS Data Confirmation for x-grey.com
- Date
- Mon, 9 Jul 2018 09:30:23 -0400 (EDT)
Dear Valued Customer,
ICANN, the organization responsible for the stability of the Internet, requires that each domain name registrant be given the opportunity to correct any inaccurate contact data (WHOIS data) associated with a domain name registration. Our records for your domain are as follows:
x-grey.com Domain Name: X-GREY.COM Registry Domain ID: 1325416434_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.domain.com Registrar URL: www.domain.com Updated Date: 2017-11-08T05:11:47 Creation Date: 2017-11-07T22:32:17 Registrar Registration Expiration Date: 2018-11-08T01:32:21 Reseller: Dotster.com Domain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited Domain Status: clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited Registry Registrant ID: Registrant Name: Data Protected Data Protected Registrant Organization: Data Protected Registrant Street: 123 Data Protected Registrant City: Toronto Registrant State/Province: ON Registrant Postal Code: M6K 3M1 Registrant Country: CA Registrant Phone: +1.0000000000 Registrant Phone Ext: Registrant Fax: +1.0000000000 Registrant Fax Ext: Registrant Email: noreply@data-protected.net Registry Admin ID: Admin Name: Data Protected Data Protected Admin Organization: Data Protected Admin Street: 123 Data Protected Admin City: Toronto Admin State/Province: ON Admin Postal Code: M6K 3M1 Admin Country: CA Admin Phone: +1.0000000000 Admin Phone Ext: Admin Fax: +1.0000000000 Admin Fax Ext: Admin Email: noreply@data-protected.net Registry Tech ID: Tech Name: Data Protected Data Protected Tech Organization: Data Protected Tech Street: 123 Data Protected Tech City: Toronto Tech State/Province: ON Tech Postal Code: M6K 3M1 Tech Country: CA Tech Phone: +1.0000000000 Tech Phone Ext: Tech Fax: +1.0000000000 Tech Fax Ext: Tech Email: noreply@data-protected.net Registry Billing ID: Billing Name: Data Protected Data Protected Billing Organization: Data Protected Billing Street: 123 Data Protected Billing City: Toronto Billing State/Province: ON Billing Postal Code: M6K 3M1 Billing Country: CA Billing Phone: +1.0000000000 Billing Phone Ext: Billing Fax: +1.0000000000 Billing Fax Ext: Billing Email: noreply@data-protected.net Name Server: ns1.armigeron.com Name Server: ns2.armigeron.com URL of the ICANN WHOIS Data Problem Reporting System: http://wdprs.internic.net/ >>> Last update of WHOIS database: 2017-11-08T05:11:47 <<<“For more information on Whois status codes, please visit https://icann.org/epp”
Registration Service Provider:
XXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX
+1.XXXXXXXXXX
This company may be contacted for domain login/passwords,
DNS/Nameserver changes, and general domain support questions.To review and update your WHOIS contact information, please log into our management interface at: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
If any of the information above is inaccurate, you should correct it. If all of the information above is accurate, you do not need to take any action.
Please remember that under the terms of your registration agreement, the provision of false WHOIS information can be grounds for cancellation of your domain name registration. If you have any questions or comments regarding ICANN's policy, please visit the following link
http://www.icann.org/registrars/wdrp.htm
Thank you for your attention.
Best regards,
XXXXXXX
It's kind of hard to review my information when it's protected from my viewing it for my protection. I think my registrar is going a bit overboard in complying with the GDPR.
Sigh.
Yes. It is music. I identified it. What more do you want?
Bunny and I had dinner at a nearby Chinese restaurant. As we ate, Bunny mentioned that the music we were listening to must be the Chinese equivalent to elevator music. I concurred, and because I was curious to know what it was, I thought I might try to use Shazam to identify it.
It did.
And now I know.
Monday, July 16, 2018
I don't think this is what McDonald's had in mind when they said “you deserve a break today”
I was at The Scottish Place to pick up some lunch. I placed my order, and while waiting in line, I noticed the telltale signs of Microsoft Windows:
Ah, Windows, keep on being your special snowflake self.
But in all seriousness, who set this up? If you are going to run any computer in a public space, I would hope those setting it up would run the bare minimum for the service required (and in this case, just the operating system and whatever program it is that runs the display) and remove everything else. Then, for whatever left is running, is there not some Windows setting to just have it automatically reboot upon an error? Or simply not display warning messages like this on the display meant for public viewing?
I have to wonder how long this message has been here, waiting for someone, anyone, to select an option (or to restart, reboot or reinstall). I wonder if management even cares?
Thursday, July 19, 2018
A sane and easy to use TLS library! Will wonders never cease!
I'm still fighting the stupidity at work, but it's becoming aparent that it's a fait accompli and we're looking at a bunch of REST/HTTPS über alles Kool-Aid™ in an area where time is critical.
Sigh.
So I'm looking around at what I can use to support the “S” in HTTPS that doesn't involve diving into the horror show that is OpenSSL. A library that can still encrypt and decrypt data when it isn't managing the network connections on the program's behalf (because the program is already managing the network connections). It can be complicated, but it must be sane to use.
I was pointed to libtls
,
which comes with LibreSSL.
Not only is this sane,
but it's easy to use.
I'm simply amazed at how easy.
In just an hour, and only reading the man pages, I was able to write a simple program that fetches a page from a secure website. And most of the code is just there to report any errors that happen. It's a very straight forward program.
Another hour or two, and I had a program where the library does not control the network connection. Which means we can (probably) use this in our existing architecture.
A few more hours, and I was able to replicate the initial C program in Lua:
local tls = require "org.flummux.tls" -- ***************************************************************** local function okay(v,err) if not v then print(">>>",err) os.exit(1) end return v end -- ***************************************************************** if #arg == 0 then io.stderr:write(string.format("usage: %s host resource\n",arg[0])) os.exit(1) end local config = tls.config() local ctx = tls.client() okay(config:set_protocols "all") okay(ctx:configure(config)) okay(ctx:connect(arg[1],"https")) okay(ctx:write(string.format( "GET %s HTTP/1.1\r\n" .. "Host: %s\r\n" .. "User-Agent: TLSTester/1.0 (TLS Testing Program Lua)\r\n" .. "Connection: close\r\n" .. "Accept: */*\r\n" .. "\r\n", arg[2], arg[1] ))) while true do local bytes = okay(ctx:read(1024)) if bytes == "" then break end io.stdout:write(bytes) end
I had to write my own Lua wrapper for LibreSSL. The existing ones (and I found only two) weren't up to my standards for use, but it wasn't terribly hard to get the above working.
The next step is expanding the Lua module to see if I can get it working with our networking code we use. I am optimistic about this.
But I am not optimistic about having to use this at work.
Monday, July 23, 2018
Managing TLS connections using Lua and Lua coroutines
Getting libtls
working with Lua wasn't as straightforward
and I thought it would be. It works
(for the most part)
but I had to change my entire approach.
The code is an ugly mess and there's quite a bit of duplication in several spots.
But!
I can request web pages,
in Lua,
via HTTPS in an event loop based around select()
(or poll()
or epoll()
or whatever is the low level event notification scheme used).
Woot!
And I'm going into excruciating detail on this.
Back on Friday,
when I wrote some “proof-of-concept” code,
I had thought I could switch coroutines in the user-supplied I/O
callback routines
(and if coroutines existed in C,
that is where you would yield to another coroutine).
It was easy enough to extend the callback to a Lua routine—
in the routine that wraps the libtls
function tls_connect_cbs()
:
static int Ltls_connect_cbs(lua_State *L) { struct tls **tls = lua_touserdata(L,1); int rc = tls_connect_cbs( *tls, Xtls_read, Xtls_write, L, luaL_checkstring(L,2) ); if (rc != 0) { lua_pushboolean(L,false); return 1; } lua_settop(L,5); lua_pushlightuserdata(L,*tls); lua_getuservalue(L,1); lua_pushvalue(L,1); lua_setfield(L,-2,"_ctx"); lua_pushvalue(L,2); lua_setfield(L,-2,"_servername"); lua_pushvalue(L,3); lua_setfield(L,-2,"_userdata"); lua_pushvalue(L,4); lua_setfield(L,-2,"_readf"); lua_pushvalue(L,5); lua_setfield(L,-2,"_writef"); lua_settable(L,LUA_REGISTRYINDEX); lua_pushboolean(L,true); return 1; }
I pass in the two callback functions,
and I'm using the Lua state context as the userdata in the callbacks.
I then create a Lua table,
populate it with some useful information,
such as the Lua functions to call,
and associate it in the Lua registry with the value of the libtls
context.
Then,
when libtls
calls one of the callbacks:
static ssize_t Xtls_write(struct tls *tls,void const *buf,size_t buflen,void *cb_arg) { lua_State *L = cb_arg; ssize_t len; lua_pushlightuserdata(L,tls); lua_gettable(L,LUA_REGISTRYINDEX); lua_getfield(L,-1,"_writef"); lua_getfield(L,-2,"_ctx"); lua_pushlstring(L,buf,buflen); lua_getfield(L,-4,"_userdata"); lua_call(L,3,1); len = lua_tonumber(L,-1); lua_pop(L,2); return len; }
I get the Lua state via the user argument.
From that,
and the libtls
context,
I obtain the data I cached into the Lua table,
which give me the Lua function to call.
Said function can then call coroutine.yield()
.
Straightforward, easy, and wrong! I got the dreaded “attempt to yield across metamethod/C-call boundary” error. Darn.
The attempted flow looks like (yellow boxes are Lua functions; green boxes are C functions):
There are four layers of C functions that can't be yielded through. Lua does have a way of dealing with intervening C functions, but it's somewhat clunky.
In this case,
the Lua function lua_callk()
is handled specially so it doesn't cause an error.
The function cf()
needs to be split in half—the portion prior to calling into Lua,
and the second half to handle things after a potential call to coroutine.yield()
.
That's represented above by the functions cf_orig()
and cf_c()
.
The “*” represent the functions returning,
not calling. coroutine.resume()
will restart luaf_b()
right after it's call to coroutine.yield()
.
And when luaf_b()
returns,
it “returns” to cf_c()
,
which does whatever and finally returns,
which “returns” to luaf_a()
.
But in the case I'm dealing with just doesn't work with that model. The code calling into Lua doesn't have the signature:
int function(lua_State *lua_State);
but the signature:
ssize_t function(struct tls *ctx,void *buf,size_t buflen,void *cb_arg);
Not only are the return types different,
but they have completely different semantics—for libtls
,
it's the number of bytes transferred,
whereas for Lua,
it's the number of items being returned to Lua.
No,
I had to rethink the entire approach,
and do the call to coroutine.yield()
a bit higher in the call stack.
Which also meant I had to push dealing with TLS_WANT_POLLIN
and TLS_WANT_POLLOUT
back to the caller.
The documentation states:
TLS_WANT_POLLIN
The underlying read file descriptor needs to be readable in order to continue.TLS_WANT_POLLOUT
The underlying write file descriptor needs to be writeable in order to continue.In the case of blocking file descriptors, the same function call should be repeated immediately. In the case of non-blocking file descriptors, the same function call should be repeated when the required condition has been met.
And here I was, trying to hide such concerns from the user. Ah well.
I eventually got it working,
but man,
is it ugly.
The Lua code wants to read data,
so I have to call into libtls
.
That in turn,
calls back into my code,
and if I don't have any,
I need to return TLS_WANT_POLLIN
,
which bubbles up through libtls
back to my code,
which can then yield.
Meanwhile,
from the other end,
I get data from the network.
I can't just feed it into libtls
,
I have to feed it when libtls
calls the callback for the data.
But when I get the data,
I may need to resume the coroutine,
so I have to track that information as well.
I can almost understand the code (and yes, I wrote it; did I mention it's ugly?)
But I'm happy. The following code works in my existing network framework (boy does that sound wierd):
local function request(item) syslog('debug',"requesting %s",item.url) local u = url:match(item.url) -- ------------------------------------------------------- -- asynchronous DNS lookup---blocks the current coroutine -- until a result is returned via the network. -- ------------------------------------------------------- local addr = dns.address(u.host,'ip','tcp',u.port) if not addr then syslog('error',"finished %s---could not look up address",u.host) return end -- --------------------------------------------------------- -- This has nothing to do with the iPhone operating system, -- but everything to do with "Input/Output Stream" -- --------------------------------------------------------- local ios if u.scheme == 'http' then ios = tcp.connecta(addr[1]) -- connect via TCP else ios = tls.connecta(addr[1],u.host) -- connect via TLS end if not ios then syslog('error',"could not connect to %s",u.host) return end local path = table.concat(u.path,'/') local fhname = "header/" .. item.hdr local fbname = "body/" .. item.body local fh = io.open(fhname,"w") local fb = io.open(fbname,"w") local command = string.format([[ GET /%s HTTP/1.0 Host: %s Connection: close User-Agent: TLSTest/2.0 (Lua TLS Testing Program) Accept: */* ]],path,u.host) ios:write(command) fh:write(ios:read("*h")) repeat local data = ios:read("*a") fb:write(data) until data == "" fb:close() fh:close() ios:close() syslog('debug',"finished %s %s",item.url,tostring(addr[1])) end
Any number of requests can be started and they all run concurrently, which is just what I wanted.
Now, the code I have for the Lua wrapper for libtls
covers just what I need to do this.
More work is required to finish covering the rest of the API.
I also have to clean up the Lua code that backs the above sample code so that I might have a chance of understanding it at some point in the future.
And until I get the working code published, you can look at the “proof-of-concept” Lua coroutine code I worked from (and no, the above code sample will not work as is with this “proof-of-concept” code).