Thomas S. Chin
Columbia University
New York, NY 10025
tchin@cs.columbia.edu
This project seeks to define an interface to an addressbook for generic Internet Telephony applications. One goal of the project is to not only to provide tools to interface with a standard directory service, but to also provide the means by which one may merge the addressbook features of multiple applications together to access a singular database. Would it not be nice to have a shared email and Internet telephone directory?
The product of this project not only facilitates accessing an accepted directory service standard, but also permits logging of events into the same directory. The use for this will become obvious.
With the advancement of higher speed network technology, new types of
information exchange are being developed on the Internet. One such
application is emerging Internet Telephony. The relatively new and
developing technology is the ability to place "phone calls" across the
Internet to single or multiple parties.
In order to place a call to another party, you need to specify the address
of the other individual. This address is very similar in specification as
a standard Internet email address, and in most cases, is the same:
As with any type of application, the interface into the program plays just
as an important role as the actually functionality. Of course Internet
Telephony packages can require that you enter the address of the person
that you are wishing to call every time, but this would eventually become
a very tiring process. Just remember adderesses will become a challenging
task as your base of contacts grow.
The management of addresses in the computer world is commonly facilitated
through the usage of an "addressbook". Many applications, that are
address centric, all support this notion, and is a natural progression for
the development Internet Telephony.
The mere storage of addresses is only the first step towards a more
complete telephony package. As in the world of POTS (Plain Old Telephone
System) calls, there exists a device called an "answering machine". This
device serves the purpose of recording messages when one is unable to
answer a call. The ability to log (and timestamp) messages is also a
necessity for Internet Telephones. Such a tool can be included in the
functional aspects of an Internet Telephony Session Initiation Protocol
(SIP) [3] thus providing a more powerful tool.
The initial project proposal sought to provide seamless integration with
the Netscape addressbook. The Netscape addressbook was chosen because
Netscape has become an industry standard, and has a relatively well
designed interface into its email addressbook. All the information stored
in this addressbook would also be relevant to an Internet Telphony
addressbook. As the project progressed, it was discovered that Netscape
stores its addressbook information in an unpublished format
[5]. On UNIX architectures, this addressbook file is:
After extensive searching for the format of this file, and contacting
Netscape support without an expensive support contract, there was still no
information attained defining the nature of this file in any way.
Professor Henning Schulzrinne then suggested that I use the export
feature of Netscape to essentially convert the file to the LDIF (LDAP Data
Interchange Format) [2] format.
Further investigation of LDAP (Lightweight Directory Access Protocol)
[4] proved it to be a logical choice for an addressbook.
Netscape has provisions to import LDIF files and access remote LDAP
servers. As LDAP becomes more of a standard for generic directory
services, this choice for a file format will smoothly phase into the
trend.
This project only serves to demonstrate the possiblities that a generic
directory architecture (LDAP) can have in intergrating heterogeneuos
communication packages and the added functional aspects it can render to
the interface of an Internet Telephony package. It does not provide a
"complete" out of the box solution in its present form, but merely
provides a strong basis and argument for the further development of this
type of design.
Many newly developed communications applications (Netscape Cooltalk, ICQ,
CUCM, etc.), and those not centered up real-time audio/video conferencing
are developing addressbook add-ons of their own. They all share common
information: name, address, etc. This set of tools that I have done for
this project seeks to provide a common architecture that can unify all
these applications. Your applications can share the same directory with
alongside the Netscape addressbook.
The Lightweight Directory Access Protocol (LDAP) is a scaled down version
of the DAP (Directory Access Protocol) as defined by the X.500 standard
for network directory services. It is defined as a network protocol used
to query directory servers for information that originated at the
University of Michigan.
The LDAP Data Interchange Format (LDIF) is a file format that can be used
to import and export directory records from LDAP servers. The format is
robust enough to serve as a simple flat file directory persistent store.
In the simplest form, it is seen as a name-value pair separated by a
colon. The LDIF format also employs base64 encoding which can be used to
encode large value member and/or binary information.
The basis of this design is to provide a scalable, generic, and logical
solution to the addressbook backend management challenges. The LDAP/LDIF
proposals have been proven and is a rising standard for all types of
directory services. This protocol provides the means for local and remote
databases accesses.
The solution is termed scalable because it seeks to conform to the LDAP
model of a distributed database. The distributed database design is a
proven scalable architecture by the size, performance, and reliability of
handling a large database task, the complete Internet name space (DNS).
The implementation portion of the project is logically separated into two
portions:
This natural separation allows this tool to be used with scripting
languages (command line interface), and more seamlessly intergrated
through the usage of the libraries. The actually command line utilities
link against the same library set.
The libraries allow mainipulation of LDIF files which may be imported
into and exported from the Netscape addressbook. This same file can also
interface in the same manner with LDAP servers.
Another goal of this project to provide a set of code that is
architecturally independent for UNIX systems (it may compile on other C
compilers also). The current code base has been tested on the following
platforms:
Porting this library to ANSI C compliant systems should not be an issue.
This portion of the document will describe the implementation portion of
the project. Click here for the source code.
Libraries
The library set includes two modules:
These two modules were written by me based on the IETF drafts for the
base64 [1] and LDIF formats.
The
The
The
The elements in the name-value pair array (
Library examples:
Loading and saving a LDIF file:
The method
Command Line Utilities
The command line utilities were written using the above mentioned
libraries. It takes the LDIF format and incorporates functional services
that external applications may need.
The following two utilities:
both allow the specification of a LDIF file to load, but will default to
The logging utility will mark the description (notes in Netscape) field of
the person designated by
The lookup utility can be used to locate an address of an individual based
on a
As you can see, these two tools give way to a simple yet robust directory
service interface for the growing Internet Telephone applications.
Example CGI
A sample CGI (
Included with the source code are two programs that served as test bed
for the functional aspects of the base64 and LDIF library functions
(base64_test.c and ldif_test.c respectively).
For future enhancement, the LDIF library set should support queries to
remote LDAP servers. This should be done by writing a network
communications module to handle LDAP requests. Generic phonebook services
can be provided on large external databases. With these databases in
place, Internet Telephony may also provide a "caller ID" service showing
credentials of the incoming call (way beyond what the present POTS systems
provide).
This project has sought to provide a layout for a generic database
solution for Internet Telephony. At the same time, this same foundation
may serve as an "addressbook" unification for all communication based
applications on the Internet. Third party directory services may be
implemented to mimic the facilities that we have with the POTS systems.
The implementation portion of the project chose LDAP as the distributed
directory service architecture to use. The future finalized directory
service of choice may or may not be LDAP, but I am very confident that it
will be of the same nature.
As with any proposal, it should be critized in the effort to find the most
scalable, optimal, and reliable solution. Many of the ideas and protocols
that I chose to use in this project are based upon already proven
technologies or architectures. Hopefully, all the positive aspects of the
individual parts of the design will give way to a comparable solution.
fill all these in later
Introduction
name@name.of.computer.net
~/.netscape/abook.nab
Related Work
Background
Architecture
Program Documentation
base64
(base64.h and base64.c)
ldif
(ldif.h and ldif.c)
base64
module is an essential part of the
ldif
module. The functions in here are used to decode and
encode base64 strings.
char *base64_decode_string(char *string)
This function will convert
string
from a base64 encoded
string to a regular text string (the return value is a newly allocated
string).
char *base64_encode_string(char *string)
This function will convert
string
from a regular text string
to a base64 encoded string (the return value is a newly allocated string).
ldif
module is a bit more involved and will be essential
for interfacing with LDIF files. It is based on the following structures:
typedef struct {
char *name;
char *value;
} nv_item_t;
typedef struct {
nv_item_t *members;
} ldif_item_t;
nv_item_t
is a name-value pair of strings. The
ldif_item_t
represents a single LDIF record, which is
composed of an array of name-value pairs.
void *add_to_array(void **array, void *new_item, size_t size)
This function allows a
new_item
of a given size
to be appended to an existing array
. The return value is the
array itself (and can be used optionally).
int ldif_read_file(const char *fname, ldif_item_t **ldif_ptr)
This function will read the file
fname
and fill in the array
pointed to by ldif_ptr
. The array (pointer) must be set to
NULL if it is empty. The return value is non-zero on success.
void ldif_pipe_record(const ldif_item_t *ldif_item, FILE *pptr)
This function will take a single record
ldif_item
and write
it to the pipe pointed to by pptr
in an LDIF record format.
void ldif_pipe_record_text(const ldif_item_t *ldif_item, FILE *pptr)
This function will take a single record
ldif_item
and write
it to the pipe pointed to by pptr
in a text format.
int ldif_save_file(const char *fname, const ldif_item_t *ldif_list)
This function will save a complete array
ldif_list
of records
to the file named fname. The return value is non-zero on
success.
char *ldif_get_value(const char *name, const ldif_item_t *ldif_item,
char ***ptr)
This function will return the value associated with
name
in
the record contained in ldif_item
. If ptr
is
non NULL, it will be pointed to the value element in the LDIF record (this
is used when one wishes to modify the value).
members
) are
of text string format. When loading and saving the file, the base64
encoding/decoding is handled automatically. The members
array is NULL terminated, so when you encounter a members[i].name ==
NULL
that signifies that there are no more name-value pairs (the
NULL name is not valid).
/* this must be set to NULL when empty */
ldif_item_t *ldif_array = NULL;
if (!ldif_read_file("foo.ldif", &ldif_array)) {
fprintf(stderr, "Error reading file.\n");
exit(-1);
}
if (!ldif_save_file("bar.ldif", ldif_array)) {
fprintf(stderr, "Error saving file.\n");
exit(-2);
}
add_to_array
can be used in the following manner
to add a new name-value pair to the ldif record:
ldif_item_t ldif_rec;
nv_item_t nv_item;
memset(&ldif_rec, 0, sizeof(ldif_item_t));
memset(&nv_item, 0, sizeof(nv_item_t));
nv_item.name = "name";
nv_item.value = "value";
add_to_array((void **) &(ldif_rec.members), &nv_item, sizeof(nv_item_t));
nv_item.name = "name2";
nv_item.value = "value2";
add_to_array((void **) &(ldif_rec.members), &nv_item, sizeof(nv_item_t));
ab_log
(ab.h and ab_log.c)
ab_lookup
(ab.h and ab_lookup.c)
abook.ldif
when not specified with the -f
option.
ab_log [-{f filename}] mail subject
f {filename} open specified ldif file
h|? help
mail
with a time stamp and
subject
. This particular utility may be used to log when you
attempt to call an individual, with the subject being the result of the
attempt and/or subject of the conversation. This same program can be used
to log incoming calls, and can be used to serve the purpose of an
answering machine.
ab_lookup [-{{f filename}|{l|t}|{g|m}}] query
f {filename} open specified ldif file
g search through givenname (default)
l output complete record(s) in LDIF format
m search through mail
t output complete record(s) in text format
h|? help
givenname
. By default, this utility merely outputs the
address(es) that match the criteria. This is useful when searching for
the address of the person you wish to place a call to. As an option, the
program can dump the complete record for the matches in both an LDIF and
text format, so more information can be screened. It can also accept an
address (mail
) as the basis of its query. The purpose of
this feature is to allow an Internet Telephony package to automatically
lookup information of an incoming call and display it on the screen for
the user to see.
ab_log.cgi
and ab_log.html
) is
included with the source distribution. This CGI will log an entry into
the addressbook. The CGI is basically a wrapper around
ab_log
, so you might need to modify the path to the logging
utility.
Measurements
Task List
Conclusion
References