libactor – a C library based on the Actor model

Recently I’ve been really interested in functional, concurrent programming languages, such as Erlang. This prompted me to have some fun in C, and try to implement a simple library that is based on the Actor Model.

Right now it is usable, although it may not be ready for production. It uses pthreads and the library handles all of the threading issues, so you don’t have to worry about any of it at all.

In a future version I plan to add more sandboxing to the actors, so that when one actor crashes, they don’t all go down!

Right now it supports the following:

  • Spawn actor
  • Sending messages
  • Broadcast message
  • Actor memory management convenience functions(when an actor dies, the memory is freed!)

Here is what a simple ping/pong example looks like:

#include <stdio.h>
#include <libactor/actor.h>
 
void *pong_func(void *args) {
        actor_msg_t *msg;
 
        while(1) {
                msg = actor_receive();
                if(msg->type == PING_MSG) {
                        printf("PING! ");
                        actor_reply_msg(msg, PONG_MSG, NULL, 0);
                }
                arelease(msg);
        }
}
 
void *ping_func(void *args) {
        actor_msg_t *msg;
        actor_id aid = spawn_actor(pong_func, NULL);
        while(1) {
                actor_send_msg(aid, PING_MSG, NULL, 0);
                msg = actor_receive();
                if(msg->type == PONG_MSG) printf("PONG!\n");
                arelease(msg);
                sleep(5);
        }
}
 
 
void *main_func(void *args) {
        struct actor_main *main = (struct actor_main*)args;
        int x;
 
        /* Accessing the arguments passed to the application */
        printf("Number of arguments: %d\n", main->argc);
        for(x = 0; x < main->argc; x++) printf("Argument: %s\n", main->argv[x]);
 
        /* PING/PONG example */
        spawn_actor(ping_func, NULL);
}
 
DECLARE_ACTOR_MAIN(main_func)

There is a more detailed example in the source distribution, located in the examples/ directory.

You can get the source here. Please, let me know what you think about it, it was really fun to write!

Documentation is available here: http://chrismoos.com/libactordocs/

Share this post:
  • Digg
  • del.icio.us
  • Facebook
  • Reddit

Colloquy for iPhone — Push Notification Server

Colloquy is a great IRC client for Mac, as well as the iPhone. Currently, to run Colloquy on the iPhone you must purchase the mobile version from the App Store. The other option is to download the source and build it yourself, but you must be a registered iPhone developer to run it on an actual iPhone. Also, if you intend to use push notifications (via the Colloquy ZNC plugin), you must have a push certificate as well.

Getting Started

I am going to assume that you have znc installed, and you know how to use it. Next, we need to install the Colloquy ZNC module, so that Colloquy can communicate with ZNC (and allow us to have push functionality). See this page for complete instructions.

The module for ZNC accepts commands from the Colloquy client, notably information on push notifications(device token, etc,.).

Modifying the Colloquy Mobile Source

Next, we need to download and build the source. Once you have downloaded the source and loaded up the Mobile Colloquy project in Xcode, we need to make a few modifications.

Certificates

To run any application on an actual iPhone device, it must be signed. Login to your Developer portal on Apple’s site and generate a certificate (and make sure to enable push). Download the certificate and install it. Next, assign that certificate to the Colloquy Mobile Project. Project…Edit Active Target. Make sure that under the Properties tab, you have the same Identifier name that you used when generating the certificate. Go to Build, and then Code Signing Identity and select the certificate.

Modifying the source

Next, find the CQConnectionsController.m file (Controllers/Connections) and change the following line from:

[self sendRawMessage:@"PUSH service colloquy.mobi 7906"];

and change it to:

[self sendRawMessage:@"PUSH service 127.0.0.1 7906"];

This will make the client tell the Colloquy ZNC module to send push notifications to our custom server.

Build the project and put it onto your device.

Push Server

I wrote a simple python script that waits on port 7906, receives a connection from the Colloquy ZNC module, and then pushes a notification to your phone (via Apple’s Push Service).

The script requires your push certificate and private key file so it can authenticate to Apple’s push service.

Export the push certificate and private key as a .p12 from Keychain Access. After that, we have to convert it to PEM format:

openssl pkcs12 -in key.p12 -out certs.pem -nodes

where key.p12 is the file exported from Keychain access.

After that, you may need to put that certs.pem file on your server that you are running ZNC on.

Installing the Colloquy Push Server

Run the following to install the Colloquy Push Server:

sudo easy_install http://www.tech9computers.com/ColloquyPushServer-0.1.tar.gz

Next, run the command colloquypushsrv.py to make sure installation was successful.

The usage looks like this:

usage: /usr/local/bin/colloquypushsrv.py [-p listen_port] [--sandbox] [-b] certs_file
	Command Summary:
		certs_file	        PEM encoded Apple Push certificate and private key file(absolute path)
		-p listen_port	Default Listen Port: 7906	
		--sandbox 	Connect to Sandbox Service
		-b		        Run in background

Now, let’s start the push server in the foreground. Make sure to specify the full path to the pem file we created.

colloquypushsrv.py ~/certs.pem

Conclusion

Finally, connect to your ZNC server with the custom built Colloquy Mobile. Your iPhone should register with the ZNC module. After, exit the Colloquy Mobile application and pull up Colloquy (or any other IRC client) on your desktop. Send yourself a message, and see if you get the push notification!

I realize this process may not be completely clear, so if you have any questions, I would be happy to walk you through the process.

Also, I just wrote this up today, so it may not be production ready :) .

Enjoy!

Share this post:
  • Digg
  • del.icio.us
  • Facebook
  • Reddit

Writing a FreeSWITCH Caller ID spoofing interface

Lately I have been really interested in voice over IP, I think there is a lot of power in it. I was using Asterisk, but I’ve moved onto a much better and more powerful solution, FreeSWITCH. I was playing with it recently and decided a Caller ID spoofing interface would be fun.

When the following script is ran, it will prompt you for an access code, and if it is correct, it will let you specify a number to spoof, and a number to call. Its fun :) . Also, it can send an email whenever a spoofed call is made (if you want to track your friends usage, for example).

To use the following script, put this in your dialplan: (I’ve put spoof.py in the fspy package.)

<application action="python" data="fspy.spoof"/>

spoof.py

import os,sys
from freeswitch import *
from datetime import datetime
from time import mktime
import httplib
import urllib
import random
import smtplib
 
def get_number(session,invalid,num=10):
	digits = session.getDigits(num, "#", 6000)
	if digits == '':
		if invalid == 3:
			session.speak('You have entered too many in valid entries. Goodbye.')
			session.hangup()
		else:
			session.speak('Invalid entry. Please try again.')
			get_number(session,invalid+1)
	else:
		return digits
 
def handler(session, args):
	session.answer()
	session.set_tts_parms('cepstral', 'Allison')
 
	session.speak('Please enter the 4 digit access code.')
	code = get_number(session,2,num=4)
	if(code == None or code != '6969'):
		session.speak('Invalid access code, goodbye!')
		session.hangup()
		return
	session.speak('Please enter the number you would like to spoof.')
	spoof_number = get_number(session, 0)
	session.speak('Please enter the number you would like to call.')
	dest_number = get_number(session, 0)
	session.setVariable("effective_caller_id_number", spoof_number)
 
	session.speak('Calling...please wait')
	server = smtplib.SMTP('smtp.mydomain.com')
 
	fromaddr = 'freeswitch@mydomain.com'
	toaddrs = ['someaddr@mydomain.com']
	subject = "A spoofed call was made"
	msg = ("From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n" % (fromaddr, ", ".join(toaddrs), subject))
	d = datetime.now().strftime('%A, %B %d, %Y %I:%M%p')
	msgContents = "Date: %s\nCaller ID: %s\n\nDestination Number: %s\nSpoofed Number: %s\n\n\nSincerely, \nFreeSwitch Spoofer" % (d, session.getVariable("caller_id_number"), dest_number, spoof_number)
 
	server.sendmail(fromaddr, toaddrs, msg+msgContents)
	session.execute('transfer', dest_number)
Share this post:
  • Digg
  • del.icio.us
  • Facebook
  • Reddit

Building an Erlang chat server with Comet – Part 3

You can see a live demo of the following tutorial here.

Overview

In the last part, we implemented the first version of our chat server. Now that the framework is down, we can start adding some more features. You can find the source for this tutorial here

In this part, we will add the following features:

  • Rate Limiting for Messages
  • Admin Login
  • Kick/Ban users
  • Limiting connections per host

Rate Limiting

This feature will *help* in stopping people from spamming the chat room. It isn’t very complex, but it will give you the idea of what rate limiting can do. The algorithm for rate limiting is very simple, if a user sends too many messages in a certain interval, stop them from sending. At the top of chat_room.erl I’ve added the following:

Continue reading ‘Building an Erlang chat server with Comet – Part 3’ »

Share this post:
  • Digg
  • del.icio.us
  • Facebook
  • Reddit

Building an Erlang chat server with Comet – Part 2

You can see a live demo of the following tutorial at chat.tech9computers.com

Getting into the code

In the previous part, I introduced the chat system and how it should work. Now we are going to write the chat_postoffice, chat_mailbox, chat_room, and chat_web modules. Before you read download the source for this tutorial here. and dedicate about 20 minutes to read through this tutorial, because it’s kind of long (sorry).

Setting up the project

When you look at the source, take a look at the structure of the files and folders. There is a makefile to help you build and run the project. To run the server, just do the following:

$ cd erl_chat
$ make erl_chat

This will compile all the code, and start the OTP application. The web server runs on port 8000.

The Mailbox Process

Before we set up the post office, let’s define how a mailbox will work. First, it will run in its own process and keep a list of messages. Essentially it is just a loop, that accepts the following messages:

Continue reading ‘Building an Erlang chat server with Comet – Part 2’ »

Share this post:
  • Digg
  • del.icio.us
  • Facebook
  • Reddit