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 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 |
|
TimeStart | TimeEnd | ThroughPut |
|
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
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
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 Varians Internet pricing pages
http://www.sims.berkeley.edu/resources/infoecon/
Some FAQs about usage based pricing, Jeffrey K. MacKie-Mason,
Hal R. Varian
ftp://alfred.sims.berkeley.edu/pub/Papers/useFAQs.html