Introducing RemoteTCP for RoboFab & FontLab

RemoteTCP is a cross-platform implementation of the RoboFab Remote that allows FontLab to respond to calls from other applications over a network connection. It aims to have compatible syntax with the original remote when possible, but may require additional parameters when increased functionality is desired. Because RemoteTCP will execute Python commands from a remote client, a user authentication system is also provided.
» Download RemoteTCP, v0.1 — updated 01.26.08.


Download, install, and don’t forget the dependencies

First, you’ll need download and unzip RemoteTCP and install the RoboFab library that this package is based on. If you wish to run a RemoteTCP server, you’ll also need to install the Twisted networking framework. (See their docs for installation information and dependencies.) Locate your RoboFab install (usually “\your\python\install\Lib\site-packages\RoboFab_1.x\Lib”) and drop remoteTCP.py into the “\robofab\tools\” folder. (We’ll do this for convenience sake — remember I’m not “official”, I’m just a dude.) Now that Python can see us, we’re ready to import into our programs.

*And remember, FontLab requires Python 2.4 (at least as of this writing). If you are like me and running Python 2.5 as your system default you may want to refer to my previous article about co-habitation.

Starting the server… I mean “Remote”.

If it wasn’t for this part you could just import RemoteTCP and use it the same way you would the standard remote. But with power comes responsibility, and potentially allowing any user on the Internet to run code on your machine — well, I could think of a few times where that wouldn’t be such a good idea.

[Enter flashback] I started out writing this little program because I just wanted to play with the RoboFab Remote. I soon found out that since it used AppleEvents I was out of luck on my humble pc that graphic designers make fun of me about. While I was mulling over some of the dancing sockets in my head, I had a brief vision of the future of collaborative type design — people… networked together, working on the same font, the same file, over the Internet and in peace and harmony. Type designers wouldn’t care what operating system I used because we’re all just using the same protocols underneath, man. Finally a chance to earn the respect of my peers… I could already imagine Erik Spiekermann racing to open the file to locate my name in the credits so he could dedicate his next typeface to me: “BillyMeta” or “Bileta” or “Melly”, well something like that.

But then I had another vision — of some arbitrary jerk logging onto Mr. Spiekermann’s FontLab server and running any destructive code she wanted. “Melly-Condensed” would be trashed! Mr. Spiekermann’s hard disk wiped! Oh no — the respect, the accolades, all gone! I knew it was up to me to do something about this travesty, I should probably add some kind of user authentication implemented in a not too invasive way. (So that gentle reader, was the main point of this paragraph… and to the code we go!)

1
2
3
from robofab.tools.remoteTCP import FontLabServer
myServer = FontLabServer()
myServer.run()

Open up the “Edit Macro” panel in Fontlab and enter in the above code. Press the play button and away she goes! If everything went well you’ll have a basic FontLab server running on port 1455 and you should see this in the output panel:

Turning on the FontLab network remote.
Starting server on port 1455.

And if that all worked, well I’ll be honest, that’s more than I thought would happen. But here’s a few more options to try out if you’d like (you are encouraged to look in the code and see what the heck is going on):

1
2
3
from robofab.tools.remoteTCP import FontLabServer
myServer = FontLabServer( False ) #no outside connections
myServer.run( 4567 ) #changes port

By passing a value to myServer.run() we can change the port that the server listens on. By passing “False” to FontLabServer() we can restrict connections to only those coming from our own machine (“localhost” / “127.0.0.1”). So in this example the location of our server would be “localhost:4567”.

At this point it’s worth noting how the server decides to handle connections. When a client connects RemoteTCP will check to see if the request originates from the same machine the server is running on. If it is localhost a’knockin then it will let the request go unchallenged, process the code, return the result back to the client, and then close the connection. If a request is made from the network, the server will require a username and password be sent as well. I’ll get to the clients responsibilities in a bit, but for now we’ll look at how to add users to the system.

I swear my name is on the list, let me in

You can add users either manually or programmatically. Doesn’t make a whole lotta difference to me, but it might to you depending on your desires. If you want to do it in code then before you start the server you’ll be making use of its addUser() method:

1
2
3
4
5
6
7
8
from robofab.tools.remoteTCP import FontLabServer
myServer = FontLabServer()
user = "erik"
password = "officinia4eva"
fullName = "Erik Spiekermann"
myServer.addUser( user, password, fullName )
#only user/password are required
myServer.run()

This is quick and easy, but much like the rest of life it lacks permanence. When you kill the server (or more likely when FontLab crashes), you kill this instance of poor Erik, so you’ll have to add him again if you restart the program.

For a more lasting solution you’ll need to open up remoteTCP.py in your favorite editor and add few little lines of code. But not to worry (and if you’re writing RoboFab scripts I don’t know why you would), located near the top of the file in the FontLabServer class you’ll find two dicts cleverly named “users” and “passwords”. Add all your favorite type designers until your heart’s content.

A little help

I’ve included a few methods to help is find out what the ip address is of our server since sometimes this is not terribly straight forward. These are the addresses that we’ll direct out client to, so try out this code in FontLab before running the server:

1
2
3
4
from robofab.tools.remoteTCP import FontLabServer
myServer = FontLabServer()
print “My local ip: %s” % myServer.getInternal_ip()
print “My internet ip: %s” % myServer.getExternal_ip()

And without a client, a server just becomes a looping process

I’ve taken the majority of this page to describe the server because that’s really the main difference between RemoteTCP and the standard RoboFab Remote. I’ve tried to duplicate it’s syntax so please read their documentation for client-side usage. Sure it may not be as riveting as this page, but if you’re into things like “usable” or “having a clear point”, well you just may like it over there. If you are working with your client/server on localhost then the RemoteTCP functions should work the same as their RoboFab brothers and sisters. Try running these examples in your code, everything should work as it would with the RoboFab Remote:

1
2
3
from robofab.tools.remoteTCP import runFontLabRemote
x = runFontLabRemote(print 1+1)
print x

You’ll see this in the output window:

2

Send a glyph over to FontLab:

1
2
3
from robofab.tools.remoteTCP import transmitGlyph
f = OpenFont()
transmitGlyph( f['a'] )

Now like I said before, this only works if you’re sending code to a server you’re running on the same machine (and I’m guessing you more than likely are). If your sending code out over the network then we’ll need to supply our functions with some additional parameters:

1
2
3
4
5
6
7
8
9
10
11
12
from robofab.tools.remoteTCP import runFontLabRemote
code = “print 1+1”
host = “192.168.0.1”
#using the output of myServer.getInternal_ip()
port = 1455
user = “erik”
password = “officina4eva”
print runFontLabRemote( code, host, port, user, password )
path = “c:\my\path\to\UFO\directory\”
f = OpenFont( path )
glyph = f['a']
transmitGlyph( glyph, host, port, user, password )

Errata, or “Oh now you tell me”

So while it has been my every intention to implement RemoteTCP so that it produces the same results as the RoboFab Remote, I can’t exactly be sure of this. Since I’m unable to run the latter in Windows I must admit that I’ve never actually seen what the original does. I can certainly infer from the examples what would happen, and since most of it’s “guts” have been ripped right out of it and put into RemoteTCP — I can hope for similar outcomes, but you know these things can get a little dicey when you are sending strings out into the great unknown. If you see behavior that’s inconsistent or a function that hasn’t been implemented correctly then please let me know.

And finally, if you’ve made it this far it’s worth mentioning that actually running a server out of FontLab can produce some funny results. Funny like a “what the f — ”, Pauly Shore kinda funny, not really a laugh out loud funny. While it’s a fine program for designing a typeface, it’s not exactly the most robust production environment. I’ve never had the server actually crash FontLab but the interface will freeze up quite consistently — though it will still accept and process requests from the client in this state. Oh well, I guess it might be awhile before my visions of harmonic collaborate typeface design become a reality after all. Maybe this is why those Mac designers make fun of me.

Posted on January 26, 2008

Tags: ,

Hey, cool! What about a remoteTCP version which runs without FontLab? using NoneLab, regular Python and UFO?

Comment by erik — January 26, 2008 @ 3:10 pm

Hey Erik. The RemoteTCP server will indeed run without FontLab, though it will simply act as a remote Python interpreter — processing a line of code and spitting out the result before closing the connection. I’d like to implement a NoneLab server with a web interface, so once I get some basic code together I’ll share.

Comment by billy — January 28, 2008 @ 10:49 pm

Leave a comment