/** * File Name : BaseStation.java * * The University of Texas at Arlington * Software Engineering Center for Telecommunications * Object Oriented Testing Project * * (c) Copyright 2000 University of Texas at Arlington * ALL RIGHTS RESERVED * * Input : Different channels used in a wireless system are simulated using different ports * 20101 - Reverse control channel for sending controls to the Base Station * 20001 - Forward control channel for receiving controls from the Base Station * 20111 - Reverse data channel for sending data to Base Station * 20011 - Forward data channel for receiving data from Base Station * The Handset sends controls to Base Station in the following format: PhoneNum MesgType * The MesgType has the following values * 4 for registration * 10 for callinitiation * 0 for acknowledgement * 12 for ringback * 16 for connect * Output : The BaseStation connects to the Mobile Switching Center on the following ports * 7777 - for sending controls to MSC * 6666 - for receiving controls from MSC * 8888 - for sending data to MSC * 9999 - for receiving data to MSC * Supported Requirements : This code handles call requests from * (1) A handset to another handset in the same Base Station * (2) A handset to another handset in a different Base Station * (3) Many handsets in the same Base Station * (4) Many handsets in different Base Stations * * Classes in this file : BaseStation, BaseStationController, BaseStationControllerData, * BaseStationData, BaseStationForwardCrtl,BaseStationForwardData, * BaseStationTranceiverControl, ConnectionHandler, DataHandler, * HandsetSocket, Status, Storage * * Update History: * * Date Author Changes * ------------------------------------------------------------------------------ * 04/27/00 Susheela Smitha Kommaraju Initial code which handles * call requests in the same Base Station * * 05/01/00 Susheela Smitha Kommaraju Initiating connections between Handsets * in different Base Stations * * 05/04/00 Susheela Smitha Kommaraju Transfering data between different * Handsets in different Base Stations * and Satish Jonnalgedda * * Functional Description : This code handles call requests from any number of handsets. * Connection between handsets is established and handsets can * exchange messages * Error Messages : Null pointer exceptions result when the assumptions are not met. * Otherwise there are no error messages * Constraints : This code works under normal conditions i.e., when the handsets * are connected to both the Control channels. * * Assumptions : It is assumed that the Handset is never busy and is always ready to receive messages. * * **/ import java.io.*; import java.net.*; import java.util.*; public class BaseStation { public static void main(String args[]) { try { ServerSocket rc = new ServerSocket(20101); // receives controls from Handset ServerSocket fc = new ServerSocket(20001); // writes controls to Handset ServerSocket rd = new ServerSocket(20111); // receives data from Handset ServerSocket fd = new ServerSocket(20011); // writes data to Handset Storage stm = new Storage(); // Storage is a class which stores phone numbers // and IP address using hash tables Status sta = new Status(); // Status is a class which stores phone numbers // and if they are connected to a Handset // in the same basestation or different base station HandsetSocket hs = new HandsetSocket(); // stores the sockets at which the Handsets are listerns for controls HandsetSocket datas = new HandsetSocket(); // stores the sockets at which the Base Station // can send data to Handset HandsetSocket datar = new HandsetSocket(); // stores the sockets at which the Handsets send data new BaseStationController(hs,stm, sta).start(); // class BSC does forwarding and // receiving of messages and data to and from MSC new BaseStationControllerData(datas, datar,stm, sta).start(); new BaseStationTransceiverControl(hs,rc,stm, sta).start(); // class BTSC does connecting of handsets new BaseStationForwardCrtl(hs,fc).start(); new BaseStationForwardData(datas,fd).start(); new BaseStationData(datas,datar,rd,stm, sta).start();// class BTSD handles conversation between handsets } catch(Exception e) { System.out.println(e); } } } // This class accepts connections from handset sockets where control messages are sent from Base Station class BaseStationForwardCrtl extends Thread { private ServerSocket fControl; private int num = 1; public HandsetSocket haso = new HandsetSocket(); public BaseStationForwardCrtl (HandsetSocket hs,ServerSocket fc) { haso = hs; fControl = fc; } public void run() { try { for(;;) { Socket forwardControl = fControl.accept(); InetAddress iAddr = forwardControl.getInetAddress(); haso.takeSocket(iAddr, forwardControl); System.out.println("No. of Handsets accessing Forward Control Channels " + num); num++; } } catch(Exception e) { System.out.println(e); } } } // This class accepts connections from handset sockets where data are sent to Handset class BaseStationForwardData extends Thread { private ServerSocket fData; private int num = 1; public HandsetSocket daso = new HandsetSocket(); public BaseStationForwardData(HandsetSocket ds, ServerSocket fd) { fData = fd; daso = ds; } public void run() { try { for(;;) { Socket forwardData = fData.accept(); InetAddress iAddr = forwardData.getInetAddress(); daso.takeSocket(iAddr, forwardData); System.out.println("No. of Handsets accessing Forward Data Channels " + num); num++; } } catch(IOException e) { System.out.println(e); } } } // This class accepts connections from handset sockets where control messages are received from Handset class BaseStationTransceiverControl extends Thread { private ServerSocket sControl; private int num = 1; public Storage x; public Status y; public HandsetSocket hs; public BaseStationTransceiverControl(HandsetSocket haso,ServerSocket rc,Storage stm, Status sta) { hs = haso; sControl = rc; x = stm; y = sta; } public void run() { try { for(;;) { Socket revControl = sControl.accept(); new ConnectionHandler(revControl, x, y, hs).start(); System.out.println("No. of Handsets accessing Reverse Control Channels " + num); num++; } } catch(Exception e) { System.out.println(e); } } } // This class accepts connections from handset sockets where data are received from Handset class BaseStationData extends Thread { private ServerSocket rData; private int num = 1; public Storage x; public Status y; public HandsetSocket hs; public HandsetSocket hr; public BaseStationData(HandsetSocket datas,HandsetSocket datar,ServerSocket rd,Storage stm, Status sta) { hs = datas; hr = datar; rData = rd; x = stm; y = sta; } public void run() { try { for(;;) { Socket revData = rData.accept(); InetAddress iAddr = revData.getInetAddress(); hr.takeSocket(iAddr,revData); new DataHandler(revData, x, y, hs, hr).start(); System.out.println("No. of Handsets accessing Reverse Data Channels " + num); num++; } } catch(Exception e) { System.out.println(e); } } } // This class handles connections between handsets class ConnectionHandler extends Thread { private Socket incoming; private Storage storageobj; private Status statusobj; public HandsetSocket hs; public ConnectionHandler(Socket i, Storage x, Status y, HandsetSocket h) { incoming = i; storageobj = x; statusobj = y; hs = h; } public void run() { try { BufferedReader in = new BufferedReader (new InputStreamReader(incoming.getInputStream())); for(;;) { String str = in.readLine(); System.out.println("BS receives " + str + " from Handset"); StringTokenizer t = new StringTokenizer(str," "); String sourcePhoneNum = t.nextToken(); String mesgType = t.nextToken(); if (mesgType.equals("4")) { InetAddress iAddr = incoming.getInetAddress(); storageobj.takeAddress(sourcePhoneNum,iAddr); // BaseStationController.sendToMSC(str); } else if (mesgType.equals("10")) { BaseStationController.sendToMSC(str); storageobj.sendToHandset(hs, sourcePhoneNum, sourcePhoneNum + " 0"); } else if (mesgType.equals("0")) { if ((statusobj.getBSType(sourcePhoneNum)).equals("Same")) { System.out.println("HS is in the same BS"); String otherHS = statusobj.getOtherHandset(sourcePhoneNum); String mesg = otherHS + " 12"; storageobj.sendToHandset(hs, otherHS, mesg); } else { statusobj.bsType.put(sourcePhoneNum, "Different"); BaseStationController.sendToMSC(str); } } else if (mesgType.equals("16")) { String bsType = statusobj.getBSType(sourcePhoneNum); if (bsType.equals("Same")) { String destHandset = statusobj.getOtherHandset(sourcePhoneNum); String connectMesg = destHandset + " 16"; storageobj.sendToHandset(hs,destHandset, connectMesg); } else { BaseStationController.sendToMSC(str); } } } } catch(Exception e) { System.out.println(e); } } } // This class handles data transfer between handsets class DataHandler extends Thread { HandsetSocket hSend; HandsetSocket hRec; private Socket incoming; private Storage storageobj; private Status statusobj; public DataHandler(Socket i, Storage x, Status y, HandsetSocket hs, HandsetSocket hr) { incoming = i; storageobj = x; statusobj = y; hSend = hs; hRec = hr; } public void run() { try { BufferedReader in = new BufferedReader (new InputStreamReader(incoming.getInputStream())); for(;;) { String str = in.readLine(); InetAddress iAddr = incoming.getInetAddress(); System.out.println("BS receives " + str + " from Handset"); String scrNum = (String)(storageobj.inetToPhone.get(iAddr)); String bstype = statusobj.getBSType(scrNum); if (bstype.equals("Same")) { String destNum = statusobj.getOtherHandset(scrNum); storageobj.sendToHandset(hSend, destNum, str); if (str.equals(".")) { statusobj.updateTablesSame(scrNum,hSend,hRec,storageobj); } } else if (bstype.equals("Different")) { String msend = scrNum + " " + str; BaseStationController.sendDataToMSC(msend); if (str.equals(".")) { statusobj.updateTablesDifferent(scrNum,hSend,hRec,storageobj); } } } } catch(Exception e) { System.out.println("Call terminated"); } } } // This class the sockets at which the handsets are connected so that the Base Station // knows which handset to send the message to class HandsetSocket { Hashtable hsock = new Hashtable(); public synchronized void takeSocket(InetAddress i, Socket s) { //System.out.println("Before Adding" + hsock.size()); hsock.put(i,s); //System.out.println("After Adding" + hsock.size()); } public synchronized Socket giveSocket(InetAddress i) { return ((Socket)(hsock.get(i))); } public synchronized void updateTable(InetAddress i1) { try { (giveSocket(i1)).close(); hsock.remove(i1); // System.out.println("Removed an entry "); } catch(Exception e) { System.out.println(e); } } } // This class stores the information regarding the handset and sends the data as required class Storage { Hashtable inetToPhone = new Hashtable(); Hashtable allAddr = new Hashtable(); public Storage() { } public synchronized void takeAddress(String s, InetAddress i) { // System.out.println("Size of the hash table 1 before adding " + allAddr.size()); allAddr.put(s, i); inetToPhone.put(i,s); // System.out.println("For the key " + s+" the element in the hash table 1 is "+((InetAddress)(allAddr.get(s)))); // System.out.println("Size of the hash table after adding " + allAddr.size()); } public synchronized void broadcast(String s, HandsetSocket h) { Enumeration en = allAddr.elements(); while (en.hasMoreElements()) { try { InetAddress i = (InetAddress)(en.nextElement()); Socket x = h.giveSocket(i); PrintWriter outPage = new PrintWriter(x.getOutputStream(),true); outPage.println(s); } catch(Exception e) { System.out.println(e); } } System.out.println("Message " + s + " has been broadcast to all the handsets connected to BS"); notifyAll(); } public synchronized void sendToHandset(HandsetSocket h, String s, String m) { try { InetAddress i = (InetAddress)(allAddr.get(s)); Socket x = h.giveSocket(i); PrintWriter outMesg = new PrintWriter(x.getOutputStream(),true); outMesg.println(m); System.out.println("BS sends message " + m + " to Handset"); } catch(Exception e) { System.out.println(e); } } } // This class keeps track of which handsets are connected to which handsets class Status { Hashtable bsType = new Hashtable(); Hashtable connectedTo = new Hashtable(); public Status() { } public synchronized void addbsTypeSame(String h1, String h2, String b) { // System.out.println("size of hashtable bsType of status before adding " + bsType.size()); // System.out.println("size of hashtable connectedTo of status before adding " + connectedTo.size()); bsType.put(h1, b); bsType.put(h2, b); connectedTo.put(h1,h2); connectedTo.put(h2,h1); // System.out.println("size of hashtable bsType of status after adding " + bsType.size()); // System.out.println("size of hashtable connectedTo of status after adding " + connectedTo.size()); } public synchronized void addbsTypeDifferent(String h1, String b) { // System.out.println("size of hashtable bsType of status before adding " + bsType.size()); bsType.put(h1, b); // System.out.println("size of hashtable bsType of status after adding " + bsType.size()); } public synchronized String getOtherHandset(String s) { return ((String)(connectedTo.get(s))); } public synchronized String getBSType(String s) { return ((String)(bsType.get(s))); } public synchronized void updateTablesSame(String s,HandsetSocket hs, HandsetSocket hr,Storage g) { String connectedHS = getOtherHandset(s); bsType.remove(s); bsType.remove(connectedHS); connectedTo.remove(s); connectedTo.remove(connectedHS); InetAddress i1 = (InetAddress)(g.allAddr.get(s)); InetAddress i2 =(InetAddress)(g.allAddr.get(connectedHS)); hs.updateTable(i1); hs.updateTable(i2); hr.updateTable(i1); hr.updateTable(i2); } public synchronized void updateTablesDifferent(String s,HandsetSocket hs, HandsetSocket hr,Storage g) { bsType.remove(s); InetAddress i1 = (InetAddress)(g.allAddr.get(s)); hs.updateTable(i1); hr.updateTable(i1); } } // This class handles sending of control messages and data messages to MSC class BaseStationController extends Thread { Storage sgobj; Status stobj; Socket outgoing; static PrintWriter out; static PrintWriter out2; BufferedReader in; Socket incoming; Socket dout; HandsetSocket hs; public BaseStationController(HandsetSocket h, Storage x, Status y) { try { outgoing = new Socket("129.107.56.23",7777); // for writing controls to MSC out = new PrintWriter(outgoing.getOutputStream(), true); incoming = new Socket("129.107.56.23",6666); // for reading controls from MSC in = new BufferedReader(new InputStreamReader(incoming.getInputStream())); dout = new Socket("129.107.56.23",8888); // for writing data to MSC out2 = new PrintWriter(dout.getOutputStream(), true); sgobj = x; stobj = y; hs = h; } catch(Exception e) { System.out.println(e); } } public static void sendToMSC(String str) { String id = "1 "; try { String bsStr = id + str; out.println(bsStr); System.out.println("BSC writes " + bsStr + " to MSC"); } catch(Exception e) { System.out.println(e); } } public static void sendDataToMSC(String s) { String id = "1 "; try { String bsStr = id + s; out2.println(bsStr); System.out.println("BSC writes " + bsStr + " to MSC"); } catch(Exception e) { System.out.println(e); } } public void run() { try { for(;;) { String strMSC = in.readLine(); System.out.println("BSC reads " + strMSC + " from MSC"); StringTokenizer st = new StringTokenizer(strMSC, " "); if (st.countTokens() == 2) { String phoneNum = st.nextToken(); String mesgType = st.nextToken(); if (mesgType.equals("5")) { sgobj.broadcast(strMSC,hs); stobj.bsType.put(phoneNum,"Different"); } else if (mesgType.equals("0")) { String cMesg = phoneNum + " 12"; sgobj.sendToHandset(hs,phoneNum,cMesg); } else if (mesgType.equals("16")) { sgobj.sendToHandset(hs, phoneNum, strMSC); } } else if (st.countTokens() == 4) { System.out.println("Entered the approved message "); String approval = st.nextToken(); String bstype = st.nextToken(); String sourceNum = st.nextToken(); String destNum = st.nextToken(); if (bstype.equals("Same")) { String bMesg = destNum + " 5"; sgobj.broadcast(bMesg,hs); stobj.addbsTypeSame(sourceNum, destNum, bstype); } else if (bstype.equals("Different")) { stobj.addbsTypeDifferent(sourceNum, bstype); } } } } catch(Exception e) { System.out.println(e); } } } // This class receives data from MSC class BaseStationControllerData extends Thread { Socket din; BufferedReader in2; HandsetSocket hSend; HandsetSocket hRec; Storage stmobj; Status staobj; public BaseStationControllerData(HandsetSocket hs, HandsetSocket hr, Storage stm, Status sta) { try { din = new Socket("129.107.56.23",9999); // for reading data from MSC in2 = new BufferedReader(new InputStreamReader(din.getInputStream())); hSend = hs; hRec = hr; stmobj = stm; staobj = sta; } catch(Exception e) { System.out.println(e); } } public void run() { for(;;) { try { String data = in2.readLine(); System.out.println("BSC reads " + data + " from MSC"); int x = data.indexOf(" "); String destNum = data.substring(0,x); String s2 = data.substring(x+1); int y = s2.indexOf(";"); String s3 = s2.substring(0,y); String mesg = s3.trim(); stmobj.sendToHandset(hSend, destNum, mesg); if (mesg.equals(".")) staobj.updateTablesDifferent(destNum,hSend,hRec,stmobj); } catch(IOException e) { System.out.println(e); } } } }