CS519 Final Report

Phonedation

Conor Hunt (ch65), Stephen Ostermiller (smo8)

Group5, Billing


 


What did you set out to do?

Overall goal:

Our overall goal at the start of the project was to create a stable and very flexible billing system for the telephony system.

Flexibility and extendibility:

We knew that we would not be able to anticipate exactly what billing system would work best for the telephony system from the start of the project so one of our main design goals was to make the system very flexible and extendable.

Coding:

Towards this goal we decided to create a very extendable java interface. We would create one class BillingServer through which other groups could call our methods. We also created a class BillingType which enables us to handle almost any billing method that we care to define. We decided that internally in BillingServer we would handle what information was tracked for a call using a BillingType object. We would also enable groups that were calling us to pass us BillingType objects so that they could define how information is tracked for billing. A fuller explanation of how billing type works can be seen in the seen in the interfaces section. However our initial goals were to enable it to handle multi party calls with ease and to handle special billing cases: throughput billing instead of time billing, different users taking different responsibilities for the cost of a call, reverse charge billing, billing depending on time of day. These were our initial goals, but BillingType had to be extendable enough to hold information for any other billing method that we might come up with.

Stability and crash recoverability:

While billing is not central to the core functionality of the telephony system unless we there is a good billing system then Phonedation is not likely to make us all very rich (which is hopefully the final outcome). So the system must have a reliable database to keep track of the calls and their billing information. This database must be reliable enough so that it can recover if there is a crash

Towards this goal of stability we decided to use proven technologies. A Microsoft Access database running on NT, accessed via ODBC using SQL requests. If we wanted to use an industrial strength system then this would just involve replacing Access with SQL server or Oracle. The database is only accessed via ODBC code.

Interfacing:

We wanted to make our interfacing with other groups a simple and painless process for them while at the same time creating a flexible interface to handle them passing us information that we could not anticipate at the start of the project. We were not sure how to handle this at the start of the project but we anticipated that it would involve a careful client/server interface splitting using JDBC.

Security:

One worry was the security of the system. Our initial goal was to create an authentication system with other groups that wanted to use our BillingServer methods. However when later down the line we realized that our interface with other groups was going to be through RMI we realized that this comes with a built in authentication and security system!

Pricing schemes.

Our only goal at the start of the project was that our pricing scheme be very flexible. We were not sure of what pricing scheme we would actually use, whether it would be billed by bandwidth, time or application type. Our initial goal was just that we wanted to be able to handle all of these in the pricing scheme.

What did you actually accomplish?

We believe that we accomplished these goals with our billing system: To create an extendable and flexible billing system. Here is a list of the areas that we concentrated on and what we accomplished in each.
 

            Billing Database

    The database runs on a remote machine. It uses a Java RMI/JDBC bridge so that we can call it remotely using Java RMI functions. This works extremely well as far as stability goes, the RMI/JDBC bridge has been running for 2-3 weeks now and it has not crashed. Any miswrites due to malformed SQL requests that we have been made have been caught through Java exceptions without causing any problems.

    The access database is completely separate from the telephony system and any crashes elsewhere in the telephony system cannot affect it.

    Calls to the database are made via SQL queries. SQL is a powerful language and the database can be modified in pretty much any way that we want to. This gives us large flexibility in manipulating the database remotely.

    For every user in every call a record is kept in this format:
     
    CallID UserID
    Amount
    TimeStart TimeEnd ThroughPut
    Start
    End
    105
    23456
    60
    913232699376 913232764591 0 Wed Dec 09 14:44:59 EST 1998 Wed Dec 09 14:45:23 EST 1998

    CallID is the ID that billing gives a call. User ID is the ID of the user in the call. TimeStart, TimeEnd are the time the user started being billed for this call and the time that the user finished being billed for this call. Start and End are just human readable formats of the TimeStart and TimeEnd information. Throughput is a measure of how much throughput a user used during a call. This call was time billed so the throughput was not updated

    Simple ideas that we did not have time to implement:

    Redundancy

    To enable billing to handle the machine holding the database going down have the billing database running on two separate machines. If one of the machines goes down the billing server will create a connection to the second machine and update that database. It is very easy to merge two databases with similar record fields. So once the main database machine comes back up then it is possible to remerge the databases with one SQL query.

    Billing Interface

    Our billing interface uses RMI. This is an extremely flexible interface. Distribution of code is simple. An RMI registry is running on the phonedation machine. We register our code with this RMI registry and tell it where to find the stubs and security policy for accessing this code (the code is held on a web server also on the phonedation machine). Anyone who wishes to use our code can then just call the RMI registry and use the billing RMI object to access our database methods. The RMI registry system has a good security system, implemented by policies, which can be used to restrict access to code.

    Pricing Schemes

    Our initial goal was to allow for any type of pricing scheme that we could imagine. We accomplished this using two things:

    The BillingType class and the pricing database.

    We have several generic methods that can be used to bill for calls (EstablishCall().. etc). These calls handle the creation and management of a BillingType object internally. However it is also possible to use a BillingType object to bill for a call. We have methods which accept billing type objects and will use these to figure out how the call should be billed.

    A BillingType object keeps track of the users in a call, what type of call this is (fax, etc), and what type of billing to use. It gives great flexibility in how a call is handled. For example it is possible to bill certain users depending on the type of the application (fax, conferencing.. )

    Call pricing for time based calls:

    Every user in a call has a weight for that call. This weight is a floating point number between 1 and 0. It tells us what fraction of the total call cost a user is paying for. In a basic call, from one user to another user this defaults to 1.0 for the person making the call. In multiparty calls, any user can take any fraction of the cost of the call. It is also possible to bill a user not in a call for the cost of that call (a 1-800 call for example).

    When calculating the cost of a time billed call the formula is as works

    User Cost = User Weight * Time In Call / Unit Time * Unit Cost

    User Weight = The fraction of the total cost the user is paying for.

    Unit Time = The unit of time that we charge by ie. Bill every six seconds (accurate to the millisecond)

    Time In Call = The time the user spent in the call

    Unit cost per unit time = The cost per unit time (ie 10 cents for 60 seconds).

    Unit Time and Unit cost per unit time are retrieved from the pricing database. We realised that we did not want to have to manage a large amount of different pricing schemes directly in our code. This would create an inflexible pricing scheme. Instead we set up a flexible billing database to handle pricing.

    Each record in the pricing database consists of:

    Type of Call, Unit Time, Unit Cost, Time Start, Time End

    So an example record might be:

    [2, 6000, 10, 9:00, 20:30]

    This is a type 2 call (conferencing). Billed every 6000 milliseconds (unit time) and billed at 10 cents for every 6000 milliseconds (unit cost). If the call falls in-between 9:00am and 8:30pm then use this billing method.

    For pricing a call we first search the billing database to see if there is a pricing record which has the same Type of Call we are looking for. If so then we get the pricing records for that type of call. We check to see what time the call started at and compare it to each pricing record. If it falls in between the time that the pricing record covers then we use that pricing record. If there are multiple matches for pricing records then we choose the one covering the smallest time period.

    We can also handle bandwidth-billed calls in a similar fashion with another pricing database. We did not have time to implement this, but it is trivial to do and all it requires is that signalling passes us the bandwidth that a call uses. We have all the calls and database set up to do this, but there was not time to set up the interface with signalling/gateway for the bandwidth information.

    Security

To prevent misuse of the billing system we decided to keep the billing database functions (reading writing records etc.) completely separate from any of the interfaces that a user can access. We created a private BillingDB class, which is only accessed through BillingServer. This billilngDB class has the information needed to access the database (password, IP and database name). The RMI registry running on the database machine (this is the bridge through which JDBC queries are made to the remote machine) also has an RMI group policy file. So if necessary we could restrict access to certain users, ports or IP’s. To help understand how these components interact here is an example of program flow for a billing call.
(Assuming that all the relevant RMI registry and RMI/JDBC bridges are already set up)

Signalling receives an incoming call
Signalling calls our CallEstablished() method in the BillingServer class using RMI
CallEstablished method creates a BillingType object for this call, adds the relevant users in the call to the object and then adds this object to a hashtable of calls in the BillingServer.
Sometime later signalling calls our CallTerminated() method in BillingServer again using RMI
CallTerminated method calls WriteOutAllCallData() to write out all the data to the database for the call

WriteOutAllCallData()
The cost of the call is calculated for each user. To do this the pricing database is called from BillingDB using RMI/JDBC to see how the call should be priced (ie. check to see how much to bill for throughput, or check to see how much to bill for a certain time period)
The information for each user in the call is written out to the calls database using addRecord from BillingDB which uses RMI/JDBC to call the database.
The BillingType object for this call is removed from the hashtable of calls in BillingServer.
 

Problems

The first problem that we faced was learning RMI. Signalling decided early on that RMI would be a good method to use to communicate with them. We knew basically how RMI functioned but no-one had any real ideas as to how to code an RMI application. As with learning any new programming concept it was a painful process at times. Not least because RMI is still developing and there are still some ‘interesting’ bugs in the Java 1.2 RMI implementation. For example, you must create a connection to the database before creating a connection to the RMI registry or all sorts of bizzare exceptions are thrown. This was only found after much trial and error and we are still not sure why it happens.

We could not get packaging to work for the java classes, we ended up just putting the classes in one directory.

Interfacing with the other groups was our main problem. Our code as we had envisioned it worked fine from a pretty early stage. However other groups really were not sure how they were meant to be interfacing with us. The only way that groups should be interfacing with us is via signalling, who calls us via RMI. Other groups did not seem to realise this at first and made requests to call us directly. After a series of meetings most of this was ironed out and we managed to get.

We had some problems with the Access database. Access can only store a maximum of 32 bit integers in a field and we needed to store 64 bit longs for the time a call starts and the time a call ends. We solved this with a little kludge, converting the numbers into strings, storing the strings in the database and then when we need the information again we convert them back into numbers.

What we learned

Code Interface

A robust interface for our code did wonders. Most of the problems that we encountered were due to inadequacies in our interface. For example, cases that were not supported or assumptions we made that turned out not to be true. The parts of the code interface that ended up as we originally planned were fairly easy to implement because of that.

RMI

RMI is extremely useful. It makes communicating between Java programs very easy. Although changing our interface from sockets to RMI changed the way we thought about the interface, RMI turned out to be a lot easier to implement than our original socket interface would have been.

Database

An access database works with Java very well. We were able to set up the JDBC-ODBC bridge and use the access database to log all calls to be billed. This is a huge plus over logging calls to a file because it is so easy to search.

Internet Pricing

Internet pricing is very complex. It is not easy to price internet services in a way that is easily billable. In setting up a pricing scheme we focused on three resources: time, bandwidth, and distance. A billing system that is based on these costs, bills more for more network usage so that users will pay according to how much burden they put on the system. Our billing scheme can handle a service for a duration or for our most widely implemented scheme, is a cost per time for a certain application.
 

What we would do differently next time

Interface

If we were to do this project again, we would probably start with the interface that we ended up with this time. Implement RMI from the beginning. It took some work to re-implement our classes as RMI classes.

Integration

Integration has also been another rather large problem. Our code needs to be called in specific instances so that it logs all calls properly and that it is able to bill everything. If we were to do this project again, we would work more closely with the people that are calling our interface to make sure that these calls get made properly. We have several methods and ways that things can be billed that will not get used because they are not being called. It would be nice to be able to use the full functionality of the billing. A tighter relationship with signaling would be desirable for this.

Where we could go further

One billing method that we did not implement is distance pricing. If we were to do this project again we would work to implement a distance pricing scheme so that calls are billed as to how far the call travels. This could either be done by using information from the users address or by counting hops on routers, or even by figuring out how many miles of wire a call travels. There are several reasons that this would be hard to implement, one of which is fairness to the customer. One would have to be careful not to bill customers for a call that is routed very poorly, i.e. not on the shortest possible path.

Something else that we could implement could be special deals. These might be designed to encourage customers to use the network at certain times of the day or to encourage full use of network resources. Telephone companies have been very successful with such schemes, Friends and Family and the like.

Another interesting aspect would be to research the actual network research, collect statistics and to see how well the pricing scheme we came up. Further research with a working network with actual users on it would allow fine tuning of the pricing schemes. With the flexibility of our pricing code this would be very easy to implement.
 

Interface that your team will provide to other teams to use

For full specifications see the attached javadoc documents.

BillingServer
BillingServerInterface.
BillingType

References

Session Initiation Protocol
http://www.cs.columbia.edu/~hgs/sip/sip.html

Java
http://java.sun.com/

Java API reference
http://java.sun.com/products/jdk/1.1/docs/api/packages.html
http://java.sun.com/products/jdk/1.2/docs/api/index.html

Java Language reference
http://java.sun.com/products/jdk/1.1/docs/index.html

Meetings
Sept. 25, 1998 meeting with Professor Keshav
Group Meeting (1,2,3,4,8)
Meeting with signalling (three meetings)
General Phonedation meeting every Tuesday after class.

RMI
http://java.sun.com/docs/books/tutorial/rmi/

JDBC
http://java.sun.com/docs/books/tutorial/jdbc/index.html

RMI/JDBC Interface reference
http://dyade.inrialpes.fr/mediation/download/RmiJdbc/Access/access.html

SQL Tutorial
http://w3.one.net/~jhoffman/sqltut.htm
http://www.instantdb.co.uk/

Microsoft Access online help

Setting up an ODCB interface to an access database.

Hal Varian’s Internet pricing pages
http://www.sims.berkeley.edu/resources/infoecon/

Some FAQ’s about usage based pricing, Jeffrey K. MacKie-Mason, Hal R. Varian
ftp://alfred.sims.berkeley.edu/pub/Papers/useFAQs.html