AppleTV Development – OpenSSL and libcurl

In doing development for the new AppleTV, I was unable to find a cross compiled version of OpenSSL and cURL (libcurl) to use for my project.   I found a helpful OpenSSL script (here) that addressed some the unique tvOS challenges (e.g. fork() is not available) and used that build script to construct an libcurl build script.

The following repo contains scripts to build OpenSSL and cURL (libcurl) for OS X, iOS and tvOS with Bitcode enabled for iOS, tvOS. It includes the required patching for tvOS to not use fork(). This requires Xcode7.1b or later for the tvOS SDK.

https://github.com/jasonacox/Build-OpenSSL-cURL

 

iCurlHTTP – cURL for iPhone and iPad

iCurlHTTP

HTTP Server Response Diagnostic Tool

I love cURL.  Systems engineers, developers, administrators, QA engineers and web operations specialist everywhere have used the curl tool to help troubleshoot web server responses.  It gives a quick view into exactly what is being sent from a web server to a browser.

On a commute home from work I started to think how handy it would be if the small computer I was holding, my iPhone, had a simple to use app like curl to do the same troubleshooting.  I always wanted to write my own iPhone app so I started researching how I could do that.

My Xcode Adventure

I fired up Xcode on my Snow Leopard equipped MacBook Pro for the first time.  I found a few great iOS development books on SafariOnline and started learning Objective-C.  After a few chapters I started going off the page and adding views and controllers.  I wanted to deploy my test apps to my iPhone so that required that I sign up as an Apple Developer (and $100!).  I soon discovered that my Xcode version was too out of date to work with my iOS 6.1 devices so I attempted to upgrade, only to discover that I needed to upgrade my OS.   Now on to Xcode 4.6 and suddenly my projects were running on my iPhone and iPad.

My libcurl Adventure

I discovered the NSURL class and started trying to get raw responses from web servers to display to the textview.  It was too digested and would require a lot of effort to simulate a raw curl session.  I started looking at the NSStream class when a friend suggested that I investigate a precompiled version of libcurl (the cURL library from Daniel Stenberg) for the ARM processor.  Instead, I found a great post by Nick Zitzmann where he shows how he compiled libcurl and even provides a binary: http://seiryu.home.comcast.net/~seiryu/libcurl-ios.html

I managed to get the latest version of libcurl to compile and also included the Apple SecureTransport library (–with-darwinsll in libcurl config):

#!/bin/bash
cd curl-7.29.0
export IPHONEOS_DEPLOYMENT_TARGET="4.3"
export CC="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-gcc-4.2"
export CFLAGS="-arch armv7 -arch armv7s -pipe -Os -gdwarf-2 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk"
export LDFLAGS="-arch armv7 -arch armv7s -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk"
./configure --disable-shared --enable-static --with-darwinssl --disable-dependency-tracking --host="armv7-apple-darwin" --prefix=~/Code/curl/device
make -j `sysctl -n hw.logicalcpu_max`
make install

I added the libcurl.a library to my Xcode project and started using the easy interface API via CURLcode curl_easy_perform(CURL * handle ). The realtime feel of iCurlHTTP comes from the use of the CURLOPT_WRITEFUNCTION option to push realtime code into a view controller method that renders to the textview object. It required  periodically having the thread give up time to the mainRunLoop (via message to NSRunLoop) in order to allow the display to render and respond to user events.

iCurlHTTP v1.0 Born

iCurlHTTP was born.  It was a simple, easy to use iOS app that allowed you to run simple cURL like tests, simulating different web browsers to retrive the raw HTTP headers and HTML response from the web servers.

icurlhttp-v1.0

OpenSSL Anyone?  iCurlHTTP v1.1

The SecureTransport library works great but provided less details on SSL connections than what I was accustomed to seeing with curl.  I wanted more x509 decoded information, specifcially SSL certificate details about expiration date.  The OpenSSL library would allow for this so I began another search to get  OpenSSL library for ARM7.  To get what I wanted, I cross-compiled both OpenSSL and libcurl together. With that I was able to get the great openssl detail in the output, including cert info:

icurlhttp-cert

I managed to cross compile libcurl and openssl separately for armv7, armv7s and i386 architectures but later found a great GitHub project script created by Miyabi Kazamatsuri that does both.  I forked his code and updated it to work with Xcode 5 (clang for iPhoneOS and iPhoneSimulator) and added the 64-bit arm64 and x86_64 architectures.  The script is available on my GitHub:  https://github.com/jasonacox/cURL-SSL-for-iOS

UPDATE: I later put together a much better build script for openssl+libcurl that creates libraries for Mac, iOS and tvOS (Apple TV) targets: https://github.com/jasonacox/Build-OpenSSL-cURL

HTTP Timing and iOS 7 support added to iCurlHTTP v1.2

Curl has the ability to provide timing data for DNS lookup, TCP Connect, SSL Handshake, First Byte and Total time.  For example…

curl -k -s -o /dev/null -w '%{time_namelookup} %{time_connect} %{time_appconnect} %{time_pretransfer} %{time_redirect} %{time_starttransfer} %{time_total}n' https://jasonacox.com

I wanted to add this to iCurlHTTP to give a mobile perspective on these numbers.  In v1.2, I added this in the detail response view and as timing data points listed along the bottom of the UI.

icurlhttp-timing3

The v1.2 version also includes the iOS 7 SDK updates and the new minimalist UI look and feel.

iCurlHTTP 1.3 Wish List 

Thanks to great feedback, I captured several feature requests from the iCurlHTTP user base that became the goal for version 1.3:

  1. Custom Headers – Allow more and customized browser emulations via a customized option.
  2. Print, Copy or Email Output – Add a one-button feature to send the output to the clipboard, printer, email, post, etc.
  3. Customized Post – Allow customized post data to simulate a POST form submit.

This meant I needed to be able to have a User Settings pop-up screen to allow users to enter custom fields for headers and posts.  I also wanted to allow the ability to have a custom user-agent, http authentication (user/password), SSL options and possibly others in the future.

I knew I wanted a table based form to allow for formatting, scrolling and auto-positioning.  I considered using the Settings bundle but I needed multi-line UITextView input (especially for custom headers).  There are several great open source solutions  but my favorite version was FXForms, written by Nick Lockwood  (https://github.com/jasonacox/FXForms).  I used a simple plist for settings persistence.

icurlhttp-settings

The following features are added in version 1.3:

  • Share Feature – Send output to Clipboard, Printer and Email
  • User Settings – Set Custom User-Agent, Custom Headers (replace defaults or add new ones), POST Data, Authentication and SSL Mode selection
  • Updates – New libcurl and openssl libraries.

iCurlHTTP 1.4 Enhanced History

The goal of the 1.4 update was to enhance the URL dropdown history by adding HEADER and POST data for easy repeated testing.  I used simple (h) and (p) symbols to denote header and post respectively:

Screen Shot 2016-03-05 at 8.53.39 AM

iCurlHTTP 1.5 Redirect

I had several requests to add a “follow redirect” features (similar to curl -L command) to make it easier for users to test.  I didn’t want this to be purely  automatic because it would defeat the purpose of the granular detail that cURL provides so I present the user with a popup dialog when a 301 or 302 redirect response is received and list the redirection URL they can follow.  In this version, I also replace the ugly text “User” (settings) and “Share” buttons with the well known icons to help make it more intuitive.

Screen Shot 2016-03-05 at 9.30.53 AM

I’m amazed at how this small and simple project continues to grow (both in users as well as feature requests).  It has been a fun adventure! I frequently recommend other try building their own apps.  iCurlHTTP is written in Objective-C but I would definitely recommend trying out Swift.  I’m in the process of porting iCurlHTTP to the Apple TV (seems ridiculous, I know but I have to do it just for fun) and hope to try my hand at Swift.

iCurlHTTP 1.6 & 1.7 – HTTP/2.0 and IPv6 Update

For those wanting the libcurl, openssl and nghttp2 (HTTP2) libraries for iOS or tvOS (AppleTV), I have posted a build script on github: https://github.com/jasonacox/Build-OpenSSL-cURL

Thanks to request from users, I added the following features:

  • Certificate Chain Details for HTTPS Sessions (Detail Mode)
  • Support for Authentication Credentials in URL (e.g. https://user:pass@jasonacox.com/gettest.php)
  • DNS Resolve Spoof Option for Manual Address Resolution (eg. HOST:PORT:ADDRESS)

iCurlHTTP 1.8 & 1.9 – Performance Improvements

  • Performance Improvements and Reported Bug Fixes
  • Added user defined DNS lookup & connection timeout setting (default 5s)

THANK YOU!

Thanks for your great feedback and support!  I really appreciate the kind words and critical advice.  Please send more!

iCurlHTTP Website:  www.jasonacox.com/icurlhttp

Download on the App Store

 

Reference and Thanks!