SlideShare a Scribd company logo
« P2P Communication Framework on Android Platform »




                    Submitted by
                     Liu Tianwei

   Department of Electrical & Computer Engineering




              In partial fulfillment of the
            requirements for the Degree of
               Bachelor of Engineering
           National University of Singapore
ABSTRACT




    With Smartphone penetration reaching 37%(Nelson,2011) worldwide
    and predicted to reach 55% by the year 2014, the availability of
    powerful mobile devices in the pocket of every consumer is fast
    becoming a nom. However, the capabilities of these devices are often
    limited by data network in which they has access to, which are often old
    and are not designed to support the huge no of increasingly data hungry
    mobile devices.
    This paper aims to explore the alternatives to traditional network
    architecture focusing mainly on the P2P network architecture on mobile
    devices.
    To reach out to wider audiences, the open-source framework
    implemented in this project is based on the widely popular open-source
    framework for mobile device - Android. The framework allows
    developers to easily leverage on in-built hardware communication
    capability of these devices(3G/Wifi/Bluetooth) without having to deal
    with the underlying networking implementation.




!                                        !                                     !
!                                        !
ACKNOWLEDGMENTS




    I would like to express my heart-felt gratitude to Associate Professor Tay
    Teng Tiow for his invaluable guidance and support through the entire
    project. I would also like to thank the ECE department for the use of the
    facilities and the provision of android devices used for the experiments. I
    would also express my gratitude to my group of peers who had work with
    me and developed the Peer-to-Peer Multiplayer Android Game based the
    framework developed in the thesis. Their inputs has allow me to stress test
    and improve on the stability of the framework.




                                         ii




!                                         !                                       !
!                                         !
CONTENTS


    ABSTRACT                                             i

    ACKNOWLEDGEMENTS                                     ii

    LIST OF FIGURES                                      iii

    CHAPTER 1 INTRODUCTION                               1
       1.1 Background                                    1
       1.2 Problems                                      2
       1.3 Motivation                                    2
       1.4 Objective                                     2
       1.5 Use Cases                                     3
       1.6 Approach                                      4
       1.7 Assumption                                    4
       1.8 Results of Implementation Experiment          5
       1.9 Thesis Layout                                 5

    CHAPTER 2 LITERATURE REVIEW                          8
       2.1 Server - Client Architecture                  8
       2.2 Peer to Peer Architecture                     9
       2.2.1 Centralized Index                           10
       2.2.2 Query Flooding                              11
       2.2.3 Hierarchical Overlay                        12
       2.2.4 Distributed Hash Table                      13
       2.2.5 Advantages of Peer-to-Peer Architecture     13
       2.2.6 Disadvantage of Peer-to-Peer Architecture   13
       2.3 Server-Client Vs Peer-to-Peer                 14
       2.4 Proposed Architecture                         16

    CHAPTER 3 IMPLEMENTATION APPROACHES AND METHODOLOGY        17
       3.1 Platform                                17
       3.2 Hardware choices and limitations        18
       3.2.1 Bluetooth                             18
       3.2.2 Wireless Fidelity                     20
       3.2.3 Mobile Telecommunication              21
       3.3 Network Design                          23
       3.3.1 Control Byte                          24
       3.3.2 Source address                        25
       3.3.3 Destination address                   25
       3.3.4 Hop Count                             25
       3.3.5 Packet Id                             25
       3.3.6 Data Size                             25
       3.3.6 Sequence No                           24

                                        iii




!                                         !                         !
!                                         !
CONTENTS
         3.4.1 Priority Queuing                                       26
         3.4.2 Round Robin Queuing                                    26
         3.4.3 Weighted Fair Queuing                                  27
         3.4.4 Leaky Bucket Policer                                   28
         3.4.5 Leaky Bucket Policer + Weighted Fair Queuing           30
         3.4.6 Design decision                                        30
         3.5 AutoConnection                                           31
         3.5.1 Unable to connect to new device without user acknowledgement   31
         3.5.2 Unable to make device always discoverable              31
         3.5.3 Working with paired devices                            32
         3.5.4 Geo-Location Indexing server                           32

    CHAPTER 4        IMPLEMENTATION RESULTS AND PERFORMANCE
    METRICS                                        33
       4.1 Key Features                            33
       4.1.1 No Rooting Required                   33
       4.1.2 Packet Routing                        33
       4.1.3 No need for centralized Index server  33
       4.1.4 Flow Control                          34
       4.1.5 Auto-Connection                       34
       4.1.6 Open-Source                           34
       4.2 Performance Metrics                     35

    CHAPTER 5 FRAMEWORK LIMITATION AND POSSIBLE FUTUREWORK 36
       5.1 Framework Limitations                        36
       5.1.1 Pairing between 2 devices                  36
       5.1.2 Lack of security                           36
       5.1.3 Dependency on Geo-Location Indexing Server 36
       5.2 Future Work                                  37
       5.2.1 Server-less implementaton                  37
       5.2.2 Optimization                               37
       5.2.3 Security                                   37

    CHAPTER 5 SUMMARY AND CONCLUSION                                 38
       6.1 Future of mobile communication                            38
       6.2 Conclusion                                                38

    REFERENCES                                                       39
    APPENDIX I - AIDI File for IConnection                           41
    APPENDIX II - AIDI File for IConnectionCallback                  41
    APPENDIX III - Connection Class                                  41
    APPENDIX IV - ConnectionService Class                            41

                                         iv




!                                         !                                        !
!                                         !
LIST OF FIGURES


    Fig. 1 U.S Smartphone Penetration & Projections   1

    Fig. 2 Mobile P2P Network                         3

    Fig. 3 Maximum Throughput Rate                    7

    Fig. 4 Server-Client                              8

    Fig. 5 Peer-to-Peer                               9

    Fig. 6 Centralized Index                          10

    Fig. 7 Query Flooding                             11

    Fig. 8 Hierarchical Overlay                       12

    Fig. 9 Server Client Vs P2P                       14

    Fig. 10 MDT vs No of Clients                      15

    Fig. 11 Mobile O.S Market Share                   17

    Fig. 12 Bluetooth Logo                            18

    Fig. 13 Power Class chart                         19

    Fig. 14 Version Chart                             19

    Fig. 15 WiFi Logo                                 20

    Fig. 16 802.11 protocol                           20

    Fig. 17 Scatter Net                               23

    Fig. 18 Data Packet Design                        24

    Fig. 19 Priority Design                           26

    Fig. 20 Round Robin Queuing                       27

    Fig. 21 Weight Fair Queuing                       27

    Fig. 22 Leaky Bucket Policer                      28

    Fig. 23 Data Rate                                 29

    Fig. 24 LBP + WFQ                                 29


                                         iii



!                                         !                !
!                                         !
CHAPTER 1

                                      INTRODUCTION

1.1 Background




                    Figure 1: U.S Smartphone Penetration & Projections

In a recent report by Nielsen, smartphone penetration rate in US is predicted to reach over 50%

reaching over 95 millions units in the 2011(Nielsen 2011). A smartphone, is defined here as a

mobile phone “that offers more advanced computing ability and connectivity than a

contemporary feature phone”(Nusca 2009). As seen in Figure 1, the high growth rate of these

devices bring about many opportunities for entrepreneurs and developer to leverage on the extra

computing and communication power of these devices. However, the high growth rate of these

data hungry devices is not without it problems.




!                                                 !                                          !
!                                                 !                                         1
1.2 Problems

The suddenly increase in the demand for mobile data bandwidth brought by these devices took

many mobile network providers by surprise. Many of these network providers relies heavily on

traditional network architectures that are not designed to handles these kinds of traffics

requirements. As network infrastructure expands takes times and also a huge amount of capital

investment, network outrages are common for smartphone users and thus in many ways limiting

the capabilities of these devices.



1.3 Motivation

At such there is a need to redesign the current network architectures to allow for greater network

scalability and more importantly a lower infrastructure cost for each additional devices(clients)

added to the network.



1.4 Objective

The objectives of the projects are therefore to explore and experiment on other means of network

infrastructures suitable for usage on smartphone. The projects aims to provide a prototype open-

source communication framework suitable for usage in the below scenario.




!                                                 !                                            !
!                                                 !                                           2
1.5 Use Cases

Figure 2 shows how the framework can serve as an support to the current mobile communication

architecture. By leveraging on the Peer-to-Peer capability of the framework, the network stress

on the traditional Architecture can be greatly reduced.




                                      Figure 2: Mobile P2P Network

Some of the propose used case for the framework would be:

- Ad-hoc gaming network.

- Instant Messaging Application.

- File sharing.

- Video Streaming.

- Internet Sharing / booster.

- Geo-Location Triangulation.

- Others applications which require data transfer within a network.




!                                                !                                           !
!                                                !                                          3
1.6 Approach

In order to meet the requirements for a network that is scalable and lower on infrastructure cost,

my literature reviews(Chapter 2) points the solution to none other than a Peer-to-Peer approach.

The network communication architecture adopted for this framework is therefore a Peer-to-Peer

one based on a modified Gnutella Peer-to-Peer architecture. Due to the ease of implementation

and also the ability to reach a wider open-source community, the Open-Source Android

Operating System for mobile devices is adopted as the platform for this framework

implementation. Extra efforts were also put in to the architecture design so that it would not

require a “Rooted” android device. By doing so, the author hopes that it would be more

appropriate for mass-market adoptions.



1.7 Assumption and Limitation

Due to the time constraints and also hardware limitations, the framework currently only relies on

bluetooth for it’s Peer-to-Peer communications(Chapter 3). This in turn means that the

framework is currently limited by the hardware capability of of the bluetooth chipsets. At the

time of this writing, majority of the android devices available in the market is still using

Bluetooth 2.1 + EDR, with some newer devices supporting Bluetooth 3.0. At such, testing and

performance benchmarking for this framework is currently done only on Bluetooth 2.1+EDR,

however there should not be any problem using the framework on Bluetooth 3.0 chipset.

The framework should work with Android O.S 2.0 and above and has been tested across Android

2.0/2.1(Eclair), Android 2.2(Froyo) and Android 2.3(GingerBread).

Due to resource limitations, the framework has been tested on the following phones only:

- HTC Magic

- HTC Device Z
!                                                  !                                              !
!                                                  !                                             4
- Samsung Galaxy S

- Nexus One



1.8 Results of Implementation and Experiment

An Open Source Peer-to-Peer framework focusing on Bluetooth Communication has been

implemented on Android O.S.

It comprises of the following Key Features:

- No Rooting Required

The framework does not required developer/users to “root” their android phones in order to use

it’s features. It’s is designed to work off the shelf and integrates easily with other existing

projects. It leverage on the Android Interface Definition Language(AIDL) to provide a clean and

easy to integrate interface for developer to work with.

- Packet Routing

All devices connected to a network clusters double up as router for the network. Once a device

has been connected successfully to a device within a network cluster, it can communicate

directly with any nodes in the network.

- No need for a centralized indexing server

The framework implements a modified “Gnutella” P2P network. This means that the network is

purely decentralized and does not require an indexing server. Through the use of Query Flooding

techniques, similar to that found in classic “Gnutella” P2P network, a device would be able to

communicated with any node within the network.

- Flow Control

As every device double up as a router within the network, it is crucial that flow control is

implemented at each node to ensure a fair usage for each node. A “Fair weighted Queuing”

Traffic policer is currently implemented at each node to ensure Quality of Service(Chapter 3).
!                                                  !                                               !
!                                                  !                                              5
- Auto-Connection

This is an experimental features of the framework. Due to the security limitation(Chapter 3) of

the bluetooth framework on android, where an device cannot be set to be “always discoverable”,

there is no way for a device to detect a nearby device and automatically setup an connection with

it. To overcome this, an indexing server is implemented to allow devices to query for nearby

devices in which they can connect to and form a network. Using geo-location information

coming from the devices, the server would suggest a list of devices in which the device can

connect to. Suggestion are made so that the bluetooth Scatter net topology is maintained.

- Open-Source

This framework is currently developed as open source project. It’s source can be found at http://

code.google.com/p/p2p-communication-framework-for-android/.

Found together with the framework is a multi-user bluetooth Chat application which

demonstrates the Apis capabilities of the framework.

A Peer-to-Peer network mutiplayer game based on the framework developed by the author

together with a good of android enthusiasts can also be found.

- Performance Metrics

According to the experimental measurements obtained from the transferring of multiple Image

files of 350 - 380 kbytes, we observed that the throughput rate stabilizes at around 54Kbits/s for

nodes that are more than 1 jump away from the original node. Figure 3 shows the throughput rate

obtained from readings measured from these experiments.




!                                                !                                              !
!                                                !                                             6
324#565'789)6:8-6$'
               +!"

               *!"

               )!"

               (!"

               '!"
    !"#$%&%'




               &!"

               %!"

               $!"

               #!"

                !"
                     !"   !,'"   #"      #,'"         $"       $,'"        %"   %,'"   &"   &,'"
                                                ()*')+',)-'$)'./%0120)1'



                                      Figure 3: Maximum Throughput Rate



1.9 Thesis Layout

In Chapter 2, a literature review is done to find out the various alternative networking

infrastructure that can be used to address the current problem and also meet the paper’s

objective. In Chapter 3, we would discuss and look into the various approaches and methodology

used in the implementation of this framework. Chapter 4, would than cover the implementations

outcome and benchmark the performance of the framework. Chapter 5 would than discuss the

limitation of the framework and the possible future work that can be done to the framework.

Lastly, the conclusion of the thesis is than presented in Chapter 6.




!                                                          !                                        !
!                                                          !                                       7
CHAPTER 2

                                    LITERATURE REVIEW

2. 1 Server - Client Architecture




                                  Figure 4: Server-Client

Figure 4 shows a classic Server - Client architecture that most Internet Service Provider(ISP)

has their network built on. The client-server model of computing is a distributed application

structure that partitions task or workloads between the providers of resources or service, called

servers, and service requesters, called clients(Microsystem 2009). The clients and servers

typically communicated over a computer network on network hardware infrastructure provided

by ISP. Due to the nature of it’s designs, additional network hardware infrastructures has to be

added in order to support additional capacity(clients).

Advantages

Greater Security assurance:

Since data are stored on the servers, which generally have far greater security controls than most

clients. Server can also have better control access with resources, to guarantee that only those

clients with the appropriate permissions may access and change data.

With data storage being centralized , updates to any data are far easier to administer as compared

to other architecture like Peer-To-Peer one.


!                                                 !                                              !
!                                                 !                                             8
Disadvantages

A major disadvantages of a Server - Client architecture is that it does not scale well when there is

sudden increase in network traffic. Increase in network bandwidth require prior hardware

infrastructure investment, which become a problem when there is a sudden increase in network

bandwidth requirement.

The client-server architecture also lacks robustness as resources are all centralized, should a

critical server fails, all clients in the network will be affected.



2.2 Peer to Peer Architecture




                                         Figure 5: Peer-to-Peer

        A Peer-to-Peer(P2P) computing or networking is a distributed application architecture

that partition tasks or workloads between peers. Peers make a portion of their resources, such as

processing power, disk storage or network bandwidth, directly available to other network


!                                                    !                                             !
!                                                    !                                            9
participants, without the need for central coordination by servers or stable hosts(Scholmeier

2002). The peer-to-peer application structure was popularized by file sharing systems like

Napster and Kazaa. Since it’s induction, many different architectural design from P2P network

has been introduced. They are however generally classified into the below 4 approaches.

2.2.1 Centralized Index




                               Figure 6: Centralized Index



This is the original “Napster” design. The design involved a centralized Index server which

registers all clients in the network and keep and index of their individual resources on the server.

When a clients requires a resource, it will first query the server to get the information regarding

the clients which holds the resource that it requires. The client will than establish an direct

connection to the respective clients to get it’s required resources.


!                                                  !                                                !
!                                                  !                                              10
2.2.2 Query flooding (Gnutella)




                              Figure 7: Query Flooding

Query flooding is a method to search for a resource on a P2P network. By using query flooding,

a P2P network can be fully decentralized with no need for an centralized indexing servers to hold

a list of all clients and resources available in the network. As shown in Figure 7, when a client

requires a resources, it will send a query message to all nodes connected to it. Each node will

than forward the query message to all of it’s neighbors, hence coining the term “Query

Flooding”. QueryHit will than be sent over in the reverse path back to the client. A direct

connection can than be established between the client and the node with the resource required. A

popular Peer-to-Peer network design that employ this search technique to implement a pure Peer-

to-Peer network is the Gnutella Peer-to-Peer network Architecture.

!                                                 !                                             !
!                                                 !                                           11
2.2.3 Hierarchical Overlay




                              Figure 8: Hierarchical Overlay

A Hierarchical Overlay Design is a fusion of the Centralized Index and Query Flooding

Architecture Design. The design recognized that not all nodes within a Peer-to-Peer network are

equal in term of bandwidth, availabilities and computational power. It therefore introduce the

concept of of “super peers” in the network which server as mini-index which keep track of all the

resources of it’s children. Similar Query Flooding concept is than employed at the “super peers”

level when a node in the network query for a resources. The popular Internet Telephony

Application SKYPE is a good example of application that employ the Hierarchical Overlay Peer-

to- peer Design.



!                                                !                                            !
!                                                !                                          12
2.2.4 Distributed Hash Table (DHT)

A distributed hash table is a class of a decentralized distributed system that implements a lookup

service similar to that of a hash table. Key, value pairs are stored in a DHT and any participating

node can efficiently retrieve the value associated with any given key. The responsibility for

maintaining the mapping from keys to values is distributed among all the nodes in the network.

An efficient algorithm is employed such that there would be minimal amount of disruption when

there is a change in the set of participants in the network.



2.2.5 Advantages of Peer-to-Peer Architecture

In Peer-to-Peer network design, clients provide resources which include bandwidth, storage

space and computing power as it join an network. This allow the total capacity of the network to

also increases as an new node arrive in the network. This allows the network to be well adapted

to sudden increase in network bandwidth requirements. There is also little to no additional cost

to support an extra client added to the network.

The distributed nature of Peer-to-Peer network also increases the robustness of network. For pure

Peer-to-Peer network like the Gnutella, Hierarchical Overlay and DHT designs, which enabled

peers to find the require resources without relying on a centralized index server, the network

robustness was very much increase as there is no single point of failure in the architecture.



2.2.6 Disadvantages of Peer-to-Peer Architecture

Due to the nature of the network design , unsecured and unsigned codes may allow unauthorized

remote access to resource on a victims nodes and compromised the entire network.




!                                                  !                                              !
!                                                  !                                            13
2.3 Server-Client Vs Peer-to-Peer

To better evaluate the performance of Server-Client network design versus that of a Peer-to-Peer

network design, let us that a look at a typical network operation: File Distribution (Figure 6)




                              Figure 9: Server Client Vs P2P

Objective:

- Distribute a large file from a single server to a large N number of host(peers). As shown in

    Figure 9.

Server-Client:




                                                                 -- Eq(1)

For a typical server client architecture, the server would need to send N copies of the file.

The slowest client takes at least F/dmin time to download the given file.

Given a network as depicted in Figure 9, Eq(1) show the total time required for the server to

!                                                 !                                               !
!                                                 !                                             14
complete the task of distributing all the files.

Peer-to-Peer:

For a Peer-to-Peer architecture, the server would need to send at least one copy of the file : F/us

The slowest client would take at least F/dmin to download the given file.

The total number of bits that must be downloaded would be NF bits, but the total upload capacity

is now                .

This would means that the minimum time taken for the task of distributing the files would be:


                                                                -- Eq(2)

Therefore, the total time taken for the task of distributing the file in a P2P network would be:


                                                                       -- Eq(3)




                                Figure 10: MDT vs No. Of Clients

Figure 10 shows a comparison of the two methods plotted by Minimum Distribution Time

(MDT) against N(no of clients). As shown in the graph, we can see that the Client-Server
!                                                  !                                            !
!                                                  !                                          15
architecture does not scale well and MTD increase linear as the required no of clients increases.

On the other hand, we can see that Peer-to-Peer architecture scales nicely with the increase in the

no of clients. The MTD tends towards the maximum time of 1 hour, which is the maximum time

taken for the server to upload one file.



2.4 Proposed Architecture

In conclusion, the literature review shows us that a Peer-to-Peer architecture design has

significant advantage in terms of scalability and cost as compared to a traditional client-server

architecture design. This suit our requirement for a new architecture design. At such, the

proposed framework would be based on a Peer-to-Peer that allows developers to build scalable

applications on top of it. In the next chapter, we would discuss in depth the implementation and

its design decision.




!                                                 !                                             !
!                                                 !                                           16
CHAPTER 3

               IMPLEMENTATION APPROACHES AND METHODOLOGY

3.1 Platform




                              Figure 11: Mobile O.S Market Share

Figure 11 shows the US smartphone market shares acquisitions rate for the different smartphone

operating systems in a research done by Nielsen in 2010. As shown in the graph, we can see that

the android platform is fast gain ground in the U.S smartphone market. This is likely due to the

“open” nature of the android platform which attracts both Hardware OEMs and software

developers.

Indeed, the openness of the android framework allows developer to unleash the full potential of a

smartphone which much more ease. At such, the author choose to use the android framework for

the purpose of this research paper due to potential(high market adoption rate) and also for its

ease of implementation.




!                                                !                                             !
!                                                !                                           17
3.2 Hardware choices and limitations

The android platform offers a varieties of ways for devices to communicate between themselves

and with the rest of the world(internet). The fews choices that are available are:

3.2.1 Bluetooth




                                       Figure 12: Bluetooth logo

Bluetooth™ is a proprietary open wireless technology standard for exchanging data over short

distances from fixed and mobile devices. Creating personal area network(PANS) with high levels

of security. It uses a radio communication system and therefore do not requires a visual line of

sight between 2 devices for them communicate.

Bluetooth™ uses a radio technology called frequency-hopping spread spectrum, which chops up

data being sent and transmits chunks of it on up to 79 bands, 1MHz each, centered from 2402 to

2480 MHZ in the range of 2400-2483.5MHZ.

Bluetooth™ is a packet-based protocol with Master-slave structure. One master may

communicate up to 7 slaves in a piconet at the same time, with all the devices sharing the

master’s clock. Packet exchange is based on the basic clock defined by the master which ticks at

312.5 us intervals.

A Bluetooth™ can switch role between a slave and master. This means that a slave device can

become the master at any time. At any given time, data can be transferred between the master

and one other device, however it can rapidly switches between devices in round-robin fashions

with little over head.




!                                                 !                                            !
!                                                 !                                          18
Figure 13: Power Class chart

Three power classes of Bluetooth™ exist in the market to address various use cases. Due to the

limited power available on mobile devices, most if not all android devices operate on Class 2

chipset which limits it range to a 10 meters as shown in Figure 13 above.




                                     Figure 14: Version Chart

Since it’s inception in 1994 by telecom vendor Ericsson(Wikipedia), Bluetooth™ has under went

a couple of revisions recorded in Figure 14. Each revision brings about different improvement in

terms of data transfer rate and also power consumption.



Begin from Android 1.6, the android operating system supports bluetooth 2.0 and above chipset.

The framework provided socket connection similar to that of a TCP socket connection. Most

androids device found in the market comes with bluetooth chipsets 2.0 and above.




!                                               !                                            !
!                                               !                                          19
3.2.2 Wireless Fidelity




                                       Figure 15: WiFi Logo

Wireless Fidelity or Wi-Fi for short is a wireless communication technology developed and

controlled by the IEEE based on the IEEE 802.11 standards. It allowed a Wi-Fi enabled device

such as a personal computer or a mobile phone to communicate with other devices or connect to

the internet. This is usually achieve by having the Wi-Fi device connect to a network through a

access points via a router.

Direct device to device communication is also possible without the involvement of a access

point. This form of Wi-Fi communication is called the ad hoc mode.




                              Figure 16: 802.11 protocol

Since it induction in 1997(Wikipedia), the IEEE 802.11 protocol has under went many revisions

in its protocol to meet the increasing bandwidth and range requirements of communication


!                                               !                                             !
!                                               !                                           20
devices. Figure 16 show the different protocol standards of the IEEE 802.11 and their data

transfer rates.

The Android Operation System supported Wi-Fi connectivity since it’s first release. Most of the

android devices in the market today are still using the IEEE802.11 g protocols. The android

framework does not support ad hoc mode of Wi-Fi communication by default. Developer would

need to “root” their device to enable this feature.



3.2.3 Mobile telecommunication

Mobile telephony or telecommunication is the provision of telephone services to phones which

may move around freely rather than stay fixed in one location. Mobile devices connect to a

terrestrial cellular network of base station(cell towers) which allows them to communicate

between one another or with the rest of the world(internet).

Most of the world mobile telephone system is based on the Global System for Mobile

Communication system, GSM in short.

Beside the GSM, another popular mobile telephone system is based on the Code division

Multiple Access system, CDMA in short.

GSM system uses Time Division Multiple Access TMDA and Frequency Division Multiple

Access FDMA techniques to multiple phones in it’s network to communicate simultaneously

while the CDMA system employ Code Division Multiple Access techniques to achieve similar

goals.

3G or 3rd generation mobile telecommunication is a generation of standards for mobile phones

and mobile telecommunication services fulfilling the International Mobile

Telecommunications-2000 specifications by the International Telecommunication Union(ITU)

(Wikipedia).

As the ITU did not provide a clear definition of the data rate users can expect from 3G
!                                                     !                                        !
!                                                     !                                      21
equipment or providers, the data transfer can varies across different equipments and service

provider. However, a typical 3G cellular network users can expect a minimum data rate of

2Mbit/s for stationary or walking users to 384kbit/s in a moving vehicles according to IMT-2000

specifications(IMT-2000 2000).

Most android power devices in the market comes with 3G data supports. However, they usually

requires users to pay additional monthly fees to enjoy this features. At such, not all android

devices will be able to use this form of communication easily.



3.2.4 Design Decisions

After reviewing the different communication options that the android framework offers, it

become clear that Bluetooth™ and Wi-Fi are more feasible choices as compared to mobile

telecommunication such as 3G due to it’s lower availability and more importantly, it’s lack of

options for direct communication between mobile devices.

However, the android platform currently does not support Wi-Fi ad hoc mode of communication.

In order for developer to leverage on this mode of communicate, it would require him to use a

“rooted” device. At such, the author choose to have the framework focus on bluetooth as the

main form of inter-device communication for it’s first release.




!                                                 !                                                !
!                                                 !                                              22
3.3 Network Design




                              Figure 17: Scatter Net

As discussed previously in 3.1, Bluetooth™ is a packet-based protocol with Master-slave

structure. A Master device can allow up to 7 slave devices to connect to it forming a piconet.

When one or more piconets is bridge by one or more devices in their individual piconet, a Scatter

net is formed. Figure 17 shows a example of 2 piconets forming a Scatter net.

A device in a Peer-to-Peer network usually acquire it’s resource in 2 steps. First, it would need

to find out which are the nodes in the network that contain the resource that it desires. Depending

on the network architectural, this is achieved by either by doing a query with some form of index

server(Central Indexing, DHT, Hierarchical Overlay) or through Query Flooding (Gnutella).

After the required information with regards to the nodes which contain the desired resource has

been acquired, the next time would be establish a direct connection to the respective nodes so

that the actual resource acquisition can begin.

Since Bluetooth™ on android devices has a range limit of up to 10 meters, unlike traditional

!                                                 !                                            !
!                                                 !                                          23
Peer-to-peer network design; a direct connection between any 2 devices in the network might not

be possible. Taking that into account, a little modifications to the traditional Peer-to-Peer

network design have to made.

After the information with regards to the nodes which contains the desired resources has been

obtained, nodes within a bluetooth Peer-to-Peer scatternet/piconet has to assist in routing data

packets between the 2 nodes.

Taking into the account of the framework design objectives of supporting ah-hoc network

creation and the hardware limitation of the Bluetooth™ communication protocol, the author

favored a modified version of the Gnutella Peer-to-Peer design as compared to the other designs

discussed previously.




                               Figure 18 : Data Packet Design

In order to implement a Gnutella Peer-to-Peer network on a Bluetooth™ Scatter net, a 1024 byte

size data packet is used for data transmission between devices on the network. The data packet

uses 60 bytes for header, leaving a dynamic data size of up to 964 bytes. Below is a break down

of each field in the header.

3.3.1 Control Byte

The first byte of the data packet is used to differentiate between a normal data packet and a

control data packets. Control data packets are currently used in the network for query flooding.


!                                                  !                                              !
!                                                  !                                            24
They have higher priority as compared to normal data packets.

3.3.2 Source address

This field contains the 17 characters hardware MAC address of the bluetooth device which the

packets originated from.

3.3.2 Destination address

This field contains the 17 characters hardware MAC address of the bluetooth device which the

packets target at.

3.3.3 Hop Count

This 1 byte contains the no of time the data packet has jumped across nodes in the network. This

is necessary for Query Flooding technique to work in a Gnutella network. Current, the cap is 10

count before the packet is no longer forwarded.

3.3.4 Packet Id

This is a 21 characters string generated by joining the MAC address of the device which generate

the packet with 4 characters string generated from the system clock time. This allows repeated

packets to be recognized and discard at each nodes and thus reducing unnecessary network

traffic and also repeat data at the destination node. The 4 characters string generated only repeats

once every 10 seconds.

3.3.5 Data Size

This 2 bytes field contains the information regarding the size of the data field. This value can

varies from 1 to 964.

3.3.6 Sequence No

This is a 1-byte field that stores that Sequence No of a packet. Since the path taken by each

packets to it’s destination might not be in order, this Sequence No will allow the destination node

to rebuild the data in sequence. This value current varies from 0 - 99.



!                                                 !                                               !
!                                                 !                                             25
3.4 Flow Control

Since packets has to be possibility routed across multiple nodes in the Scatter net before reaching

it’s destination, there is a need to implement some form of schedule system/traffic policing to

ensure a certain level of Quality of Service(QoS). A traditional First-In-First-Out system would

not scale well under high network traffic condition, such as a scenario where by there is a large

file transfer between 2 devices in the network. If a traditional First-In-First-Out system is

adopted. During the entire period of the file transfer operation, other devices in the network

would experience low bandwidth thus affecting QoS. Let us look at some possible schedule

system/traffic policing implementation.



3.4.1 Priority Queuing




                               Figure 19: Priority Queuing

In this approach, packets are classified into different priority classes & placed into different

queues. Figure 19 shows an example implementation of this form of scheduling, The red packets

represented high priority packets and the green packets represented lower priority packets.

Packets of the same priority are served using First-in-first-out scheduling system.




!                                                  !                                                 !
!                                                  !                                               26
3.4.2 Round Robin Queuing




                               Figure 20: Round Robin Queuing

The round robin queuing is a scheduling mechanism that ensure that fair usage of between

different Class(type) of packets. Every queue take turns in getting their data packets processed.

This schedule method can be made work-conserving by never allowing the link to be idle when

there are still packets in any other queue. If a Class queue is empty, any Class queue which is not

empty will immediately be processed. Figure 20 shows a graphic depiction of this method of

scheduling.

3.4.3 Weighted Fair Queuing




                               Figure 21: Weight Fair Queuing

Weighted Fair Queuing is a generalized form of a Round Robin scheduling system. It differs

from a normal round robin scheduling system by allowing each class to have a different

weighted amount of service in a cycle. Similar to a round-robin implementation, the Weighted

Fair Queuing can be made work-conserving by ensuring the link does not become idle when

there are still packets in any other queue.

!                                                !                                             !
!                                                !                                           27
--- Eq(4)

In the worst case, when all Class queue are filled with packets, any even Class i would still be

guaranteed to received bandwidth equal to that of Eq(4).



3.4.4 Leaky Bucket Policer

Unlike a scheduling technique, a policing approach regulate the traffic entering a network

according to declared parameters.

There are commonly three policing criteria:

Average Rate:

This control the network traffic by limiting the Long-term average rate at which packets are

sent.

Peak Rate:

This control the network traffic by limiting the max number of packets allowed to be sent over a

short period of time.

Maximum Burst Size:

This control the network traffic by limiting the max number of packets allowed to be sent over

an extremely short interval of time. This short interval of time is usually treated as instantaneous.




                               Figure 22: Leaky Bucket Policer



!                                                 !                                              !
!                                                 !                                            28
The leaky Bucket Policer technique is a policing technique that employ all the above 3 policing

criteria. Figure 22 shows a graphical description of this policing technique. A “bucket” which

can hold up to b tokens is first created. Tokens are than generated at the rate of r tokens/sec and

adding to the “bucket”. If the bucket is full, newly generated token would be ignored. Before a

packet is sent into the network, it must first remove an available token, when the bucket comes

empty, it would then be not allowed to to sent a packet.

By doing this, the Maximum burst size is b packets and the long-term average rate is r packets/

sec. Eq(5) and Figure 23 shows the maximum number of packets that can enter the network over

any interval of time of length t.



                                                                              --- Eq(5)




                                              Figure 23: Data Rate




!                                                 !                                              !
!                                                 !                                            29
3.4.5 Leaky Bucket Policer + Weighted Fair Queuing

By combining the two techniques, the technique can provides a guaranteed upper bound on delay

and thus provide a QoS guarantee.




                              Figure 24: LBP + WFQ

Suppose flow 1’s bucket is initially full, a burst of b1 packets can pass through & join the

Weighted Fair Queue buffer. Since these packets are served at a rate of at least                ,

the last packet will have a maximum delay of:




                                                           --- Eq(6)

provided that :


                                                      -- Eq(7)



3.4.6 Design decision

Given the time constraints and also to reduce the complexity of the implementation, a Weighted

Fair Queueing scheduling technique is chosen as the flow control mechanism in the framework

implemented.




!                                                 !                                              !
!                                                 !                                            30
3.5 AutoConnections

In order to prevent malicious activities to be perform on a user mobile devices via bluetooth

connectivity, the Android Operating System has put in place many security features to sure that

the end uses will always be keep inform of activities perform via bluetooth. For example, the

system requires user acknowledge when an application tried to turn on bluetooth connectivity or

connect to a device that it has not paired with before.

Although, these security features may have help to increase the security of the android operating

service, it has also hindered the many possible innovations in Peer-to-Peer networking on the

Android Operating System.

The following two security features of the Android Operating System has been the major

hinderer of Peer-to-Peer networking innovations on Android Operating System so far.



3.5.1 Unable to connect to new devices without user acknowledgement

The Android Bluetooth framework also requires 2 devices who have not been previously

connected before to undergo an “pairing” process before data is able to be transmitted between

them. This pairing process require both phone users to acknowledge a prompt from the system

within a short period of time before allowing the 2 devices to be connected. These makes it

extremely difficult for a Peer-to-Peer network to be formed.



3.5.2 Unable to make device always discoverable

The Android Bluetooth framework only allow a device to be “make discoverable” by other

devices for a maximum period of 120 second at any given time. Therefore, the framework

require users acknowledge each time to allow a device to “make discoverable” for another 120

seconds. The inability for an device to “made discoverable” automatically and persistently makes

it hard to implement a peer-to-peer network on the framework as a device would not know who
!                                                 !                                             !
!                                                 !                                           31
to connect to when it first tries to join the network.



3.5.3 Working with paired devices

For simplicity sake, the framework currently does not offer a solution to this. Users currently can

only automatically form a Peer-to-Peer network with devices that it has previous connected.

However, being an “open” operating system, the Android platform has been constantly listening

to feedback from developers and making changes to the framework to meet their needs. In latest

Android release of 2.3.3, the android framework has finally allow unsecured bluetooth

communication to be established between 2 devices who has never been paired before without

user acknowledgement(2.3.3 2010).



3.5.4 Geo-Location Indexing server

To overcome the problem where by a device cannot be set to be always “discoverable” a

centralized index server was developed to index the geo-location coordinate of the all mobile

devices on the network. Before connecting to the Peer-to-Peer network, a device would first

query the centralized indexing server with it’s own Geo-location details to get information

regarding all the devices nearby. The central indexing server is thus responsible for maintain the

bluetooth Scatter net formed by the devices.

This is currently a temporary experimental solutions as the author believe that with open nature

of the framework would see that a alternative would be provided from within the android

framework similar to the modification since previous in Android 2.3.3 release.




!                                                  !                                            !
!                                                  !                                          32
CHAPTER 4

            IMPLEMENTATION RESULTS AND PERFORMANCE METRICS



4.1 Key Features

An Open Source Peer-to-Peer framework focusing on Bluetooth Communication has been

implemented on Android O.S.

It comprises of the following Key Features:

4.1.1 No Rooting Required

Unlike most open source Bluetooth application/framework out there, this framework does not

required developer/users to “root” their android phones in order to use it’s features. It’s is

designed to work off the shelf and integrates easily with other existing projects. It leverage on

the Android Interface Definition Language(AIDL) to provide a clean and easy to integrate

interface for developer work with. The author hope that by doing so, the framework would be

able to have a much larger outreach and would allow it to collect more data from it’s central

indexing server which is used by it’s Auto connect feature.



4.1.2 Packet Routing

All devices connected to a network clusters double up as router for the network. Once a device

has been connected successfully to a device within a network cluster, it can communicate

directly with any nodes in the network. This feature allow ah-hoc network to form manually or

automatically between devices. This feature would enable developer to build many interesting

application should as multi- user chat room and multiplayer games.



4.1.3 No need for centralized indexing server

The framework implements a modified “Gnutella” P2P network. This means that the network is
!                                                  !                                               !
!                                                  !                                             33
purely decentralized and does not require an indexing server. Through the use of Query Flood

techniques, similar to that found in classic “Gnutella” P2P network, a device would be able to

communicated with any node within the network.



4.1.4 Flow Control

As every device double up as a router within the network, it is crucial that flow control is

implemented at each node to ensure a fair usage for each node. A “Fair weighted Queuing”

schedule mechanism is implemented at each node(Chapter 3). This scheduling technique ensure

that control packets has higher priority as compared to normal packet and while ensuring a fair

distribution of the network bandwidth between all the nodes in the network.



4.1.5 Auto-Connection

This is an experimental features of this framework. Due to the security limitation(Chapter 3) of

the bluetooth framework on android, where an device cannot be set to be “always discoverable”,

there is no way for a device to detect a nearby device and automatically setup an connection with

it. To over this, an indexing server is implemented to allow devices to query for nearby devices

in which they can connect to and form a network. Using geo-location information coming from

the devices, the server would suggest a list of devices in which the devices can connect to.

Suggestion are made so that the bluetooth Scatter net topology is maintained.



4.1.6 Open-Source

This framework is currently developed as open source project. It’s source can be found at http://

code.google.com/p/p2p-communication-framework-for-android/.

Found together with the framework is a multi-user bluetooth Chat application which

demonstrates the Apis capabilities of the framework.
!                                                 !                                              !
!                                                 !                                            34
A Peer-to-Peer networking game based on the framework developed by the author together with

a group of android enthusiasts can also be found.



4.2 Performance Metrics

According to the experimental measurements obtained from the transferring of multiple Image

files of 350 - 380 kbytes, we observed that the throughput rate stabilizes at around 54Kbits/s for

nodes that are more than 1 mores away from the original node. Figure 3 shows the throughput

rate obtained from read measure from these experiments.


                                         324#565'789)6:8-6$'
               +!"

               *!"

               )!"

               (!"

               '!"
    !"#$%&%'




               &!"

               %!"

               $!"

               #!"

                !"
                     !"   !,'"      #"     #,'"         $"       $,'"        %"   %,'"   &"   &,'"
                                                  ()*')+',)-'$)'./%0120)1'



                                 Figure 3: Maximum Throughput Rate

This transfer rate is acceptable for most of the uses proposal earlier. We would also like to

highlight that the test is conducted on Nexus one and HTC Desire Z devices which are using

Bluetooth 2.0 chipset. With much high speed of Bluetooth 3.0 chipset(8 times faster than 2.0), it

is believe that the performance of this framework could be much better.




!                                                            !                                         !
!                                                            !                                       35
CHAPTER 5

             FRAMEWORK LIMITATION AND POSSIBLE FUTURE WORK

5.1 Framework Limitations

The first release of the framework aims to show a working prototype of an alternative mobile

communication network based on Peer-to-Peer architectural. However, due to time constraints

and other external/internal factors, the frameworks does has a few limitation. The next few

paragraphs discuss some of them.



5.1.1 Pairing between 2 devices

As of the time of this writing, no android has released an official firmware upgrade which uses

Android 2.3.3. At such, the framework has not been tested with the new unsecured Bluetooth™

connection which allow Bluetooth™ connection between 2 devices which have not been

previously paired. These still remain as the major limitation for the existing framework as it

hinder automatic connection between 2 devices who have not been previously paired.



5.1.2 Lack of security

The current framework implementation did not encrypt the data packets in any way. This would

means that current framework is vulnerable to malicious activities and attacks such as the “man-

in-the-middle” attacks. This made data transfer in the network unsecured and unsuitable for

usage by data which are “confidential” in nature.



5.1.3 Dependency on Geo-Location Indexing server

Due to the Android Bluetooth™ framework security limitation discussed in Chapter 3, the

currently framework is unable to be fully decentralized and require am external indexing server

for it’s Auto connection feature to work. This approach is also affected by hardware limitation
!                                                !                                              !
!                                                !                                            36
both in term of the accuracy of the geo-location chipset and the available of Internet connection

on the device.



5.2 FutureWork

After reviewing the limitation of the current framework, the following future work is suggested

to be done:

5.2.1 Server-less implementation

To allow the Peer-to-Peer network to be truly scalable, it’s dependency on the Geo-Location

indexing server has be to remove. Future work can be done to use Bluetooth scanning instead of

geo-location position to determine which device a device should connect to. This would also be

largely affected by the implementation changes from the Android framework itself.

5.2.2 Optimization

The current Framework adopted a Gnutella Peer-to-Peer architecture large due to it’s simplicity

of implementation. In the next release of the framework, more work can be done to optimize and

improve the efficiency of the Peer-to-Peer framework. More efficient search and routing

technique could be adopted to improve the data transfer speed of the current framework.

5.2.3 Security

As discussed previously in the limitation of the framework, the current framework does not

implement any form of data encryption which cause the underlying network to be be an

unsecured one. This made it a security risk and thus unsuitable for applications which contains

sensitive information to be developed on it. At such, it might be good for the next release to take

this into account and implement some form of data encryption to allow better data security

within the network.




!                                                 !                                            !
!                                                 !                                          37
CHAPTER 6

                               SUMMARY AND CONCLUSION



6.1 Future of mobile communication

As the computation power of mobile devices continue to increase and the cost of these devices

continue to falls, the term “smartphone” would soon become a term of the past. All mobile

devices would soon have the computation power of a laptop or desktop that we are using today.

As the power of these devices increase, the demand for faster data connectivity and higher

bandwidth would definitely continue to increase at an exponential rate. At such there would be a

need for us to reconsider the current network infrastructure design to allow for better scalability.



6.2 Conclusion

In this thesis paper, we had explored the different alternatives communication architectural

design that would allow the current mobile communication to scale better. The prototype

framework that was developed as part of this thesis provided us a platform to evaluate the

feasibility of using Peer-to-Peer communication between mobile devices as an alternative to

traditional mobile communication method.

From the result of the implementation, namely the success demonstrated in the multi-user chat

application and also the multi-player game both implemented using the Peer-to-Peer framework,

we can conclude that a Peer-to-Peer implementation more than exceed our expectation as an

alternative to support or even replace the current mobile communication architecture. With the

increasing adoption rate of the Android platform and also it’s recognition for the potential in

Peer-to-Peer communication (revision 2.3.3), we can concluded that the future for Peer-to-Peer

communication on mobile devices is a bright one. The author hope that the framework developed

in this thesis would provide a start for more innovation in this field.
!                                                  !                                             !
!                                                  !                                           38
REFERENCES

    [1] 2.3.3, A. (2010). "Android 2.3.3."         Retrieved 31 March, 2010, from http://

        developer.android.com/sdk/android-2.3.3.html.

    [2] IMT-2000 (2000).

    [3] Microsystem, S. (2009). "Distributed Application Architecture."   Retrieved 06-16,

        2009, from http://java.sun.com/developer/Books/jdbc/ch07.pdf.

    [4] Nielsen (2011). "US Smartphone Penetration and forecast 2011."

    [5] Nusca, A. (2009). "Smartphone Vs feature phone arms race heats up; which did you

        buy?", from http://www.zdnet.com/blog/gadgetreviews/smartphone-vs-feature-

        phone-arms-race-heats-up-which-did-you-buy/6836.

    [6] Scholmeier, R. (2002). A definition of Peer-to-Peer Networking for the

        Classificiation of Peer-to-Peer Architectures and Applications, Proceedings of the

        First International Conference on Peer-to-Peer Computing. IEEE.

    [7] Wikipedia. "3G." Retrieved 31 march, 2010, from http://en.wikipedia.org/wiki/3G.

    [8] Wikipedia. "Bluetooth."    Retrieved 31 March, 2010, from http://en.wikipedia.org/

        wiki/Bluetooth#cite_note-0.

    [9] Wikipedia. "IEEE 802.11." Retrieved 31 March, 2010, from http://en.wikipedia.org/

        wiki/IEEE_802.11#cite_note-80211timeline-6.

    [10] Broadcast-Based Peer-to-Peer Collaborative Video Streaming Among Mobiles, Man-

        Fung Leung and S-H Gary Chan

    [11] Integrating Bluetooth with Wireless and Ricocheting, David J.Y Lee and William

        C.Y.Lee

    [12] Dynamic Topology Management in Bluetooth Networks, Suresh Srinivasan, Keyur

        Desai, Akash Tilak Choudhari, Dinesh Rajan, South Methodist University, Dallas,

        TX
!                                              !                                          !
!                                              !                                        39
[13] Always Best Connected, EVA GUSTAFSSON AND ANNIKA JONSSON,

        ERICSSON RESEARCH

    [14] MobiClique: Middleware for Mobile Social Networking, Anna-Kaisa Pietillainen

        (Thomson), Earl Oliver(University of waterloo), Jason LeBrun(University of

        California, Davis), George Varghese(University of California, San Diego) and

        Christophe Diot(Thomson)




!                                           !                                        !
!                                           !                                      40
!        !      !      !       !       !       !       !     !      !  APPENDIX I
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * AIDL for the Bluetooth Connect, Link, Compete Service
 * IConnection.java is autogenerated from this
 */

package net.clc.bt;

// TODO: Ideally, we would import BluetoothDevice here
// and use that instead of just a String in the connect
// method for better type safety, but this is currently
// not possible yet.

import net.clc.bt.IConnectionCallback;

// Declare the interface.
interface IConnection {
  String getAddress();
  Map getDevices();
  String getName();
  int startServer(in String srcApp, in int maxConnections,in boolean AutoConnect);
  int connect(in String srcApp, in String device);
  int sendMessage(in String srcApp, in String device, in byte[] message);
  int broadcastMessage(in String srcApp,in String destination, in byte[] message);
  String getConnections(in String srcApp);
  int getVersion();
  int registerCallback(in String srcApp, IConnectionCallback cb);
  int unregisterCallback(in String srcApp);
  void shutdown(in String srcApp);
}


!                                               !                                      !
!                                               !                                    41
APPENDIX II
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * AIDL for the Bluetooth Connect, Link, Compete Service
 * IConnectionCallback.java is autogenerated from this
 */

package net.clc.bt;

// Declare the interface.
oneway interface IConnectionCallback {
  void incomingConnection(String device);
  void maxConnectionsReached();
  void messageReceived(String device, in byte[] message);
  void connectionLost(String device);
}




!                                              !                           !
!                                              !                         42
APPENDIX III
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.clc.bt;

import java.util.List;
import java.util.Map;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

/**
 * API for the Bluetooth Click, Link, Compete library. This library simplifies
 * the process of establishing Bluetooth connections and sending data in a way
 * that is geared towards multi-player games.
 */

public class Connection {
  public static final String TAG = "net.clc.bt.Connection";

    public static final int SUCCESS = 0;

    public static final int FAILURE = 1;

    public static final int MAX_SUPPORTED = 7;

    public interface OnConnectionServiceReadyListener {
      public void OnConnectionServiceReady();

!                                               !                                          !
!                                               !                                        43
}

    public interface OnIncomingConnectionListener {
      public void OnIncomingConnection(String device);
    }

    public interface OnMaxConnectionsReachedListener {
      public void OnMaxConnectionsReached();
    }

    public interface OnMessageReceivedListener {
      public void OnMessageReceived(String device, byte[] message);
    }

    public interface OnConnectionLostListener {
      public void OnConnectionLost(String device);
    }

    private OnConnectionServiceReadyListener mOnConnectionServiceReadyListener;

    private OnIncomingConnectionListener mOnIncomingConnectionListener;

    private OnMaxConnectionsReachedListener mOnMaxConnectionsReachedListener;

    private OnMessageReceivedListener mOnMessageReceivedListener;

    private OnConnectionLostListener mOnConnectionLostListener;

    private ServiceConnection mServiceConnection;

    private Context mContext;

    private String mPackageName = "";

    private boolean mStarted = false;

    private final Object mStartLock = new Object();

    private IConnection mIconnection;

    private IConnectionCallback mIccb = new IConnectionCallback.Stub() {
       @Override
                public void incomingConnection(String device) throws RemoteException {
         if (mOnIncomingConnectionListener != null) {
            mOnIncomingConnectionListener.OnIncomingConnection(device);
         }
       }

!                                               !                                          !
!                                               !                                        44
@Override
               public void connectionLost(String device) throws RemoteException {
        if (mOnConnectionLostListener != null) {
           mOnConnectionLostListener.OnConnectionLost(device);
        }
      }

      @Override
               public void maxConnectionsReached() throws RemoteException {
        if (mOnMaxConnectionsReachedListener != null) {
           mOnMaxConnectionsReachedListener.OnMaxConnectionsReached();
        }
      }

     @Override
              public void messageReceived(String device, byte[] message) throws
RemoteException {
       if (mOnMessageReceivedListener != null) {
          mOnMessageReceivedListener.OnMessageReceived(device, message);
       }
     }
  };

    // TODO: Add a check to autodownload this service from Market if the user
    // does not have it already.
    public Connection(Context ctx, OnConnectionServiceReadyListener ocsrListener) {
       mOnConnectionServiceReadyListener = ocsrListener;
       mContext = ctx;
       mPackageName = ctx.getPackageName();
       mServiceConnection = new ServiceConnection() {
         @Override
                          public void onServiceConnected(ComponentName name, IBinder service)
{
            synchronized (mStartLock) {
              mIconnection = IConnection.Stub.asInterface(service);
              mStarted = true;
              if (mOnConnectionServiceReadyListener != null) {
                 mOnConnectionServiceReadyListener.OnConnectionServiceReady();
              }
            }
        }

        @Override
                       public void onServiceDisconnected(ComponentName name) {
            synchronized (mStartLock) {
              try {

!                                              !                                         !
!                                              !                                       45
mStarted = false;
                        mIconnection.unregisterCallback(mPackageName);
                        mIconnection.shutdown(mPackageName);
                     } catch (RemoteException e) {
                        Log.e(TAG, "RemoteException in onServiceDisconnected", e);
                     }
                     mIconnection = null;
                 }
             }
        };

        Intent intent = new Intent("com.google.intent.action.BT_ClickLinkCompete_SERVICE");
        intent.addCategory("com.google.intent.category.BT_ClickLinkCompete");
        mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);

    }

  public int startServer(final int maxConnections, OnIncomingConnectionListener oicListener,
       OnMaxConnectionsReachedListener omcrListener, OnMessageReceivedListener
omrListener,
       OnConnectionLostListener oclListener, boolean AutoConnect) {
    if (!mStarted) {
       return Connection.FAILURE;
    }
    if (maxConnections > MAX_SUPPORTED) {
       Log.e(TAG, "The maximum number of allowed connections is " + MAX_SUPPORTED);
       return Connection.FAILURE;
    }
    mOnIncomingConnectionListener = oicListener;
    mOnMaxConnectionsReachedListener = omcrListener;
    mOnMessageReceivedListener = omrListener;
    mOnConnectionLostListener = oclListener;
    try {
       int result = mIconnection.startServer(mPackageName, maxConnections, AutoConnect);
       mIconnection.registerCallback(mPackageName, mIccb);
       return result;
    } catch (RemoteException e) {
       Log.e(TAG, "RemoteException in startServer", e);
    }
    return Connection.FAILURE;
  }

   public int connect(String device, OnMessageReceivedListener omrListener,
        OnConnectionLostListener oclListener) {
//    if (!mStarted) {
//       return Connection.FAILURE;
//    }

!                                                     !                                  !
!                                                     !                                46
mOnMessageReceivedListener = omrListener;
        mOnConnectionLostListener = oclListener;
        try {
           int result = mIconnection.connect(mPackageName, device);
           mIconnection.registerCallback(mPackageName, mIccb);
           return result;
        } catch (RemoteException e) {
           Log.e(TAG, "RemoteException in connect", e);
        }
        Log.e(TAG, "Return failure here");
        return Connection.FAILURE;
    }

    public int sendMessage(String device, byte[] message) {
      if (!mStarted) {
         return Connection.FAILURE;
      }
      try {
         return mIconnection.sendMessage(mPackageName, device, message);
      } catch (RemoteException e) {
         Log.e(TAG, "RemoteException in sendMessage", e);
      }
      return Connection.FAILURE;
    }

    public int broadcastMessage(byte[] message,String destination) {
      if (!mStarted) {
         return Connection.FAILURE;
      }
      try {
         return mIconnection.broadcastMessage(mPackageName,destination, message);
      } catch (RemoteException e) {
         Log.e(TAG, "RemoteException in broadcastMessage", e);
      }
      return Connection.FAILURE;
    }

    public String getConnections() {
      if (!mStarted) {
         return "";
      }
      try {
         return mIconnection.getConnections(mPackageName);
      } catch (RemoteException e) {
         Log.e(TAG, "RemoteException in getConnections", e);
      }
      return "";

!                                                !                                    !
!                                                !                                  47
}

    public int getVersion() {
      if (!mStarted) {
         return Connection.FAILURE;
      }
      try {
         return mIconnection.getVersion();
      } catch (RemoteException e) {
         Log.e(TAG, "RemoteException in getVersion", e);
      }
      return Connection.FAILURE;
    }

    public String getAddress() {
      if (!mStarted) {
         return "";
      }
      try {
         return mIconnection.getAddress();
      } catch (RemoteException e) {
         Log.e(TAG, "RemoteException in getAddress", e);
      }
      return "";
    }

    public Map getDevices(){
               try{
                       return mIconnection.getDevices();
               } catch(RemoteException e){
                       Log.e(TAG,"Remote Exception in getDevice",e);
               }
               return null;
    }

    public String getName() {
      if (!mStarted) {
         return "";
      }
      try {
         return mIconnection.getName();
      } catch (RemoteException e) {
         Log.e(TAG, "RemoteException in getVersion", e);
      }
      return "";
    }


!                                              !                         !
!                                              !                       48
public void shutdown() {
      try {
         mStarted = false;
         if (mIconnection != null) {
            mIconnection.shutdown(mPackageName);
         }
         mContext.unbindService(mServiceConnection);
      } catch (RemoteException e) {
         Log.e(TAG, "RemoteException in shutdown", e);
      }
    }

}




!                                             !            !
!                                             !          49
APPENDIX IV
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.clc.bt;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.location.Location;

!                                              !                                  !
!                                              !                                50
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

import com.example.Geoscribe.UseGPS;
import com.example.Geoscribe.comms.GeoscribeComms2;
import com.webservice.objects.RegisterDeviceResult;

/**
 * Service for simplifying the process of establishing Bluetooth connections and
 * sending data in a way that is geared towards multi-player games.
 */

public class ConnectionService extends Service {
        public static final boolean T = true;

         public static final boolean D = false;

    public static final String TAG = "net.clc.bt.ConnectionService";

    public static final String NEW_NETWORK_DEVICE_FOUND = TAG+"DEVICEFOUND";

    public static final String DEVICE_ADDR = TAG+"DEVICEADDRESS";

    public static final String DEVICE_NAME = TAG+"DEVICENAME";

    static final int bufferSize = 1024;

    private ArrayList<UUID> mUuid;

    private ConnectionService mSelf;

         private Context mContext;

    private String mApp; // Assume only one app can use this at a time; may

    // change this later

    private IConnectionCallback mCallback;

    private ArrayList<String> mBtDeviceAddresses;

    private HashMap<String,String> networkDevices;


!                                                 !                                  !
!                                                 !                                51
private HashMap<String, BluetoothSocket> mBtSockets;

    private HashMap<String, Thread> mBtStreamWatcherThreads;

    private HashMap<String, Long> packetWatcher;

    private HashMap<String, Byte> seqNoWatcher;

    private HashMap<String, Byte> recievedSeqNoWatcher;

    private Object seqNoWatcherLock;

    private Object recievedSeqNoWatcherLock;

    private Object mBtLock;

    private BluetoothAdapter mBtAdapter;

    private String mDeviceAddress;

    private String mDeviceName;

    private Runtime r;

    private Location mGeoCoordinate;

    private String mMasterDevice="";

    private boolean mAutoConnect = false;

    private boolean recoveryMode = false;

    private ArrayList<String> recoveryDevicesList;

    private GeoscribeComms2 webService;

    final Handler mHandler = new Handler(){


                /* (non-Javadoc)
                 * @see android.os.Handler#handleMessage(android.os.Message)
                 */
                @Override
                public void handleMessage(Message msg) {
                        // TODO Auto-generated method stub
                        //super.handleMessage(msg);
                        String message = msg.obj.toString();

!                                               !                                !
!                                               !                              52
Toast.makeText(mSelf, message, 1).show();
                }


    };

    //private final BlockingQueue<DataStream> packetQueue;

    public static final byte[] shortToByteArray(short value) {

         if (value < 0) return new byte[]{0,0};

                return new byte[] {
           (byte)(value >>> 8),
           (byte)value};
    }

    public static final short byteArrayToShort(byte [] b) {
      return (short)(((b[0] & 0xFF) << 8)
            + (b[1] & 0xFF));
    }

    public static DataPacket decrypt(byte[] buffer){
                   DataPacket pkt = new DataPacket();
                   pkt.Ctr = buffer[0];
                   pkt.Src = new String(buffer,1,17);
                   pkt.Dest = new String(buffer,18,17);
                   pkt.PktId = new String(buffer,35,21);
                   pkt.HopCount = buffer[56];
                   byte[] dataSize = new byte[]{buffer[57],buffer[58]};
                   pkt.dataSize = byteArrayToShort(dataSize);
                   pkt.SeqNo = buffer[59];
                   pkt.data = new byte[pkt.dataSize];

                    for(int i = 0; i<pkt.dataSize;i++){
                             pkt.data[i] = buffer[i+60];
                    }

                    dataSize = null;
                    buffer = null;

                    return pkt;
    }

    /* (non-Javadoc)
          * @see android.app.Service#onCreate()

!                                                     !                     !
!                                                     !                   53
*/
          @Override
          public void onCreate() {
                  // TODO Auto-generated method stub
                  super.onCreate();
                  mContext = this;
          }

          public static byte[] encrypt(DataPacket pkt){

                 byte header[] = new byte[1];
          header[0] = pkt.Ctr;
          byte packetAsBytes[] = joinByteArray(header,pkt.Src.getBytes());

          packetAsBytes = joinByteArray(packetAsBytes,pkt.Dest.getBytes());

          packetAsBytes = joinByteArray(packetAsBytes,pkt.PktId.getBytes());
          byte hop[] = new byte[1];
          //hop[0] = (byte) (pkt.HopCount+1);
          hop[0] = pkt.HopCount;
          packetAsBytes = joinByteArray(packetAsBytes,hop);

          packetAsBytes = joinByteArray(packetAsBytes,shortToByteArray(pkt.dataSize));

          byte seq[] = new byte[1];
          seq[0] = pkt.SeqNo;
          packetAsBytes = joinByteArray(packetAsBytes,seq);

          packetAsBytes = joinByteArray(packetAsBytes,pkt.data);
//        //add a stop
//        packetAsBytes = joinByteArray(packetAsBytes," ".getBytes());
//        packetAsBytes[packetAsBytes.length-1] = 0;

          header = null;
          hop = null;
          seq = null;
          pkt = null;

                 return packetAsBytes;
     }


     public static byte[] joinByteArray(byte[] a, byte[] b){

                 int count = a.length + b.length;
                 byte[] result = new byte[count];
                 for(int i =0; i<a.length; i++){

!                                                   !                                      !
!                                                   !                                    54
result[i] = a[i];
                }
                for(int i =0; i<b.length; i++){
                         result[a.length+i] = b[i];
                }

                return result;
    }

    public static String generatePacketId(String mDeviceAddress){

                String id = Integer.toString( (int)(Calendar.getInstance().getTimeInMillis()
%(10*1000)));

                int length = id.length();
                if(length<0) length = 0;
                for(int i = length; i<4;i++){
                         id = "0"+id;
                }

                return mDeviceAddress+id;
    }

    public synchronized boolean isPacketRepeated(DataPacket pkt){
      for ( Iterator<Long> iter = packetWatcher.values().iterator(); iter.hasNext(); ){
                  Long time = iter.next();
                  if ( (Calendar.getInstance().getTimeInMillis() - time )> 1000){
                          // remove from any state with a space in its long name.
                          iter.remove();// avoids ConcurrentModificationException
         }
                  //Log.e(TAG,""+time);
      }

        //Clean up memory
                  r.gc();

                if(packetWatcher.containsKey(pkt.PktId)){
                       return true;
                }
                else{
                       packetWatcher.put(pkt.PktId, Calendar.getInstance().getTimeInMillis());
                       return false;
                }
    }

    public ConnectionService() {
      mSelf = this;

!                                                     !                                          !
!                                                     !                                        55
mBtAdapter = BluetoothAdapter.getDefaultAdapter();
        mDeviceAddress = mBtAdapter.getAddress();
        mDeviceName = mBtAdapter.getName();
        mApp = "";
        mBtSockets = new HashMap<String, BluetoothSocket>();
        mBtDeviceAddresses = new ArrayList<String>();
        mBtStreamWatcherThreads = new HashMap<String, Thread>();
        packetWatcher = new HashMap<String,Long>();
        seqNoWatcher = new HashMap<String,Byte>();
        recievedSeqNoWatcher = new HashMap<String,Byte>();
        recievedSeqNoWatcherLock = new Object();
        seqNoWatcherLock = new Object();
        mBtLock = new Object();

        webService = new GeoscribeComms2();




        //packetQueue = new LinkedBlockingQueue<DataStream>();

        r = Runtime.getRuntime();
        if (T) Log.e(TAG, "Total Memory at Creation: "+r.totalMemory());
        if (T) Log.e(TAG, "Free Memory at Creation: "+r.freeMemory());

        mUuid = new ArrayList<UUID>();
        // Allow up to 7 devices to connect to the server
        mUuid.add(UUID.fromString("a60f35f0-b93a-11de-8a39-08002009c666"));
        mUuid.add(UUID.fromString("503c7430-bc23-11de-8a39-0800200c9a66"));
        mUuid.add(UUID.fromString("503c7431-bc23-11de-8a39-0800200c9a66"));
        mUuid.add(UUID.fromString("503c7432-bc23-11de-8a39-0800200c9a66"));
        mUuid.add(UUID.fromString("503c7433-bc23-11de-8a39-0800200c9a66"));
        mUuid.add(UUID.fromString("503c7434-bc23-11de-8a39-0800200c9a66"));
        mUuid.add(UUID.fromString("503c7435-bc23-11de-8a39-0800200c9a66"));
    }

    @Override
    public IBinder onBind(Intent arg0) {
      return mBinder;
    }

    private class BtStreamWatcher implements Runnable {
       private String address;
       private final PriorityBlockingQueue pktQueue;
       private Thread pktRouter;

        public BtStreamWatcher(String deviceAddress) {
          address = deviceAddress;

!                                                !                              !
!                                                !                            56
pktQueue = new PriorityBlockingQueue();
         pktRouter = new Thread(new PacketRouter(pktQueue));
         pktRouter.start();
     }

    @Override
      public void run() {
         //byte[] buffer = new byte[DataPacket.HEADER_SIZE];
               BluetoothSocket bSock;
               synchronized(mBtLock){
                      bSock = mBtSockets.get(address);
               }
         try {
            InputStream instream = new BufferedInputStream(bSock.getInputStream());
            int bytesRead = -1;

             while (true) {
//                      DataStream dataStream = new DataStream();
                        byte[] dataBuffer = new byte[DataPacket.PACKET_SIZE];
                bytesRead = instream.read(dataBuffer,0,DataPacket.HEADER_SIZE);
                if (bytesRead != -1) {
                                //ensure HEADERSIDE Byte is read.
                                if (T) Log.e(TAG,"HeaderbyteRead:"+bytesRead);
                                int bytesRead2 = bytesRead;
                                int bufferSize = DataPacket.HEADER_SIZE;
                                while(bytesRead2 != bufferSize){
                                        bufferSize = bufferSize - bytesRead2;
                                        bytesRead2 = instream.read
(dataBuffer,bytesRead,bufferSize);
                                        bytesRead = bytesRead+bytesRead2;
                                }

                              byte[] temp = new byte[]{dataBuffer[57],dataBuffer[58]};
                              short dataSize = byteArrayToShort(temp);
                              if (T) Log.e(TAG,"decoded DataSize:"+dataSize);

                              //THIS IS A HACK????

                              if(dataSize > DataPacket.DATA_MAX_SIZE || dataSize <0){
                                      dataSize = DataPacket.DATA_MAX_SIZE;
                                      Log.e(TAG,"ERROR DATASIZE!!!! :"+dataSize);
                              }


                              if(dataSize>0){



!                                               !                                          !
!                                               !                                        57
bytesRead = instream.read
(dataBuffer,DataPacket.HEADER_SIZE,dataSize);
                                 if (bytesRead != -1) {
                                         if (T) Log.e(TAG,"DatabyteRead:"+bytesRead);
                                         bytesRead2 = bytesRead;
                                         bufferSize = dataSize;
                                         while(bytesRead2 != bufferSize){
                                                 bufferSize = bufferSize - bytesRead2;
                                                 bytesRead2 = instream.read
(dataBuffer,DataPacket.HEADER_SIZE+bytesRead,bufferSize);
                                                 if(T) Log.e(TAG,"insufficient bytes,
reading:"+bytesRead2);
                                                 bytesRead = bytesRead+bytesRead2;
                                         }
                                 }

                                     if(dataBuffer[0] != 1){
                                             DataStream dataStream = new DataStream
(address,dataBuffer);

                                             pktQueue.put(dataStream);

                                             dataStream = null;
                                     }
                                     else{
                                             DataStream dataStream = new DataStream
(address,dataBuffer,0);

                                             pktQueue.put(dataStream);

                                             dataStream = null;
                                     }

                               }
                }

                     //Clean up
                dataBuffer = null;
                     r.gc();

              }
           } catch (IOException e) {
              Log.i(TAG,
                   "IOException in BtStreamWatcher - probably caused by normal
disconnection",
                   e);
           }

!                                              !                                        !
!                                              !                                      58
// Getting out of the while loop means the connection is dead.
         try {
                      synchronized(mBtLock){
                    mBtDeviceAddresses.remove(address);
                    mBtSockets.remove(address);
                    mBtStreamWatcherThreads.remove(address);
                      }
            synchronized (recievedSeqNoWatcherLock){
                             recievedSeqNoWatcher.remove(address);
            }

           synchronized (seqNoWatcherLock){
                          seqNoWatcher.remove(address);
           }

             //to do inform other in network of connection lost
                            DataPacket packet = new DataPacket();
                            packet.Dest = mDeviceAddress;
                            packet.Src = mDeviceAddress;
                            packet.Ctr = 3;
                            packet.SeqNo = 125;
                            packet.PktId = generatePacketId(mDeviceAddress);

                           packet.data = address.getBytes();
                           packet.dataSize = (short) packet.data.length;

                           //get Current network device List
                           //reseting
                           networkDevices = new HashMap<String,String>();

                           DataPacket queryPacket = new DataPacket();
                           queryPacket.Dest = mDeviceAddress;
                           queryPacket.Src = mDeviceAddress;
                           queryPacket.Ctr = 1;
                           queryPacket.SeqNo = 125;
                           queryPacket.PktId = generatePacketId
(mDeviceAddress);

                           synchronized(mBtLock){
                                  for(int i=0; i< mBtDeviceAddresses.size(); i++){
                                           sendPkt(packet,mBtDeviceAddresses.get(i));
                                           sendPkt(queryPacket,mBtDeviceAddresses.get(i));
                                  }
                           }

                           //inform webservice
                           String results[] = webService.deviceConnectionLost(address);

!                                             !                                         !
!                                             !                                       59
if(mMasterDevice.compareTo(address)==0){
                                     mMasterDevice = "";
                                     recoveryMode = true;
                                     recoveryDevicesList = new ArrayList(Arrays.asList
(results));
                               }


                 mCallback.connectionLost(address);
              } catch (RemoteException e) {
                 Log.e(TAG, "RemoteException in BtStreamWatcher while disconnecting", e);
              }
         }

              public int sendPkt(DataPacket pkt,String target)
     throws RemoteException {

                               try {
                                      String destination = target;
                                      BluetoothSocket myBsock;
                                      synchronized(mBtLock){
                                              myBsock = mBtSockets.get(destination);
                                      }
                             if (myBsock != null) {
                                OutputStream outStream = myBsock.getOutputStream();

                               //pkt.HopCount = (byte) (pkt.HopCount+1);

                               byte[] packetAsBytes = encrypt(pkt);

                         outStream.write(packetAsBytes);
                         if (T) Log.e(TAG,"sendPkt To:"+target+" Ctr:"+pkt.Ctr+" Src:"
                                        +pkt.Src+" Dest:"+pkt.Dest+"
HopCount:"+pkt.HopCount+" ID:"+pkt.PktId);

                             }
                             else{
                                       return Connection.FAILURE;
                              }
                           } catch (IOException e) {
                              Log.i(TAG, "IOException in Forwarding packets",
                                   e);
                           }

                     return Connection.SUCCESS;
                 }

!                                                 !                                        !
!                                                 !                                      60
}

    private class PacketRouter implements Runnable{
                 private final BlockingQueue pktQueue;

        private ArrayList<DataPacket> queue;

        private   Comparator<DataPacket> comperator = new Comparator<DataPacket>(){
                       @Override
                       public int compare(DataPacket object1, DataPacket object2) {
                               // TODO Auto-generated method stub
                               if(object1.SeqNo == object2.SeqNo){
                                        return 0;
                               }
                               else if((object1.SeqNo - object2.SeqNo) <0){
                                        return -1;
                               }
                               else{
                                        return 1;
                               }
                       }

                  };


                  PacketRouter(BlockingQueue q){
                         pktQueue = q;
                         queue = new ArrayList<DataPacket>();
                  }

                  /* (non-Javadoc)
                   * @see java.lang.Runnable#run()
                   */
                  @Override
                  public void run() {
                          // TODO Auto-generated method stub
                          while(true){
                                  try {
                                        DataStream dataStream = (DataStream) pktQueue.take();

                                       if (T) Log.e(TAG,"Read one
dataStream :"+dataStream.seqNum);

                                       DataPacket pkt = new DataPacket();

!                                                !                                         !
!                                                !                                       61
pkt = decrypt(dataStream.data);

                                       routePacket(pkt,dataStream.address);

                                } catch (InterruptedException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                } catch (RemoteException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                }

                      }

               }

            private void routePacket(DataPacket pkt, String address) throws
RemoteException {
                    if(!isPacketRepeated(pkt)){
                             if (T) Log.e(TAG,"ACCEPTED From:"+address+" Ctr:"+pkt.Ctr
+" Src:"
                                            +pkt.Src+" Dest:"+pkt.Dest+"
HC:"+pkt.HopCount+" ID:"+pkt.PktId+" Size:"+pkt.dataSize+" SN:"+pkt.SeqNo);


                          byte request = 1;
                          byte reply = 2;
                          byte connectionLost = 3;

                          if(mDeviceAddress.compareTo(pkt.Dest) ==0){
                                if (T) Log.e(TAG,"Packet reach Dest!");

                                        if(pkt.Ctr==reply){
                                                if (T) Log.e(TAG,"Control packet Received!");

                                               if(!networkDevices.containsKey(pkt.Src)){
                                                       if (T) Log.e(TAG,"Found
device:"+pkt.Src);
                                                         String name = new String(pkt.data,
0,pkt.data.length);
                                          networkDevices.put(pkt.Src, name);
                                          Intent i = new Intent
(ConnectionService.NEW_NETWORK_DEVICE_FOUND);
                                          i.putExtra
(ConnectionService.DEVICE_ADDR, pkt.Src);


!                                                    !                                          !
!                                                    !                                        62
i.putExtra
(ConnectionService.DEVICE_NAME, name);
                                                     Log.e(TAG,"SendBroadCast");
                                                     sendBroadcast(i);
                                             }


                                     }
                                     else{
                                             byte missingPkt;
                                             synchronized (recievedSeqNoWatcherLock){
                                                    if(recievedSeqNoWatcher.containsKey
(pkt.Src)){
                                                             missingPkt =
recievedSeqNoWatcher.get(pkt.Src);
                                                     }
                                                     else{
                                                             missingPkt = 0;
                                                             recievedSeqNoWatcher.put(pkt.Src,
missingPkt);
                                                     }
                                             }


                                     if(pkt.SeqNo != missingPkt){
                                             Log.e(TAG,pkt.Src+": "+missingPkt+"
MISSING!, adding"+pkt.SeqNo);
                                             queue.add(pkt);
                                             Collections.sort(queue,comperator);
                                     }
                                     else{
                                             Log.e(TAG,pkt.Src+": "+missingPkt+" Found!");
                                             mCallback.messageReceived(pkt.Src, pkt.data);

                                             missingPkt++;
                                             if(missingPkt>100){
                                                     missingPkt = 0;
                                             }

                                             synchronized (recievedSeqNoWatcherLock){
                                                    recievedSeqNoWatcher.remove(pkt.Src);
                                                    recievedSeqNoWatcher.put(pkt.Src,
missingPkt);
                                             }

                                             int index = queue.size();


!                                                !                                        !
!                                                !                                      63
for(int i = 0; i<queue.size();i++){
                                       if(queue.get(i).SeqNo == missingPkt){
                                               index =i;
                                       }
                              }
                              //if not found index = queue.size;

                              while(true){
                                      if(index == queue.size()){ //missing pkt not
found
                                             break;
                                      }
                                      Log.e(TAG,pkt.Src+": "+missingPkt+"
Release Found!");
                                      missingPkt = (byte) (queue.get
(index).SeqNo+1);
                                      if(missingPkt>100){
                                              missingPkt = 0;
                                      }

                                      synchronized
(recievedSeqNoWatcherLock){
                                             recievedSeqNoWatcher.remove
(pkt.Src);
                                             recievedSeqNoWatcher.put(pkt.Src,
missingPkt);
                                      }


                                      DataPacket temp = queue.remove(index);

                                      mCallback.messageReceived
(temp.Src,temp.data);

                                      index = queue.size();
                                      for(int i = 0; i<queue.size();i++){
                                               if(queue.get(i).SeqNo ==
missingPkt){
                                                      index =i;
                                             }
                                      }


                              }


!                                 !                                           !
!                                 !                                         64
}
                                     }
                            }
                            else{

                                    if(pkt.Ctr==request || pkt.Ctr == connectionLost){

                                            if (T) Log.e(TAG,"Control packet
Received!,"+pkt.Ctr);
                                            DataPacket packet = new DataPacket
();

                                            if(pkt.Ctr == request){
                                                    //Send message to dest.
                                                    packet.Dest = pkt.Dest;
                                                    packet.Src = mDeviceAddress;
                                                    packet.PktId = generatePacketId
(mDeviceAddress);
                                                    packet.Ctr = reply;
                                                    packet.dataSize = (short)
mDeviceName.length();
                                                    packet.data = mDeviceName.getBytes();
                                                    packet.HopCount = pkt.HopCount;

                                                    boolean contains;

                                                    synchronized (mBtLock){
                                                           contains =
mBtDeviceAddresses.contains(packet.Dest);
                                                    }

                                                    if(contains){
                                                            if (T) Log.e(TAG,"Reply
connected");
                                                            sendPkt(packet,packet.Dest);
                                                    }
                                                    else{
                                                            if (T) Log.e(TAG,"Reply to
Source!");
                                                    sendPkt(packet,address);

                                                    }

                                            }
                                            else{
                                                    String deviceLost =new String(pkt.data,
0,pkt.dataSize);

!                                              !                                             !
!                                              !                                           65
//no need to check for mMasterDevice lost.

                                                  mCallback.connectionLost(deviceLost);

                                                  synchronized (recievedSeqNoWatcherLock)
{
                                                         if
(recievedSeqNoWatcher.containsKey(deviceLost)){

       recievedSeqNoWatcher.remove(deviceLost);
                                                         }
                                                  }

                                                  synchronized (seqNoWatcherLock){
                                                         if(seqNoWatcher.containsKey
(deviceLost)){
                                                                seqNoWatcher.remove
(deviceLost);
                                                         }
                                                  }

                                          }

                                          synchronized (mBtLock){
                                                 if (T) Log.e(TAG,"mBtDeviceAddress
size:"+mBtDeviceAddresses.size());
                                                  if (T) Log.e(TAG,"mBtDeviceAddress
Addr:"+mBtDeviceAddresses.get(0));
                                              if (T) Log.e(TAG,"mBtDeviceAddress
Addr:"+mBtDeviceAddresses.get(0).compareTo(address));
                                              if (T) Log.e(TAG,"mBtDeviceAddress
Addr:"+mBtDeviceAddresses.get(0).compareTo(pkt.Dest));
                                              //forward to all peers other than the one who
u just replied to.
                                              for (int i = 0; i < mBtDeviceAddresses.size
(); i++) {
                                                       if(mBtDeviceAddresses.get
(i).compareTo(address) != 0 &&
                                                         mBtDeviceAddresses.get
(i).compareTo(pkt.Dest) != 0){
                                                                //nodes that u have not
replied to
                                                                if (T) Log.e
(TAG,"Forwarding to Peer:");
                                                                sendPkt
(pkt,mBtDeviceAddresses.get(i));

!                                             !                                          !
!                                             !                                        66
}

                                                      }
                                              }

                                              //clean up
                                              packet = null;

                                      }
                                      else{
                                              if(pkt.HopCount < 10){
                                                       forwardPkt(pkt,address);
                                              }
                                              else{
                                                       //do nothing, dun forward.
                                              }
                                      }
                               }

                      }
                      else{
                               if (T) Log.e(TAG,"Rejected From:"+address+" Ctr:"+pkt.Ctr+"
Src:"
                                         +pkt.Src+" Dest:"+pkt.Dest+"
HC:"+pkt.HopCount+" ID:"+pkt.PktId+" Size:"+pkt.dataSize+" SN:"+pkt.SeqNo);

                      }
             }

             public int sendPkt(DataPacket pkt,String target)
    throws RemoteException {

                              try {
                                   String destination = target;
                                   BluetoothSocket myBsock;
                                   synchronized (mBtLock){
                                           myBsock = mBtSockets.get(destination);
                                   }
                          if (myBsock != null) {
                             OutputStream outStream = myBsock.getOutputStream();

                              pkt.HopCount = (byte) (pkt.HopCount+1);

                              byte[] packetAsBytes = encrypt(pkt);

                              outStream.write(packetAsBytes);
                              if (T) Log.e(TAG,"sendPkt To:"+target+" Ctr:"+pkt.Ctr+" Src:"

!                                                 !                                        !
!                                                 !                                      67
+pkt.Src+" Dest:"+pkt.Dest+"
HopCount:"+pkt.HopCount+" ID:"+pkt.PktId);

                           }
                           else{
                                     return Connection.FAILURE;
                            }
                         } catch (IOException e) {
                            Log.i(TAG, "IOException in Forwarding packets",
                                 e);
                         }

                   return Connection.SUCCESS;
               }

                 public int forwardPkt(DataPacket pkt, String Source)
     throws RemoteException {
                          synchronized (mBtLock){
        for (int i = 0; i < mBtDeviceAddresses.size(); i++) {
                                 try {
                                          if(mBtDeviceAddresses.get(i).compareTo(Source)!=0){ //
dun forward back to source
                                                String destination = mBtDeviceAddresses.get(i);
                                                BluetoothSocket myBsock = mBtSockets.get
(destination);
                                       if (myBsock != null) {
                                          OutputStream outStream =myBsock.getOutputStream
();

                                     pkt.HopCount++;

                                     byte[] packetAsBytes = encrypt(pkt);

                                     DataPacket test = decrypt(packetAsBytes);

                                     if (T) Log.e(TAG,"Forwarding To:"+destination+"
Ctr:"+test.Ctr+" Src:"
                                                 +test.Src+" Dest:"+test.Dest+"
HopCount:"+test.HopCount+" ID:"+test.PktId+" dataSize:"+test.dataSize);


                                     outStream.write(packetAsBytes);
                                     if (T) Log.e(TAG,"Forwarding To:"+destination+"
Ctr:"+pkt.Ctr+" Src:"
                                                +pkt.Src+" Dest:"+pkt.Dest+"
HopCount:"+pkt.HopCount+" ID:"+pkt.PktId+" dataSize:"+pkt.dataSize);


!                                               !                                            !
!                                               !                                          68
//Clean up
                                          packetAsBytes = null;
                                          //pkt = null;
                                          r.gc();

                                      }
                                      else{
                                                 return Connection.FAILURE;
                                      }
                                       }
                           } catch (IOException e) {
                              Log.i(TAG, "IOException in Forwarding packets",
                                   e);
                           }
                          }
                     return Connection.SUCCESS;
                          }
                 }


    }

    private class ConnectionWaiter implements Runnable {
       private String srcApp;

        private int maxConnections;

        public ConnectionWaiter(String theApp, int connections) {
          srcApp = theApp;
          maxConnections = connections;
        }

        @Override
                  public void run() {
         try {
            for (int i = 0; i < Connection.MAX_SUPPORTED && maxConnections > 0; i++) {
               BluetoothServerSocket myServerSocket = mBtAdapter
                     .listenUsingRfcommWithServiceRecord(srcApp, mUuid.get(i));
               BluetoothSocket myBSock = myServerSocket.accept();
               String address = myBSock.getRemoteDevice().getAddress();

               boolean contains;
               synchronized (mBtLock){
                        contains = mBtSockets.containsKey(address);
               }

               while(contains){

!                                                   !                                 !
!                                                   !                               69
Log.e(TAG,address+" Already connected");
                           mHandler.obtainMessage(0, address+" Already Connected").sendToTarget
();
                           myBSock = myServerSocket.accept();
                  }

                  myServerSocket.close(); // Close the socket now that a proper
                  // connection has been made.

                  synchronized (mBtLock){
                  mBtSockets.put(address, myBSock);
                  mBtDeviceAddresses.add(address);
                  }

                  Thread mBtStreamWatcherThread = new Thread(new BtStreamWatcher(address));
                  mBtStreamWatcherThread.start();

          synchronized (mBtLock){
          mBtStreamWatcherThreads.put(address, mBtStreamWatcherThread);
          if (T) Log.e(TAG, "Listen Add btDevice:"+address+" Device
count:"+mBtDeviceAddresses.size());
          if (T) Log.e(TAG, "Listen Add BtStreamThread:"+address+" BtStreamThread
count:"+mBtStreamWatcherThreads.size());
          }

                  maxConnections = maxConnections - 1;

                  //inform webservice
                  webService.deviceConnected(mDeviceAddress, address);

                  if (mCallback != null) {
                     mCallback.incomingConnection(address);
                  }
                 }
                 if (mCallback != null) {
                    mCallback.maxConnectionsReached();
                 }
              } catch (IOException e) {
                 Log.i(TAG, "IOException in ConnectionService:ConnectionWaiter", e);
              } catch (RemoteException e) {
                 Log.e(TAG, "RemoteException in ConnectionService:ConnectionWaiter", e);
              }
          }
      }

      private class GPSListener implements Runnable {
         private UseGPS GPS;

!                                                    !                                       !
!                                                    !                                     70
private Location GeoCoordinate;

     public GPSListener() {
       GPS = new UseGPS(mSelf);
       GeoCoordinate = null;
     }

     @Override
             public void run() {
             while(true){
                     try {
                                           Thread.sleep(3000);
                                   } catch (InterruptedException e) {
                                           // TODO Auto-generated catch block
                                           e.printStackTrace();
                                   }

                     GeoCoordinate = GPS.returnCoordinates();

                    if(GeoCoordinate!=null){
                           mGeoCoordinate = GeoCoordinate;
                           Log.e(TAG,"Got Reading:"+GeoCoordinate.getLatitude()
+" ,"+GeoCoordinate.getLongitude());

                              if(mAutoConnect && mMasterDevice=="" &&!recoveryMode){
                                    mHandler.obtainMessage(0, "Attempting to AutoConnect,
Searching...").sendToTarget();
                                          Log.e(TAG,"LAT:"+GeoCoordinate.getLatitude());
                                          double geoY = GeoCoordinate.getLatitude();
                                          Log.e
(TAG,"LONG:"+GeoCoordinate.getLongitude());
                                          double geoX = GeoCoordinate.getLongitude();

                                   RegisterDeviceResult[] result = webService.registerDevice
(mDeviceAddress, geoX, geoY);
                          if(mAutoConnect){

                                                 boolean connectSucceed = false;

                                                 if(result !=null){

                                                         for( RegisterDeviceResult value:
result){

                                                                 if
(value.hardwareId.compareTo(mDeviceAddress)!=0){

!                                            !                                           !
!                                            !                                         71
Log.e(TAG,"Auto
connecting to "+value.hardwareId);


       mHandler.obtainMessage(0, "Connecting to "+value.hardwareId).sendToTarget();
                                                                      //Toast.makeText
(mSelf, "Connecting to "+value.hardwareId, 1).show();

                                                                            try {

                                                                            if(connect
("AutoConnect",value.hardwareId)==Connection.SUCCESS){


       connectSucceed = true;


       webService.deviceConnected(value.hardwareId, mDeviceAddress);


       mMasterDevice = value.hardwareId;

                                                                                    break;

                                                                            }
                                                                                             } catch
(RemoteException e) {

                                                                            // TODO Auto-
generated catch block

                                                                            e.printStackTrace();
                                                                                           }

                                                                     }
                                                              }
                                                      }
                                                      else{
                                                              mHandler.obtainMessage(0, "Unable
to a response from webservice").sendToTarget();
                                                              //Toast.makeText(mSelf, "Unable to
a response from webservice", 1).show();
                                                      }

                                             if(!connectSucceed){
                                                     if((result.length==0) || (result
[0].hardwareId.compareTo(mDeviceAddress)==0 && result.length==1 ) ){

!                                                 !                                             !
!                                                 !                                           72
mHandler.obtainMessage(0,
"No available Cluster found").sendToTarget();
                                                                      //Toast.makeText(mSelf, "No
available Cluster found", 1).show();
                                                              }
                                                              else{
                                                                      mHandler.obtainMessage(0,
"AutoConnection Unsucessful").sendToTarget();
                                                                      //Toast.makeText(mSelf,
"AutoConnection Unsucessful", 1).show();
                                                              }
                                                      }

                                                      //try again 1 min later.
                                                      try {
                                                                                        Thread.sleep
(1*60*1000);
                                                      } catch (InterruptedException e) {
                                                                                   // TODO
Auto-generated catch block

          e.printStackTrace();
                                                      }
                                        }

                                 }

                                 if(recoveryMode){
                                         //Recovering from lost Masterconnection
                                         for( String value: recoveryDevicesList){
                                                 if(!networkDevices.containsKey(value) && value!
=null){
                                                      //not in current networkDevices
                                                      Log.e(TAG,"Recovery connecting to
"+value);

                                                      mHandler.obtainMessage(0, "Recovery
Connecting to "+value).sendToTarget();
                                                      //Toast.makeText(mSelf, "Connecting to
"+value.hardwareId, 1).show();

                                                      try {
                                                                                 if(connect
("AutoConnect",value)==Connection.SUCCESS){

          webService.deviceConnected(value, mDeviceAddress);


!                                                 !                                               !
!                                                 !                                             73
mMasterDevice = value;
                                                                                  break;
                                                                            }
                                                                    } catch (RemoteException e)
{
                                                                           // TODO Auto-
generated catch block
                                                                           e.printStackTrace();
                                                                    }

                                              }

                                       }
                                       recoveryMode = false;
                               }

                        }
                 }
     }

                  public int connect(String srcApp, String device) throws RemoteException {
//        if (mApp.length() > 0) {
//                        Log.e(TAG, "Return failure");
//           return Connection.FAILURE;
//        }

               synchronized (mBtLock){
               if(mBtSockets.containsKey(device)){
                      mHandler.obtainMessage(0, "Already connected to
"+device).sendToTarget();
                      return Connection.FAILURE;
               }
               }

         mApp = srcApp;
         BluetoothDevice myBtServer = mBtAdapter.getRemoteDevice(device);
         BluetoothSocket myBSock = null;

         for (int i = 0; i < Connection.MAX_SUPPORTED && myBSock == null; i++) {
            for (int j = 0; j < 3 && myBSock == null; j++) {
               myBSock = getConnectedSocket(myBtServer, mUuid.get(i));
               if (myBSock == null) {
                  try {
                     Thread.sleep(200);
                  } catch (InterruptedException e) {
                     Log.e(TAG, "InterruptedException in connect", e);

!                                                 !                                             !
!                                                 !                                           74
}
                  }
              }
      }
      if (myBSock == null) {
         return Connection.FAILURE;
      }
      synchronized (mBtLock){
      mBtSockets.put(device, myBSock);
      mBtDeviceAddresses.add(device);
      if (T) Log.e(TAG, "Connect Add btDevice:"+device+" Devicesss
count:"+mBtDeviceAddresses.size());
      }

            Thread mBtStreamWatcherThread = new Thread(new BtStreamWatcher(device));
            mBtStreamWatcherThread.start();

      synchronized (mBtLock){
      mBtStreamWatcherThreads.put(device, mBtStreamWatcherThread);
      if(T) Log.e(TAG,"Adding new threads");
      if (T) Log.e(TAG, "Listen Add BtStreamThread:"+device+" BtStreamThread
count:"+mBtStreamWatcherThreads.size());
      }

            mMasterDevice = device;

            return Connection.SUCCESS;
        }


    }


  private BluetoothSocket getConnectedSocket(BluetoothDevice myBtServer, UUID
uuidToTry) {
     BluetoothSocket myBSock;
     try {
        myBSock = myBtServer.createRfcommSocketToServiceRecord(uuidToTry);
        myBSock.connect();
        return myBSock;
     } catch (IOException e) {
        Log.i(TAG, "IOException in getConnectedSocket", e);
     }
     return null;
  }



!                                                !                                       !
!                                                !                                     75
private final IConnection.Stub mBinder = new IConnection.Stub() {
      @Override
                 public int startServer(String srcApp, int maxConnections, boolean AutoConnect)
throws RemoteException {
//        if (mApp.length() > 0) {
//           return Connection.FAILURE;
//        }
//        mApp = srcApp;
                 mAutoConnect = AutoConnect;
        (new Thread(new ConnectionWaiter(srcApp, maxConnections))).start();
        (new Thread(new GPSListener())).start();

        //GPS


        //start discoverable
        Intent i = new Intent();
        i.setClass(mSelf, StartDiscoverableModeActivity.class);
        i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(i);
        return Connection.SUCCESS;
    }

    @Override
               public int connect(String srcApp, String device) throws RemoteException {
//      if (mApp.length() > 0) {
//                     Log.e(TAG, "Return failure");
//         return Connection.FAILURE;
//      }
               synchronized (mBtLock){
                       if(mBtSockets.containsKey(device)){
                              mHandler.obtainMessage(0, "Already connected to
"+device).sendToTarget();
                              return Connection.FAILURE;
                       }
               }

        mApp = srcApp;
        BluetoothDevice myBtServer = mBtAdapter.getRemoteDevice(device);
        BluetoothSocket myBSock = null;

        for (int i = 0; i < Connection.MAX_SUPPORTED && myBSock == null; i++) {
           for (int j = 0; j < 3 && myBSock == null; j++) {
              myBSock = getConnectedSocket(myBtServer, mUuid.get(i));
              if (myBSock == null) {
                 try {

!                                               !                                            !
!                                               !                                          76
Thread.sleep(200);
                 } catch (InterruptedException e) {
                    Log.e(TAG, "InterruptedException in connect", e);
                 }
             }
           }
        }
        if (myBSock == null) {
           return Connection.FAILURE;
        }

       synchronized (mBtLock){
       mBtSockets.put(device, myBSock);
       mBtDeviceAddresses.add(device);
       if (T) Log.e(TAG, "Connect Add btDevice:"+device+" Device
count:"+mBtDeviceAddresses.size());
       }

        Thread mBtStreamWatcherThread = new Thread(new BtStreamWatcher(device));
        mBtStreamWatcherThread.start();

       synchronized (mBtLock){
       mBtStreamWatcherThreads.put(device, mBtStreamWatcherThread);
       if (T) Log.e(TAG, "Listen Add BtStreamThread:"+device+" BtStreamThread
count:"+mBtStreamWatcherThreads.size());
       }

        mMasterDevice = device;

        return Connection.SUCCESS;
    }

     @Override
               public int broadcastMessage(String srcApp,String destination, byte[] message)
throws RemoteException {
//      if (!mApp.equals(srcApp)) {
//         return Connection.FAILURE;

                 if (T) Log.e(TAG,"BroadCasting");
                 byte zero = 0;
                 String dest;
                 byte seqNo = 0;

                 synchronized (mBtLock){
        for (int i = 0; i < mBtDeviceAddresses.size(); i++) {
                          if(destination == ""){
                                  dest = mBtDeviceAddresses.get(i);

!                                                 !                                        !
!                                                 !                                      77
}
                      else{
                              dest = destination;
                      }
                      //for broadcasting, seqNo should not increase.

                       if(destination ==""){
                               //sending to everyone
                               if(sendByte(zero,mBtDeviceAddresses.get(i),dest,message,false)
==Connection.FAILURE){
                                        return Connection.FAILURE;
                               }
                       }
                       else{
                               //sendint to a specific target
                       if(i ==0){//first packet
                                        if(sendByte(zero,mBtDeviceAddresses.get
(i),dest,message,false)==Connection.FAILURE){
                                                        return Connection.FAILURE;
                                        }

                            }
                            else{//subsequence packet is the same seqNo
                                    if(sendByte(zero,mBtDeviceAddresses.get
(i),dest,message,true)==Connection.FAILURE){
                                           return Connection.FAILURE;
                                    }
                            }

                      }

//                if(i ==0){
//                        if(sendByte(zero,mBtDeviceAddresses.get(i),dest,message,false)
==Connection.FAILURE){
//                               return Connection.FAILURE;
//                        }
//
//                }
//                else{
//                        if(sendByte(zero,mBtDeviceAddresses.get(i),dest,message,true)
==Connection.FAILURE){
//                               return Connection.FAILURE;
//                        }
//                }

              }
              }

!                                                   !                                      !
!                                                   !                                    78
return Connection.SUCCESS;
    }

    public int broadcastPacket(DataPacket pkt) throws RemoteException{
               if (T) Log.e(TAG,"PacketBroadCasting");

                 synchronized (mBtLock){
        for (int i = 0; i < mBtDeviceAddresses.size(); i++) {
                          if(sendPacket(pkt,mBtDeviceAddresses.get(i))==Connection.FAILURE){
                                 return Connection.FAILURE;
                          }
        }
                 }

               return Connection.SUCCESS;
    }

    @Override
               public String getConnections(String srcApp) throws RemoteException {
      if (!mApp.equals(srcApp)) {
         return "";
      }
      String connections = "";
      synchronized (mBtLock){
      for (int i = 0; i < mBtDeviceAddresses.size(); i++) {
         connections = connections + mBtDeviceAddresses.get(i) + ",";
      }
      }
      return connections;
    }

    @Override
              public int getVersion() throws RemoteException {
      try {
         PackageManager pm = mSelf.getPackageManager();
         PackageInfo pInfo = pm.getPackageInfo(mSelf.getPackageName(), 0);
         return pInfo.versionCode;
      } catch (NameNotFoundException e) {
         Log.e(TAG, "NameNotFoundException in getVersion", e);
      }
      return 0;
    }

   @Override
             public int registerCallback(String srcApp, IConnectionCallback cb) throws
RemoteException {
//     if (!mApp.equals(srcApp)) {

!                                             !                                            !
!                                             !                                          79
//          return Connection.FAILURE;
//         }
         mCallback = cb;
         return Connection.SUCCESS;
     }

     public int sendPacket(DataPacket pkt,String target)
                      throws RemoteException {
                      try {
                             String destination = target;
                             BluetoothSocket myBsock;
                             synchronized (mBtLock){
                                     myBsock = mBtSockets.get(destination);
                             }

                    if (myBsock != null) {
                       OutputStream outStream = myBsock.getOutputStream();
                       pkt.HopCount = (byte) (pkt.HopCount + 1);

                       byte[] packetAsBytes = encrypt(pkt);

                       outStream.write(packetAsBytes);

                     if (T) Log.e(TAG,"SendPacket To:"+destination+" Ctr:"+pkt.Ctr+" Src:"
                              +pkt.Src+" Dest:"+pkt.Dest+" HC:"+pkt.HopCount+"
ID:"+pkt.PktId+" SN:"+pkt.SeqNo);

                       //Clean up
                       packetAsBytes = null;
                       pkt = null;
                       r.gc();


                             return Connection.SUCCESS;
                    }
                 } catch (IOException e) {
                    Log.i(TAG, "IOException in Forwarding packets",
                         e);
                 }

                 return Connection.FAILURE;
     }

     //Only 1mb of data can be send including 57byte of header, 17src, 17dest,21 pktId, 2 hop
count, 967 data
               public int sendByte(byte Ctr,String target ,String destination, byte[] data, boolean
offSeqNo)

!                                                 !                                            !
!                                                 !                                          80
throws RemoteException {
              try {
                          if (D) Log.e(TAG,"Free memory at SendByte: "+r.freeMemory());

                        if(data.length > DataPacket.DATA_MAX_SIZE){
                                 Log.e(TAG,"Data should not
exceed"+DataPacket.DATA_MAX_SIZE+"byte!");
                                 return Connection.FAILURE;
                        }

                BluetoothSocket myBsock = mBtSockets.get(target);
                if (myBsock != null) {
                   OutputStream outStream = myBsock.getOutputStream();
                         DataPacket packet = new DataPacket();

                         byte seqNo =0;

                         if(Ctr != 0){
                                 seqNo = 125;
                         }
                         else{
                                 synchronized(seqNoWatcherLock){
                                        if(seqNoWatcher.containsKey(destination)){
                                               seqNo = seqNoWatcher.get(destination);

                                               if(!offSeqNo){
                                                       seqNo = (byte)(seqNo +1);

                                                      if(seqNo >100){
                                                             seqNo = 0;
                                                      }

                                                      seqNoWatcher.remove(destination);
                                                      seqNoWatcher.put(destination,
seqNo);
                                               }
                                       }
                                       else{
                                               seqNoWatcher.put(destination, seqNo);
                                       }
                                }
                         }

                         packet.SeqNo = seqNo;

                         packet.Ctr = Ctr;
                         packet.Src = mDeviceAddress;

!                                          !                                         !
!                                          !                                       81
packet.Dest = destination;
                                  packet.PktId = generatePacketId(mDeviceAddress);
                                  //packet.PktId = mDeviceAddress+"1234";
                                  packet.dataSize = (short) data.length;
                                  //packet.data = joinByteArray(data," ".getBytes());
                                  packet.data = data;

                                  byte[] packetAsBytes = encrypt(packet);


                                  outStream.write(packetAsBytes);


                     if (T) Log.e(TAG,"SendBtye To:"+target+" Ctr:"+packet.Ctr+" Src:"
                              +packet.Src+" Dest:"+packet.Dest+" HC:"+packet.HopCount+"
ID:"+packet.PktId+" SN:"+packet.SeqNo);


                             //Clean up
                         packetAsBytes = null;
                             packet = null;
                             data = null;
                             destination = null;
                             target = null;
                             outStream.flush();
                             outStream =null;
                             myBsock = null;
                             r.gc();

                          return Connection.SUCCESS;
                        }
                     } catch (IOException e) {
                        Log.i(TAG, "IOException in sendMessage - Dest:" + destination + ", Msg:"
+ data.toString(),
                            e);
                     }
                     return Connection.FAILURE;
               }

     @Override
             public int sendMessage(String srcApp, String destination, byte[] message)
                  throws RemoteException {

                         if(message ==null){
                                Log.e(TAG,"Unable to Send NULL byte Message");
                                return Connection.FAILURE;
                         }

!                                                   !                                        !
!                                                   !                                      82
//                          Location test = GPS.returnCoordinates();
//
                            if(mGeoCoordinate != null) {
                                  Log.e(TAG,"LAT:"+mGeoCoordinate.getLatitude());
                                  Log.e(TAG,"LONG:"+mGeoCoordinate.getLongitude());
                            }
                            else
                            {
                                  Log.e(TAG,"location is null");
                            }


                    byte zero = 0;

                    synchronized (mBtLock){
                    if(mBtDeviceAddresses.size() == 0) return Connection.FAILURE;
                    }

                    boolean contains;
                    synchronized (mBtLock){
                           contains = mBtDeviceAddresses.contains(destination);
                    }

                    if(contains){

                            return sendByte(zero,destination,destination,message,false);
                    }
                    else{
                            return broadcastMessage("",destination,message);
                    }

     }


     @Override
               public void shutdown(String srcApp) throws RemoteException {
      try {
               synchronized (mBtLock){
         for (int i = 0; i < mBtDeviceAddresses.size(); i++) {
            BluetoothSocket myBsock = mBtSockets.get(mBtDeviceAddresses.get(i));
            myBsock.close();
         }
         mBtSockets = new HashMap<String, BluetoothSocket>();
         mBtStreamWatcherThreads = new HashMap<String, Thread>();
         mBtDeviceAddresses = new ArrayList<String>();
         mApp = "";

!                                             !                                              !
!                                             !                                            83
mAutoConnect = false;
            mMasterDevice ="";
            recoveryMode = false;
                 }
         } catch (IOException e) {
            Log.i(TAG, "IOException in shutdown", e);
         }

     }

     @Override
                public int unregisterCallback(String srcApp) throws RemoteException {
//       if (!mApp.equals(srcApp)) {
//          return Connection.FAILURE;
//       }
       mCallback = null;
       return Connection.SUCCESS;
     }

                @Override
                public HashMap<String,String> getDevices(){
                       //List<String> devices = new ArrayList<String>();
                       if (T) Log.e(TAG,"Getting devices!");

                       //reseting
                       networkDevices = new HashMap<String,String>();

                       //fire signal to get reply
                       DataPacket packet = new DataPacket();
                       packet.Dest = mDeviceAddress;
                       packet.Src = mDeviceAddress;
                       packet.Ctr = 1;
                       packet.SeqNo = 125;
                       packet.PktId = generatePacketId(mDeviceAddress);

                       try {
                               broadcastPacket(packet);
                       } catch (RemoteException e1) {
                               // TODO Auto-generated catch block
                               e1.printStackTrace();
                       }


                       //Clean up
                       packet = null;

                       return networkDevices;

!                                               !                                         !
!                                               !                                       84
//                        try
//                        {
//                               Thread.sleep(3000); // do nothing for 1000 miliseconds (3 second)
//                        }
//                               catch(InterruptedException e)
//                        {
//                                      e.printStackTrace();
//                        }
//
//                        return networkDevicesAddresses;

                   }

          @Override
                   public String getAddress() throws RemoteException {
            return mBtAdapter.getAddress();
          }

          @Override
                   public String getName() throws RemoteException {
            return mBtAdapter.getName();
          }

     };

}




!                                                  !                                           !
!                                                  !                                         85

More Related Content

KEY
Test+video+upload
PDF
NetBeez - IEEE IRI 2016
PPTX
DEVNET-1114 Automated Management Using SDN/NFV
PPTX
Slideshare
KEY
testing+123
PDF
FYP%3A+P2P+Bluetooth+Communication+Framework+on+Android%0A
KEY
FYP%3A+P2P+Bluetooth+Communication+Framework+on+Android%0A
PPTX
Business+Case+Competition
Test+video+upload
NetBeez - IEEE IRI 2016
DEVNET-1114 Automated Management Using SDN/NFV
Slideshare
testing+123
FYP%3A+P2P+Bluetooth+Communication+Framework+on+Android%0A
FYP%3A+P2P+Bluetooth+Communication+Framework+on+Android%0A
Business+Case+Competition

Similar to FYP%3A+P2P+Bluetooth+Communication+Framework+on+Android%0A (20)

PDF
Cad_cam_cim___3rd_edition
PDF
PDF
End2end resilience
PDF
Semantic Web Services for Computational Mechanics : A Literature Survey and R...
PDF
Guide to Videoconferencing
PDF
Guide to Videoconferencing
PDF
Integratedbook
DOCX
Chani index
DOC
Diplomatiki word
PDF
Finjan Vital Security For eMail Technical White Paper
PDF
A.vivotek ip surveillance_handbook
DOC
Crap shit head
PDF
070105618001 070105618006-070105618015-070105618021
PDF
CCIE Data Center V3.0 Training and Certification
DOC
msword
PDF
student mangement
DOC
Lead Allocation System's Attribute Driven Design (ADD)
PPTX
Agile and CMMI - a potential blend
DOC
3.table of contents
PDF
File Splitter Table of contents
Cad_cam_cim___3rd_edition
End2end resilience
Semantic Web Services for Computational Mechanics : A Literature Survey and R...
Guide to Videoconferencing
Guide to Videoconferencing
Integratedbook
Chani index
Diplomatiki word
Finjan Vital Security For eMail Technical White Paper
A.vivotek ip surveillance_handbook
Crap shit head
070105618001 070105618006-070105618015-070105618021
CCIE Data Center V3.0 Training and Certification
msword
student mangement
Lead Allocation System's Attribute Driven Design (ADD)
Agile and CMMI - a potential blend
3.table of contents
File Splitter Table of contents
Ad

More from Tianwei_liu (20)

PPT
LifeBloom_test_192371
PDF
Electronic+Gaming
PDF
Final+Year+Project
PDF
This+is+blah
PDF
Insane+Studd
PDF
Insane+Studd
PDF
Insane+Studd
PDF
Insane+Studd
PDF
Insane+Studd
PPT
Project2
PPT
Project2
PPT
Project2
PDF
alsdkj
PDF
alsdkj
PDF
This+is+blah
PDF
Eon nus hci_master_class
PPT
test+new
PPTX
PPTX
Startup+weekend
PDF
EE3207+-+Computer+Architecture
LifeBloom_test_192371
Electronic+Gaming
Final+Year+Project
This+is+blah
Insane+Studd
Insane+Studd
Insane+Studd
Insane+Studd
Insane+Studd
Project2
Project2
Project2
alsdkj
alsdkj
This+is+blah
Eon nus hci_master_class
test+new
Startup+weekend
EE3207+-+Computer+Architecture
Ad

FYP%3A+P2P+Bluetooth+Communication+Framework+on+Android%0A

  • 1. « P2P Communication Framework on Android Platform » Submitted by Liu Tianwei Department of Electrical & Computer Engineering In partial fulfillment of the requirements for the Degree of Bachelor of Engineering National University of Singapore
  • 2. ABSTRACT With Smartphone penetration reaching 37%(Nelson,2011) worldwide and predicted to reach 55% by the year 2014, the availability of powerful mobile devices in the pocket of every consumer is fast becoming a nom. However, the capabilities of these devices are often limited by data network in which they has access to, which are often old and are not designed to support the huge no of increasingly data hungry mobile devices. This paper aims to explore the alternatives to traditional network architecture focusing mainly on the P2P network architecture on mobile devices. To reach out to wider audiences, the open-source framework implemented in this project is based on the widely popular open-source framework for mobile device - Android. The framework allows developers to easily leverage on in-built hardware communication capability of these devices(3G/Wifi/Bluetooth) without having to deal with the underlying networking implementation. ! ! ! ! !
  • 3. ACKNOWLEDGMENTS I would like to express my heart-felt gratitude to Associate Professor Tay Teng Tiow for his invaluable guidance and support through the entire project. I would also like to thank the ECE department for the use of the facilities and the provision of android devices used for the experiments. I would also express my gratitude to my group of peers who had work with me and developed the Peer-to-Peer Multiplayer Android Game based the framework developed in the thesis. Their inputs has allow me to stress test and improve on the stability of the framework. ii ! ! ! ! !
  • 4. CONTENTS ABSTRACT i ACKNOWLEDGEMENTS ii LIST OF FIGURES iii CHAPTER 1 INTRODUCTION 1 1.1 Background 1 1.2 Problems 2 1.3 Motivation 2 1.4 Objective 2 1.5 Use Cases 3 1.6 Approach 4 1.7 Assumption 4 1.8 Results of Implementation Experiment 5 1.9 Thesis Layout 5 CHAPTER 2 LITERATURE REVIEW 8 2.1 Server - Client Architecture 8 2.2 Peer to Peer Architecture 9 2.2.1 Centralized Index 10 2.2.2 Query Flooding 11 2.2.3 Hierarchical Overlay 12 2.2.4 Distributed Hash Table 13 2.2.5 Advantages of Peer-to-Peer Architecture 13 2.2.6 Disadvantage of Peer-to-Peer Architecture 13 2.3 Server-Client Vs Peer-to-Peer 14 2.4 Proposed Architecture 16 CHAPTER 3 IMPLEMENTATION APPROACHES AND METHODOLOGY 17 3.1 Platform 17 3.2 Hardware choices and limitations 18 3.2.1 Bluetooth 18 3.2.2 Wireless Fidelity 20 3.2.3 Mobile Telecommunication 21 3.3 Network Design 23 3.3.1 Control Byte 24 3.3.2 Source address 25 3.3.3 Destination address 25 3.3.4 Hop Count 25 3.3.5 Packet Id 25 3.3.6 Data Size 25 3.3.6 Sequence No 24 iii ! ! ! ! !
  • 5. CONTENTS 3.4.1 Priority Queuing 26 3.4.2 Round Robin Queuing 26 3.4.3 Weighted Fair Queuing 27 3.4.4 Leaky Bucket Policer 28 3.4.5 Leaky Bucket Policer + Weighted Fair Queuing 30 3.4.6 Design decision 30 3.5 AutoConnection 31 3.5.1 Unable to connect to new device without user acknowledgement 31 3.5.2 Unable to make device always discoverable 31 3.5.3 Working with paired devices 32 3.5.4 Geo-Location Indexing server 32 CHAPTER 4 IMPLEMENTATION RESULTS AND PERFORMANCE METRICS 33 4.1 Key Features 33 4.1.1 No Rooting Required 33 4.1.2 Packet Routing 33 4.1.3 No need for centralized Index server 33 4.1.4 Flow Control 34 4.1.5 Auto-Connection 34 4.1.6 Open-Source 34 4.2 Performance Metrics 35 CHAPTER 5 FRAMEWORK LIMITATION AND POSSIBLE FUTUREWORK 36 5.1 Framework Limitations 36 5.1.1 Pairing between 2 devices 36 5.1.2 Lack of security 36 5.1.3 Dependency on Geo-Location Indexing Server 36 5.2 Future Work 37 5.2.1 Server-less implementaton 37 5.2.2 Optimization 37 5.2.3 Security 37 CHAPTER 5 SUMMARY AND CONCLUSION 38 6.1 Future of mobile communication 38 6.2 Conclusion 38 REFERENCES 39 APPENDIX I - AIDI File for IConnection 41 APPENDIX II - AIDI File for IConnectionCallback 41 APPENDIX III - Connection Class 41 APPENDIX IV - ConnectionService Class 41 iv ! ! ! ! !
  • 6. LIST OF FIGURES Fig. 1 U.S Smartphone Penetration & Projections 1 Fig. 2 Mobile P2P Network 3 Fig. 3 Maximum Throughput Rate 7 Fig. 4 Server-Client 8 Fig. 5 Peer-to-Peer 9 Fig. 6 Centralized Index 10 Fig. 7 Query Flooding 11 Fig. 8 Hierarchical Overlay 12 Fig. 9 Server Client Vs P2P 14 Fig. 10 MDT vs No of Clients 15 Fig. 11 Mobile O.S Market Share 17 Fig. 12 Bluetooth Logo 18 Fig. 13 Power Class chart 19 Fig. 14 Version Chart 19 Fig. 15 WiFi Logo 20 Fig. 16 802.11 protocol 20 Fig. 17 Scatter Net 23 Fig. 18 Data Packet Design 24 Fig. 19 Priority Design 26 Fig. 20 Round Robin Queuing 27 Fig. 21 Weight Fair Queuing 27 Fig. 22 Leaky Bucket Policer 28 Fig. 23 Data Rate 29 Fig. 24 LBP + WFQ 29 iii ! ! ! ! !
  • 7. CHAPTER 1 INTRODUCTION 1.1 Background Figure 1: U.S Smartphone Penetration & Projections In a recent report by Nielsen, smartphone penetration rate in US is predicted to reach over 50% reaching over 95 millions units in the 2011(Nielsen 2011). A smartphone, is defined here as a mobile phone “that offers more advanced computing ability and connectivity than a contemporary feature phone”(Nusca 2009). As seen in Figure 1, the high growth rate of these devices bring about many opportunities for entrepreneurs and developer to leverage on the extra computing and communication power of these devices. However, the high growth rate of these data hungry devices is not without it problems. ! ! ! ! ! 1
  • 8. 1.2 Problems The suddenly increase in the demand for mobile data bandwidth brought by these devices took many mobile network providers by surprise. Many of these network providers relies heavily on traditional network architectures that are not designed to handles these kinds of traffics requirements. As network infrastructure expands takes times and also a huge amount of capital investment, network outrages are common for smartphone users and thus in many ways limiting the capabilities of these devices. 1.3 Motivation At such there is a need to redesign the current network architectures to allow for greater network scalability and more importantly a lower infrastructure cost for each additional devices(clients) added to the network. 1.4 Objective The objectives of the projects are therefore to explore and experiment on other means of network infrastructures suitable for usage on smartphone. The projects aims to provide a prototype open- source communication framework suitable for usage in the below scenario. ! ! ! ! ! 2
  • 9. 1.5 Use Cases Figure 2 shows how the framework can serve as an support to the current mobile communication architecture. By leveraging on the Peer-to-Peer capability of the framework, the network stress on the traditional Architecture can be greatly reduced. Figure 2: Mobile P2P Network Some of the propose used case for the framework would be: - Ad-hoc gaming network. - Instant Messaging Application. - File sharing. - Video Streaming. - Internet Sharing / booster. - Geo-Location Triangulation. - Others applications which require data transfer within a network. ! ! ! ! ! 3
  • 10. 1.6 Approach In order to meet the requirements for a network that is scalable and lower on infrastructure cost, my literature reviews(Chapter 2) points the solution to none other than a Peer-to-Peer approach. The network communication architecture adopted for this framework is therefore a Peer-to-Peer one based on a modified Gnutella Peer-to-Peer architecture. Due to the ease of implementation and also the ability to reach a wider open-source community, the Open-Source Android Operating System for mobile devices is adopted as the platform for this framework implementation. Extra efforts were also put in to the architecture design so that it would not require a “Rooted” android device. By doing so, the author hopes that it would be more appropriate for mass-market adoptions. 1.7 Assumption and Limitation Due to the time constraints and also hardware limitations, the framework currently only relies on bluetooth for it’s Peer-to-Peer communications(Chapter 3). This in turn means that the framework is currently limited by the hardware capability of of the bluetooth chipsets. At the time of this writing, majority of the android devices available in the market is still using Bluetooth 2.1 + EDR, with some newer devices supporting Bluetooth 3.0. At such, testing and performance benchmarking for this framework is currently done only on Bluetooth 2.1+EDR, however there should not be any problem using the framework on Bluetooth 3.0 chipset. The framework should work with Android O.S 2.0 and above and has been tested across Android 2.0/2.1(Eclair), Android 2.2(Froyo) and Android 2.3(GingerBread). Due to resource limitations, the framework has been tested on the following phones only: - HTC Magic - HTC Device Z ! ! ! ! ! 4
  • 11. - Samsung Galaxy S - Nexus One 1.8 Results of Implementation and Experiment An Open Source Peer-to-Peer framework focusing on Bluetooth Communication has been implemented on Android O.S. It comprises of the following Key Features: - No Rooting Required The framework does not required developer/users to “root” their android phones in order to use it’s features. It’s is designed to work off the shelf and integrates easily with other existing projects. It leverage on the Android Interface Definition Language(AIDL) to provide a clean and easy to integrate interface for developer to work with. - Packet Routing All devices connected to a network clusters double up as router for the network. Once a device has been connected successfully to a device within a network cluster, it can communicate directly with any nodes in the network. - No need for a centralized indexing server The framework implements a modified “Gnutella” P2P network. This means that the network is purely decentralized and does not require an indexing server. Through the use of Query Flooding techniques, similar to that found in classic “Gnutella” P2P network, a device would be able to communicated with any node within the network. - Flow Control As every device double up as a router within the network, it is crucial that flow control is implemented at each node to ensure a fair usage for each node. A “Fair weighted Queuing” Traffic policer is currently implemented at each node to ensure Quality of Service(Chapter 3). ! ! ! ! ! 5
  • 12. - Auto-Connection This is an experimental features of the framework. Due to the security limitation(Chapter 3) of the bluetooth framework on android, where an device cannot be set to be “always discoverable”, there is no way for a device to detect a nearby device and automatically setup an connection with it. To overcome this, an indexing server is implemented to allow devices to query for nearby devices in which they can connect to and form a network. Using geo-location information coming from the devices, the server would suggest a list of devices in which the device can connect to. Suggestion are made so that the bluetooth Scatter net topology is maintained. - Open-Source This framework is currently developed as open source project. It’s source can be found at http:// code.google.com/p/p2p-communication-framework-for-android/. Found together with the framework is a multi-user bluetooth Chat application which demonstrates the Apis capabilities of the framework. A Peer-to-Peer network mutiplayer game based on the framework developed by the author together with a good of android enthusiasts can also be found. - Performance Metrics According to the experimental measurements obtained from the transferring of multiple Image files of 350 - 380 kbytes, we observed that the throughput rate stabilizes at around 54Kbits/s for nodes that are more than 1 jump away from the original node. Figure 3 shows the throughput rate obtained from readings measured from these experiments. ! ! ! ! ! 6
  • 13. 324#565'789)6:8-6$' +!" *!" )!" (!" '!" !"#$%&%' &!" %!" $!" #!" !" !" !,'" #" #,'" $" $,'" %" %,'" &" &,'" ()*')+',)-'$)'./%0120)1' Figure 3: Maximum Throughput Rate 1.9 Thesis Layout In Chapter 2, a literature review is done to find out the various alternative networking infrastructure that can be used to address the current problem and also meet the paper’s objective. In Chapter 3, we would discuss and look into the various approaches and methodology used in the implementation of this framework. Chapter 4, would than cover the implementations outcome and benchmark the performance of the framework. Chapter 5 would than discuss the limitation of the framework and the possible future work that can be done to the framework. Lastly, the conclusion of the thesis is than presented in Chapter 6. ! ! ! ! ! 7
  • 14. CHAPTER 2 LITERATURE REVIEW 2. 1 Server - Client Architecture Figure 4: Server-Client Figure 4 shows a classic Server - Client architecture that most Internet Service Provider(ISP) has their network built on. The client-server model of computing is a distributed application structure that partitions task or workloads between the providers of resources or service, called servers, and service requesters, called clients(Microsystem 2009). The clients and servers typically communicated over a computer network on network hardware infrastructure provided by ISP. Due to the nature of it’s designs, additional network hardware infrastructures has to be added in order to support additional capacity(clients). Advantages Greater Security assurance: Since data are stored on the servers, which generally have far greater security controls than most clients. Server can also have better control access with resources, to guarantee that only those clients with the appropriate permissions may access and change data. With data storage being centralized , updates to any data are far easier to administer as compared to other architecture like Peer-To-Peer one. ! ! ! ! ! 8
  • 15. Disadvantages A major disadvantages of a Server - Client architecture is that it does not scale well when there is sudden increase in network traffic. Increase in network bandwidth require prior hardware infrastructure investment, which become a problem when there is a sudden increase in network bandwidth requirement. The client-server architecture also lacks robustness as resources are all centralized, should a critical server fails, all clients in the network will be affected. 2.2 Peer to Peer Architecture Figure 5: Peer-to-Peer A Peer-to-Peer(P2P) computing or networking is a distributed application architecture that partition tasks or workloads between peers. Peers make a portion of their resources, such as processing power, disk storage or network bandwidth, directly available to other network ! ! ! ! ! 9
  • 16. participants, without the need for central coordination by servers or stable hosts(Scholmeier 2002). The peer-to-peer application structure was popularized by file sharing systems like Napster and Kazaa. Since it’s induction, many different architectural design from P2P network has been introduced. They are however generally classified into the below 4 approaches. 2.2.1 Centralized Index Figure 6: Centralized Index This is the original “Napster” design. The design involved a centralized Index server which registers all clients in the network and keep and index of their individual resources on the server. When a clients requires a resource, it will first query the server to get the information regarding the clients which holds the resource that it requires. The client will than establish an direct connection to the respective clients to get it’s required resources. ! ! ! ! ! 10
  • 17. 2.2.2 Query flooding (Gnutella) Figure 7: Query Flooding Query flooding is a method to search for a resource on a P2P network. By using query flooding, a P2P network can be fully decentralized with no need for an centralized indexing servers to hold a list of all clients and resources available in the network. As shown in Figure 7, when a client requires a resources, it will send a query message to all nodes connected to it. Each node will than forward the query message to all of it’s neighbors, hence coining the term “Query Flooding”. QueryHit will than be sent over in the reverse path back to the client. A direct connection can than be established between the client and the node with the resource required. A popular Peer-to-Peer network design that employ this search technique to implement a pure Peer- to-Peer network is the Gnutella Peer-to-Peer network Architecture. ! ! ! ! ! 11
  • 18. 2.2.3 Hierarchical Overlay Figure 8: Hierarchical Overlay A Hierarchical Overlay Design is a fusion of the Centralized Index and Query Flooding Architecture Design. The design recognized that not all nodes within a Peer-to-Peer network are equal in term of bandwidth, availabilities and computational power. It therefore introduce the concept of of “super peers” in the network which server as mini-index which keep track of all the resources of it’s children. Similar Query Flooding concept is than employed at the “super peers” level when a node in the network query for a resources. The popular Internet Telephony Application SKYPE is a good example of application that employ the Hierarchical Overlay Peer- to- peer Design. ! ! ! ! ! 12
  • 19. 2.2.4 Distributed Hash Table (DHT) A distributed hash table is a class of a decentralized distributed system that implements a lookup service similar to that of a hash table. Key, value pairs are stored in a DHT and any participating node can efficiently retrieve the value associated with any given key. The responsibility for maintaining the mapping from keys to values is distributed among all the nodes in the network. An efficient algorithm is employed such that there would be minimal amount of disruption when there is a change in the set of participants in the network. 2.2.5 Advantages of Peer-to-Peer Architecture In Peer-to-Peer network design, clients provide resources which include bandwidth, storage space and computing power as it join an network. This allow the total capacity of the network to also increases as an new node arrive in the network. This allows the network to be well adapted to sudden increase in network bandwidth requirements. There is also little to no additional cost to support an extra client added to the network. The distributed nature of Peer-to-Peer network also increases the robustness of network. For pure Peer-to-Peer network like the Gnutella, Hierarchical Overlay and DHT designs, which enabled peers to find the require resources without relying on a centralized index server, the network robustness was very much increase as there is no single point of failure in the architecture. 2.2.6 Disadvantages of Peer-to-Peer Architecture Due to the nature of the network design , unsecured and unsigned codes may allow unauthorized remote access to resource on a victims nodes and compromised the entire network. ! ! ! ! ! 13
  • 20. 2.3 Server-Client Vs Peer-to-Peer To better evaluate the performance of Server-Client network design versus that of a Peer-to-Peer network design, let us that a look at a typical network operation: File Distribution (Figure 6) Figure 9: Server Client Vs P2P Objective: - Distribute a large file from a single server to a large N number of host(peers). As shown in Figure 9. Server-Client: -- Eq(1) For a typical server client architecture, the server would need to send N copies of the file. The slowest client takes at least F/dmin time to download the given file. Given a network as depicted in Figure 9, Eq(1) show the total time required for the server to ! ! ! ! ! 14
  • 21. complete the task of distributing all the files. Peer-to-Peer: For a Peer-to-Peer architecture, the server would need to send at least one copy of the file : F/us The slowest client would take at least F/dmin to download the given file. The total number of bits that must be downloaded would be NF bits, but the total upload capacity is now . This would means that the minimum time taken for the task of distributing the files would be: -- Eq(2) Therefore, the total time taken for the task of distributing the file in a P2P network would be: -- Eq(3) Figure 10: MDT vs No. Of Clients Figure 10 shows a comparison of the two methods plotted by Minimum Distribution Time (MDT) against N(no of clients). As shown in the graph, we can see that the Client-Server ! ! ! ! ! 15
  • 22. architecture does not scale well and MTD increase linear as the required no of clients increases. On the other hand, we can see that Peer-to-Peer architecture scales nicely with the increase in the no of clients. The MTD tends towards the maximum time of 1 hour, which is the maximum time taken for the server to upload one file. 2.4 Proposed Architecture In conclusion, the literature review shows us that a Peer-to-Peer architecture design has significant advantage in terms of scalability and cost as compared to a traditional client-server architecture design. This suit our requirement for a new architecture design. At such, the proposed framework would be based on a Peer-to-Peer that allows developers to build scalable applications on top of it. In the next chapter, we would discuss in depth the implementation and its design decision. ! ! ! ! ! 16
  • 23. CHAPTER 3 IMPLEMENTATION APPROACHES AND METHODOLOGY 3.1 Platform Figure 11: Mobile O.S Market Share Figure 11 shows the US smartphone market shares acquisitions rate for the different smartphone operating systems in a research done by Nielsen in 2010. As shown in the graph, we can see that the android platform is fast gain ground in the U.S smartphone market. This is likely due to the “open” nature of the android platform which attracts both Hardware OEMs and software developers. Indeed, the openness of the android framework allows developer to unleash the full potential of a smartphone which much more ease. At such, the author choose to use the android framework for the purpose of this research paper due to potential(high market adoption rate) and also for its ease of implementation. ! ! ! ! ! 17
  • 24. 3.2 Hardware choices and limitations The android platform offers a varieties of ways for devices to communicate between themselves and with the rest of the world(internet). The fews choices that are available are: 3.2.1 Bluetooth Figure 12: Bluetooth logo Bluetooth™ is a proprietary open wireless technology standard for exchanging data over short distances from fixed and mobile devices. Creating personal area network(PANS) with high levels of security. It uses a radio communication system and therefore do not requires a visual line of sight between 2 devices for them communicate. Bluetooth™ uses a radio technology called frequency-hopping spread spectrum, which chops up data being sent and transmits chunks of it on up to 79 bands, 1MHz each, centered from 2402 to 2480 MHZ in the range of 2400-2483.5MHZ. Bluetooth™ is a packet-based protocol with Master-slave structure. One master may communicate up to 7 slaves in a piconet at the same time, with all the devices sharing the master’s clock. Packet exchange is based on the basic clock defined by the master which ticks at 312.5 us intervals. A Bluetooth™ can switch role between a slave and master. This means that a slave device can become the master at any time. At any given time, data can be transferred between the master and one other device, however it can rapidly switches between devices in round-robin fashions with little over head. ! ! ! ! ! 18
  • 25. Figure 13: Power Class chart Three power classes of Bluetooth™ exist in the market to address various use cases. Due to the limited power available on mobile devices, most if not all android devices operate on Class 2 chipset which limits it range to a 10 meters as shown in Figure 13 above. Figure 14: Version Chart Since it’s inception in 1994 by telecom vendor Ericsson(Wikipedia), Bluetooth™ has under went a couple of revisions recorded in Figure 14. Each revision brings about different improvement in terms of data transfer rate and also power consumption. Begin from Android 1.6, the android operating system supports bluetooth 2.0 and above chipset. The framework provided socket connection similar to that of a TCP socket connection. Most androids device found in the market comes with bluetooth chipsets 2.0 and above. ! ! ! ! ! 19
  • 26. 3.2.2 Wireless Fidelity Figure 15: WiFi Logo Wireless Fidelity or Wi-Fi for short is a wireless communication technology developed and controlled by the IEEE based on the IEEE 802.11 standards. It allowed a Wi-Fi enabled device such as a personal computer or a mobile phone to communicate with other devices or connect to the internet. This is usually achieve by having the Wi-Fi device connect to a network through a access points via a router. Direct device to device communication is also possible without the involvement of a access point. This form of Wi-Fi communication is called the ad hoc mode. Figure 16: 802.11 protocol Since it induction in 1997(Wikipedia), the IEEE 802.11 protocol has under went many revisions in its protocol to meet the increasing bandwidth and range requirements of communication ! ! ! ! ! 20
  • 27. devices. Figure 16 show the different protocol standards of the IEEE 802.11 and their data transfer rates. The Android Operation System supported Wi-Fi connectivity since it’s first release. Most of the android devices in the market today are still using the IEEE802.11 g protocols. The android framework does not support ad hoc mode of Wi-Fi communication by default. Developer would need to “root” their device to enable this feature. 3.2.3 Mobile telecommunication Mobile telephony or telecommunication is the provision of telephone services to phones which may move around freely rather than stay fixed in one location. Mobile devices connect to a terrestrial cellular network of base station(cell towers) which allows them to communicate between one another or with the rest of the world(internet). Most of the world mobile telephone system is based on the Global System for Mobile Communication system, GSM in short. Beside the GSM, another popular mobile telephone system is based on the Code division Multiple Access system, CDMA in short. GSM system uses Time Division Multiple Access TMDA and Frequency Division Multiple Access FDMA techniques to multiple phones in it’s network to communicate simultaneously while the CDMA system employ Code Division Multiple Access techniques to achieve similar goals. 3G or 3rd generation mobile telecommunication is a generation of standards for mobile phones and mobile telecommunication services fulfilling the International Mobile Telecommunications-2000 specifications by the International Telecommunication Union(ITU) (Wikipedia). As the ITU did not provide a clear definition of the data rate users can expect from 3G ! ! ! ! ! 21
  • 28. equipment or providers, the data transfer can varies across different equipments and service provider. However, a typical 3G cellular network users can expect a minimum data rate of 2Mbit/s for stationary or walking users to 384kbit/s in a moving vehicles according to IMT-2000 specifications(IMT-2000 2000). Most android power devices in the market comes with 3G data supports. However, they usually requires users to pay additional monthly fees to enjoy this features. At such, not all android devices will be able to use this form of communication easily. 3.2.4 Design Decisions After reviewing the different communication options that the android framework offers, it become clear that Bluetooth™ and Wi-Fi are more feasible choices as compared to mobile telecommunication such as 3G due to it’s lower availability and more importantly, it’s lack of options for direct communication between mobile devices. However, the android platform currently does not support Wi-Fi ad hoc mode of communication. In order for developer to leverage on this mode of communicate, it would require him to use a “rooted” device. At such, the author choose to have the framework focus on bluetooth as the main form of inter-device communication for it’s first release. ! ! ! ! ! 22
  • 29. 3.3 Network Design Figure 17: Scatter Net As discussed previously in 3.1, Bluetooth™ is a packet-based protocol with Master-slave structure. A Master device can allow up to 7 slave devices to connect to it forming a piconet. When one or more piconets is bridge by one or more devices in their individual piconet, a Scatter net is formed. Figure 17 shows a example of 2 piconets forming a Scatter net. A device in a Peer-to-Peer network usually acquire it’s resource in 2 steps. First, it would need to find out which are the nodes in the network that contain the resource that it desires. Depending on the network architectural, this is achieved by either by doing a query with some form of index server(Central Indexing, DHT, Hierarchical Overlay) or through Query Flooding (Gnutella). After the required information with regards to the nodes which contain the desired resource has been acquired, the next time would be establish a direct connection to the respective nodes so that the actual resource acquisition can begin. Since Bluetooth™ on android devices has a range limit of up to 10 meters, unlike traditional ! ! ! ! ! 23
  • 30. Peer-to-peer network design; a direct connection between any 2 devices in the network might not be possible. Taking that into account, a little modifications to the traditional Peer-to-Peer network design have to made. After the information with regards to the nodes which contains the desired resources has been obtained, nodes within a bluetooth Peer-to-Peer scatternet/piconet has to assist in routing data packets between the 2 nodes. Taking into the account of the framework design objectives of supporting ah-hoc network creation and the hardware limitation of the Bluetooth™ communication protocol, the author favored a modified version of the Gnutella Peer-to-Peer design as compared to the other designs discussed previously. Figure 18 : Data Packet Design In order to implement a Gnutella Peer-to-Peer network on a Bluetooth™ Scatter net, a 1024 byte size data packet is used for data transmission between devices on the network. The data packet uses 60 bytes for header, leaving a dynamic data size of up to 964 bytes. Below is a break down of each field in the header. 3.3.1 Control Byte The first byte of the data packet is used to differentiate between a normal data packet and a control data packets. Control data packets are currently used in the network for query flooding. ! ! ! ! ! 24
  • 31. They have higher priority as compared to normal data packets. 3.3.2 Source address This field contains the 17 characters hardware MAC address of the bluetooth device which the packets originated from. 3.3.2 Destination address This field contains the 17 characters hardware MAC address of the bluetooth device which the packets target at. 3.3.3 Hop Count This 1 byte contains the no of time the data packet has jumped across nodes in the network. This is necessary for Query Flooding technique to work in a Gnutella network. Current, the cap is 10 count before the packet is no longer forwarded. 3.3.4 Packet Id This is a 21 characters string generated by joining the MAC address of the device which generate the packet with 4 characters string generated from the system clock time. This allows repeated packets to be recognized and discard at each nodes and thus reducing unnecessary network traffic and also repeat data at the destination node. The 4 characters string generated only repeats once every 10 seconds. 3.3.5 Data Size This 2 bytes field contains the information regarding the size of the data field. This value can varies from 1 to 964. 3.3.6 Sequence No This is a 1-byte field that stores that Sequence No of a packet. Since the path taken by each packets to it’s destination might not be in order, this Sequence No will allow the destination node to rebuild the data in sequence. This value current varies from 0 - 99. ! ! ! ! ! 25
  • 32. 3.4 Flow Control Since packets has to be possibility routed across multiple nodes in the Scatter net before reaching it’s destination, there is a need to implement some form of schedule system/traffic policing to ensure a certain level of Quality of Service(QoS). A traditional First-In-First-Out system would not scale well under high network traffic condition, such as a scenario where by there is a large file transfer between 2 devices in the network. If a traditional First-In-First-Out system is adopted. During the entire period of the file transfer operation, other devices in the network would experience low bandwidth thus affecting QoS. Let us look at some possible schedule system/traffic policing implementation. 3.4.1 Priority Queuing Figure 19: Priority Queuing In this approach, packets are classified into different priority classes & placed into different queues. Figure 19 shows an example implementation of this form of scheduling, The red packets represented high priority packets and the green packets represented lower priority packets. Packets of the same priority are served using First-in-first-out scheduling system. ! ! ! ! ! 26
  • 33. 3.4.2 Round Robin Queuing Figure 20: Round Robin Queuing The round robin queuing is a scheduling mechanism that ensure that fair usage of between different Class(type) of packets. Every queue take turns in getting their data packets processed. This schedule method can be made work-conserving by never allowing the link to be idle when there are still packets in any other queue. If a Class queue is empty, any Class queue which is not empty will immediately be processed. Figure 20 shows a graphic depiction of this method of scheduling. 3.4.3 Weighted Fair Queuing Figure 21: Weight Fair Queuing Weighted Fair Queuing is a generalized form of a Round Robin scheduling system. It differs from a normal round robin scheduling system by allowing each class to have a different weighted amount of service in a cycle. Similar to a round-robin implementation, the Weighted Fair Queuing can be made work-conserving by ensuring the link does not become idle when there are still packets in any other queue. ! ! ! ! ! 27
  • 34. --- Eq(4) In the worst case, when all Class queue are filled with packets, any even Class i would still be guaranteed to received bandwidth equal to that of Eq(4). 3.4.4 Leaky Bucket Policer Unlike a scheduling technique, a policing approach regulate the traffic entering a network according to declared parameters. There are commonly three policing criteria: Average Rate: This control the network traffic by limiting the Long-term average rate at which packets are sent. Peak Rate: This control the network traffic by limiting the max number of packets allowed to be sent over a short period of time. Maximum Burst Size: This control the network traffic by limiting the max number of packets allowed to be sent over an extremely short interval of time. This short interval of time is usually treated as instantaneous. Figure 22: Leaky Bucket Policer ! ! ! ! ! 28
  • 35. The leaky Bucket Policer technique is a policing technique that employ all the above 3 policing criteria. Figure 22 shows a graphical description of this policing technique. A “bucket” which can hold up to b tokens is first created. Tokens are than generated at the rate of r tokens/sec and adding to the “bucket”. If the bucket is full, newly generated token would be ignored. Before a packet is sent into the network, it must first remove an available token, when the bucket comes empty, it would then be not allowed to to sent a packet. By doing this, the Maximum burst size is b packets and the long-term average rate is r packets/ sec. Eq(5) and Figure 23 shows the maximum number of packets that can enter the network over any interval of time of length t. --- Eq(5) Figure 23: Data Rate ! ! ! ! ! 29
  • 36. 3.4.5 Leaky Bucket Policer + Weighted Fair Queuing By combining the two techniques, the technique can provides a guaranteed upper bound on delay and thus provide a QoS guarantee. Figure 24: LBP + WFQ Suppose flow 1’s bucket is initially full, a burst of b1 packets can pass through & join the Weighted Fair Queue buffer. Since these packets are served at a rate of at least , the last packet will have a maximum delay of: --- Eq(6) provided that : -- Eq(7) 3.4.6 Design decision Given the time constraints and also to reduce the complexity of the implementation, a Weighted Fair Queueing scheduling technique is chosen as the flow control mechanism in the framework implemented. ! ! ! ! ! 30
  • 37. 3.5 AutoConnections In order to prevent malicious activities to be perform on a user mobile devices via bluetooth connectivity, the Android Operating System has put in place many security features to sure that the end uses will always be keep inform of activities perform via bluetooth. For example, the system requires user acknowledge when an application tried to turn on bluetooth connectivity or connect to a device that it has not paired with before. Although, these security features may have help to increase the security of the android operating service, it has also hindered the many possible innovations in Peer-to-Peer networking on the Android Operating System. The following two security features of the Android Operating System has been the major hinderer of Peer-to-Peer networking innovations on Android Operating System so far. 3.5.1 Unable to connect to new devices without user acknowledgement The Android Bluetooth framework also requires 2 devices who have not been previously connected before to undergo an “pairing” process before data is able to be transmitted between them. This pairing process require both phone users to acknowledge a prompt from the system within a short period of time before allowing the 2 devices to be connected. These makes it extremely difficult for a Peer-to-Peer network to be formed. 3.5.2 Unable to make device always discoverable The Android Bluetooth framework only allow a device to be “make discoverable” by other devices for a maximum period of 120 second at any given time. Therefore, the framework require users acknowledge each time to allow a device to “make discoverable” for another 120 seconds. The inability for an device to “made discoverable” automatically and persistently makes it hard to implement a peer-to-peer network on the framework as a device would not know who ! ! ! ! ! 31
  • 38. to connect to when it first tries to join the network. 3.5.3 Working with paired devices For simplicity sake, the framework currently does not offer a solution to this. Users currently can only automatically form a Peer-to-Peer network with devices that it has previous connected. However, being an “open” operating system, the Android platform has been constantly listening to feedback from developers and making changes to the framework to meet their needs. In latest Android release of 2.3.3, the android framework has finally allow unsecured bluetooth communication to be established between 2 devices who has never been paired before without user acknowledgement(2.3.3 2010). 3.5.4 Geo-Location Indexing server To overcome the problem where by a device cannot be set to be always “discoverable” a centralized index server was developed to index the geo-location coordinate of the all mobile devices on the network. Before connecting to the Peer-to-Peer network, a device would first query the centralized indexing server with it’s own Geo-location details to get information regarding all the devices nearby. The central indexing server is thus responsible for maintain the bluetooth Scatter net formed by the devices. This is currently a temporary experimental solutions as the author believe that with open nature of the framework would see that a alternative would be provided from within the android framework similar to the modification since previous in Android 2.3.3 release. ! ! ! ! ! 32
  • 39. CHAPTER 4 IMPLEMENTATION RESULTS AND PERFORMANCE METRICS 4.1 Key Features An Open Source Peer-to-Peer framework focusing on Bluetooth Communication has been implemented on Android O.S. It comprises of the following Key Features: 4.1.1 No Rooting Required Unlike most open source Bluetooth application/framework out there, this framework does not required developer/users to “root” their android phones in order to use it’s features. It’s is designed to work off the shelf and integrates easily with other existing projects. It leverage on the Android Interface Definition Language(AIDL) to provide a clean and easy to integrate interface for developer work with. The author hope that by doing so, the framework would be able to have a much larger outreach and would allow it to collect more data from it’s central indexing server which is used by it’s Auto connect feature. 4.1.2 Packet Routing All devices connected to a network clusters double up as router for the network. Once a device has been connected successfully to a device within a network cluster, it can communicate directly with any nodes in the network. This feature allow ah-hoc network to form manually or automatically between devices. This feature would enable developer to build many interesting application should as multi- user chat room and multiplayer games. 4.1.3 No need for centralized indexing server The framework implements a modified “Gnutella” P2P network. This means that the network is ! ! ! ! ! 33
  • 40. purely decentralized and does not require an indexing server. Through the use of Query Flood techniques, similar to that found in classic “Gnutella” P2P network, a device would be able to communicated with any node within the network. 4.1.4 Flow Control As every device double up as a router within the network, it is crucial that flow control is implemented at each node to ensure a fair usage for each node. A “Fair weighted Queuing” schedule mechanism is implemented at each node(Chapter 3). This scheduling technique ensure that control packets has higher priority as compared to normal packet and while ensuring a fair distribution of the network bandwidth between all the nodes in the network. 4.1.5 Auto-Connection This is an experimental features of this framework. Due to the security limitation(Chapter 3) of the bluetooth framework on android, where an device cannot be set to be “always discoverable”, there is no way for a device to detect a nearby device and automatically setup an connection with it. To over this, an indexing server is implemented to allow devices to query for nearby devices in which they can connect to and form a network. Using geo-location information coming from the devices, the server would suggest a list of devices in which the devices can connect to. Suggestion are made so that the bluetooth Scatter net topology is maintained. 4.1.6 Open-Source This framework is currently developed as open source project. It’s source can be found at http:// code.google.com/p/p2p-communication-framework-for-android/. Found together with the framework is a multi-user bluetooth Chat application which demonstrates the Apis capabilities of the framework. ! ! ! ! ! 34
  • 41. A Peer-to-Peer networking game based on the framework developed by the author together with a group of android enthusiasts can also be found. 4.2 Performance Metrics According to the experimental measurements obtained from the transferring of multiple Image files of 350 - 380 kbytes, we observed that the throughput rate stabilizes at around 54Kbits/s for nodes that are more than 1 mores away from the original node. Figure 3 shows the throughput rate obtained from read measure from these experiments. 324#565'789)6:8-6$' +!" *!" )!" (!" '!" !"#$%&%' &!" %!" $!" #!" !" !" !,'" #" #,'" $" $,'" %" %,'" &" &,'" ()*')+',)-'$)'./%0120)1' Figure 3: Maximum Throughput Rate This transfer rate is acceptable for most of the uses proposal earlier. We would also like to highlight that the test is conducted on Nexus one and HTC Desire Z devices which are using Bluetooth 2.0 chipset. With much high speed of Bluetooth 3.0 chipset(8 times faster than 2.0), it is believe that the performance of this framework could be much better. ! ! ! ! ! 35
  • 42. CHAPTER 5 FRAMEWORK LIMITATION AND POSSIBLE FUTURE WORK 5.1 Framework Limitations The first release of the framework aims to show a working prototype of an alternative mobile communication network based on Peer-to-Peer architectural. However, due to time constraints and other external/internal factors, the frameworks does has a few limitation. The next few paragraphs discuss some of them. 5.1.1 Pairing between 2 devices As of the time of this writing, no android has released an official firmware upgrade which uses Android 2.3.3. At such, the framework has not been tested with the new unsecured Bluetooth™ connection which allow Bluetooth™ connection between 2 devices which have not been previously paired. These still remain as the major limitation for the existing framework as it hinder automatic connection between 2 devices who have not been previously paired. 5.1.2 Lack of security The current framework implementation did not encrypt the data packets in any way. This would means that current framework is vulnerable to malicious activities and attacks such as the “man- in-the-middle” attacks. This made data transfer in the network unsecured and unsuitable for usage by data which are “confidential” in nature. 5.1.3 Dependency on Geo-Location Indexing server Due to the Android Bluetooth™ framework security limitation discussed in Chapter 3, the currently framework is unable to be fully decentralized and require am external indexing server for it’s Auto connection feature to work. This approach is also affected by hardware limitation ! ! ! ! ! 36
  • 43. both in term of the accuracy of the geo-location chipset and the available of Internet connection on the device. 5.2 FutureWork After reviewing the limitation of the current framework, the following future work is suggested to be done: 5.2.1 Server-less implementation To allow the Peer-to-Peer network to be truly scalable, it’s dependency on the Geo-Location indexing server has be to remove. Future work can be done to use Bluetooth scanning instead of geo-location position to determine which device a device should connect to. This would also be largely affected by the implementation changes from the Android framework itself. 5.2.2 Optimization The current Framework adopted a Gnutella Peer-to-Peer architecture large due to it’s simplicity of implementation. In the next release of the framework, more work can be done to optimize and improve the efficiency of the Peer-to-Peer framework. More efficient search and routing technique could be adopted to improve the data transfer speed of the current framework. 5.2.3 Security As discussed previously in the limitation of the framework, the current framework does not implement any form of data encryption which cause the underlying network to be be an unsecured one. This made it a security risk and thus unsuitable for applications which contains sensitive information to be developed on it. At such, it might be good for the next release to take this into account and implement some form of data encryption to allow better data security within the network. ! ! ! ! ! 37
  • 44. CHAPTER 6 SUMMARY AND CONCLUSION 6.1 Future of mobile communication As the computation power of mobile devices continue to increase and the cost of these devices continue to falls, the term “smartphone” would soon become a term of the past. All mobile devices would soon have the computation power of a laptop or desktop that we are using today. As the power of these devices increase, the demand for faster data connectivity and higher bandwidth would definitely continue to increase at an exponential rate. At such there would be a need for us to reconsider the current network infrastructure design to allow for better scalability. 6.2 Conclusion In this thesis paper, we had explored the different alternatives communication architectural design that would allow the current mobile communication to scale better. The prototype framework that was developed as part of this thesis provided us a platform to evaluate the feasibility of using Peer-to-Peer communication between mobile devices as an alternative to traditional mobile communication method. From the result of the implementation, namely the success demonstrated in the multi-user chat application and also the multi-player game both implemented using the Peer-to-Peer framework, we can conclude that a Peer-to-Peer implementation more than exceed our expectation as an alternative to support or even replace the current mobile communication architecture. With the increasing adoption rate of the Android platform and also it’s recognition for the potential in Peer-to-Peer communication (revision 2.3.3), we can concluded that the future for Peer-to-Peer communication on mobile devices is a bright one. The author hope that the framework developed in this thesis would provide a start for more innovation in this field. ! ! ! ! ! 38
  • 45. REFERENCES [1] 2.3.3, A. (2010). "Android 2.3.3." Retrieved 31 March, 2010, from http:// developer.android.com/sdk/android-2.3.3.html. [2] IMT-2000 (2000). [3] Microsystem, S. (2009). "Distributed Application Architecture." Retrieved 06-16, 2009, from http://java.sun.com/developer/Books/jdbc/ch07.pdf. [4] Nielsen (2011). "US Smartphone Penetration and forecast 2011." [5] Nusca, A. (2009). "Smartphone Vs feature phone arms race heats up; which did you buy?", from http://www.zdnet.com/blog/gadgetreviews/smartphone-vs-feature- phone-arms-race-heats-up-which-did-you-buy/6836. [6] Scholmeier, R. (2002). A definition of Peer-to-Peer Networking for the Classificiation of Peer-to-Peer Architectures and Applications, Proceedings of the First International Conference on Peer-to-Peer Computing. IEEE. [7] Wikipedia. "3G." Retrieved 31 march, 2010, from http://en.wikipedia.org/wiki/3G. [8] Wikipedia. "Bluetooth." Retrieved 31 March, 2010, from http://en.wikipedia.org/ wiki/Bluetooth#cite_note-0. [9] Wikipedia. "IEEE 802.11." Retrieved 31 March, 2010, from http://en.wikipedia.org/ wiki/IEEE_802.11#cite_note-80211timeline-6. [10] Broadcast-Based Peer-to-Peer Collaborative Video Streaming Among Mobiles, Man- Fung Leung and S-H Gary Chan [11] Integrating Bluetooth with Wireless and Ricocheting, David J.Y Lee and William C.Y.Lee [12] Dynamic Topology Management in Bluetooth Networks, Suresh Srinivasan, Keyur Desai, Akash Tilak Choudhari, Dinesh Rajan, South Methodist University, Dallas, TX ! ! ! ! ! 39
  • 46. [13] Always Best Connected, EVA GUSTAFSSON AND ANNIKA JONSSON, ERICSSON RESEARCH [14] MobiClique: Middleware for Mobile Social Networking, Anna-Kaisa Pietillainen (Thomson), Earl Oliver(University of waterloo), Jason LeBrun(University of California, Davis), George Varghese(University of California, San Diego) and Christophe Diot(Thomson) ! ! ! ! ! 40
  • 47. ! ! ! ! ! ! ! ! ! ! APPENDIX I /* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * AIDL for the Bluetooth Connect, Link, Compete Service * IConnection.java is autogenerated from this */ package net.clc.bt; // TODO: Ideally, we would import BluetoothDevice here // and use that instead of just a String in the connect // method for better type safety, but this is currently // not possible yet. import net.clc.bt.IConnectionCallback; // Declare the interface. interface IConnection { String getAddress(); Map getDevices(); String getName(); int startServer(in String srcApp, in int maxConnections,in boolean AutoConnect); int connect(in String srcApp, in String device); int sendMessage(in String srcApp, in String device, in byte[] message); int broadcastMessage(in String srcApp,in String destination, in byte[] message); String getConnections(in String srcApp); int getVersion(); int registerCallback(in String srcApp, IConnectionCallback cb); int unregisterCallback(in String srcApp); void shutdown(in String srcApp); } ! ! ! ! ! 41
  • 48. APPENDIX II /* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * AIDL for the Bluetooth Connect, Link, Compete Service * IConnectionCallback.java is autogenerated from this */ package net.clc.bt; // Declare the interface. oneway interface IConnectionCallback { void incomingConnection(String device); void maxConnectionsReached(); void messageReceived(String device, in byte[] message); void connectionLost(String device); } ! ! ! ! ! 42
  • 49. APPENDIX III /* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.clc.bt; import java.util.List; import java.util.Map; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; /** * API for the Bluetooth Click, Link, Compete library. This library simplifies * the process of establishing Bluetooth connections and sending data in a way * that is geared towards multi-player games. */ public class Connection { public static final String TAG = "net.clc.bt.Connection"; public static final int SUCCESS = 0; public static final int FAILURE = 1; public static final int MAX_SUPPORTED = 7; public interface OnConnectionServiceReadyListener { public void OnConnectionServiceReady(); ! ! ! ! ! 43
  • 50. } public interface OnIncomingConnectionListener { public void OnIncomingConnection(String device); } public interface OnMaxConnectionsReachedListener { public void OnMaxConnectionsReached(); } public interface OnMessageReceivedListener { public void OnMessageReceived(String device, byte[] message); } public interface OnConnectionLostListener { public void OnConnectionLost(String device); } private OnConnectionServiceReadyListener mOnConnectionServiceReadyListener; private OnIncomingConnectionListener mOnIncomingConnectionListener; private OnMaxConnectionsReachedListener mOnMaxConnectionsReachedListener; private OnMessageReceivedListener mOnMessageReceivedListener; private OnConnectionLostListener mOnConnectionLostListener; private ServiceConnection mServiceConnection; private Context mContext; private String mPackageName = ""; private boolean mStarted = false; private final Object mStartLock = new Object(); private IConnection mIconnection; private IConnectionCallback mIccb = new IConnectionCallback.Stub() { @Override public void incomingConnection(String device) throws RemoteException { if (mOnIncomingConnectionListener != null) { mOnIncomingConnectionListener.OnIncomingConnection(device); } } ! ! ! ! ! 44
  • 51. @Override public void connectionLost(String device) throws RemoteException { if (mOnConnectionLostListener != null) { mOnConnectionLostListener.OnConnectionLost(device); } } @Override public void maxConnectionsReached() throws RemoteException { if (mOnMaxConnectionsReachedListener != null) { mOnMaxConnectionsReachedListener.OnMaxConnectionsReached(); } } @Override public void messageReceived(String device, byte[] message) throws RemoteException { if (mOnMessageReceivedListener != null) { mOnMessageReceivedListener.OnMessageReceived(device, message); } } }; // TODO: Add a check to autodownload this service from Market if the user // does not have it already. public Connection(Context ctx, OnConnectionServiceReadyListener ocsrListener) { mOnConnectionServiceReadyListener = ocsrListener; mContext = ctx; mPackageName = ctx.getPackageName(); mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { synchronized (mStartLock) { mIconnection = IConnection.Stub.asInterface(service); mStarted = true; if (mOnConnectionServiceReadyListener != null) { mOnConnectionServiceReadyListener.OnConnectionServiceReady(); } } } @Override public void onServiceDisconnected(ComponentName name) { synchronized (mStartLock) { try { ! ! ! ! ! 45
  • 52. mStarted = false; mIconnection.unregisterCallback(mPackageName); mIconnection.shutdown(mPackageName); } catch (RemoteException e) { Log.e(TAG, "RemoteException in onServiceDisconnected", e); } mIconnection = null; } } }; Intent intent = new Intent("com.google.intent.action.BT_ClickLinkCompete_SERVICE"); intent.addCategory("com.google.intent.category.BT_ClickLinkCompete"); mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); } public int startServer(final int maxConnections, OnIncomingConnectionListener oicListener, OnMaxConnectionsReachedListener omcrListener, OnMessageReceivedListener omrListener, OnConnectionLostListener oclListener, boolean AutoConnect) { if (!mStarted) { return Connection.FAILURE; } if (maxConnections > MAX_SUPPORTED) { Log.e(TAG, "The maximum number of allowed connections is " + MAX_SUPPORTED); return Connection.FAILURE; } mOnIncomingConnectionListener = oicListener; mOnMaxConnectionsReachedListener = omcrListener; mOnMessageReceivedListener = omrListener; mOnConnectionLostListener = oclListener; try { int result = mIconnection.startServer(mPackageName, maxConnections, AutoConnect); mIconnection.registerCallback(mPackageName, mIccb); return result; } catch (RemoteException e) { Log.e(TAG, "RemoteException in startServer", e); } return Connection.FAILURE; } public int connect(String device, OnMessageReceivedListener omrListener, OnConnectionLostListener oclListener) { // if (!mStarted) { // return Connection.FAILURE; // } ! ! ! ! ! 46
  • 53. mOnMessageReceivedListener = omrListener; mOnConnectionLostListener = oclListener; try { int result = mIconnection.connect(mPackageName, device); mIconnection.registerCallback(mPackageName, mIccb); return result; } catch (RemoteException e) { Log.e(TAG, "RemoteException in connect", e); } Log.e(TAG, "Return failure here"); return Connection.FAILURE; } public int sendMessage(String device, byte[] message) { if (!mStarted) { return Connection.FAILURE; } try { return mIconnection.sendMessage(mPackageName, device, message); } catch (RemoteException e) { Log.e(TAG, "RemoteException in sendMessage", e); } return Connection.FAILURE; } public int broadcastMessage(byte[] message,String destination) { if (!mStarted) { return Connection.FAILURE; } try { return mIconnection.broadcastMessage(mPackageName,destination, message); } catch (RemoteException e) { Log.e(TAG, "RemoteException in broadcastMessage", e); } return Connection.FAILURE; } public String getConnections() { if (!mStarted) { return ""; } try { return mIconnection.getConnections(mPackageName); } catch (RemoteException e) { Log.e(TAG, "RemoteException in getConnections", e); } return ""; ! ! ! ! ! 47
  • 54. } public int getVersion() { if (!mStarted) { return Connection.FAILURE; } try { return mIconnection.getVersion(); } catch (RemoteException e) { Log.e(TAG, "RemoteException in getVersion", e); } return Connection.FAILURE; } public String getAddress() { if (!mStarted) { return ""; } try { return mIconnection.getAddress(); } catch (RemoteException e) { Log.e(TAG, "RemoteException in getAddress", e); } return ""; } public Map getDevices(){ try{ return mIconnection.getDevices(); } catch(RemoteException e){ Log.e(TAG,"Remote Exception in getDevice",e); } return null; } public String getName() { if (!mStarted) { return ""; } try { return mIconnection.getName(); } catch (RemoteException e) { Log.e(TAG, "RemoteException in getVersion", e); } return ""; } ! ! ! ! ! 48
  • 55. public void shutdown() { try { mStarted = false; if (mIconnection != null) { mIconnection.shutdown(mPackageName); } mContext.unbindService(mServiceConnection); } catch (RemoteException e) { Log.e(TAG, "RemoteException in shutdown", e); } } } ! ! ! ! ! 49
  • 56. APPENDIX IV /* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.clc.bt; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.Timer; import java.util.TimerTask; import java.util.UUID; import java.util.concurrent.BlockingQueue; import java.util.concurrent.PriorityBlockingQueue; import android.app.Service; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothSocket; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.location.Location; ! ! ! ! ! 50
  • 57. import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.RemoteException; import android.util.Log; import android.widget.Toast; import com.example.Geoscribe.UseGPS; import com.example.Geoscribe.comms.GeoscribeComms2; import com.webservice.objects.RegisterDeviceResult; /** * Service for simplifying the process of establishing Bluetooth connections and * sending data in a way that is geared towards multi-player games. */ public class ConnectionService extends Service { public static final boolean T = true; public static final boolean D = false; public static final String TAG = "net.clc.bt.ConnectionService"; public static final String NEW_NETWORK_DEVICE_FOUND = TAG+"DEVICEFOUND"; public static final String DEVICE_ADDR = TAG+"DEVICEADDRESS"; public static final String DEVICE_NAME = TAG+"DEVICENAME"; static final int bufferSize = 1024; private ArrayList<UUID> mUuid; private ConnectionService mSelf; private Context mContext; private String mApp; // Assume only one app can use this at a time; may // change this later private IConnectionCallback mCallback; private ArrayList<String> mBtDeviceAddresses; private HashMap<String,String> networkDevices; ! ! ! ! ! 51
  • 58. private HashMap<String, BluetoothSocket> mBtSockets; private HashMap<String, Thread> mBtStreamWatcherThreads; private HashMap<String, Long> packetWatcher; private HashMap<String, Byte> seqNoWatcher; private HashMap<String, Byte> recievedSeqNoWatcher; private Object seqNoWatcherLock; private Object recievedSeqNoWatcherLock; private Object mBtLock; private BluetoothAdapter mBtAdapter; private String mDeviceAddress; private String mDeviceName; private Runtime r; private Location mGeoCoordinate; private String mMasterDevice=""; private boolean mAutoConnect = false; private boolean recoveryMode = false; private ArrayList<String> recoveryDevicesList; private GeoscribeComms2 webService; final Handler mHandler = new Handler(){ /* (non-Javadoc) * @see android.os.Handler#handleMessage(android.os.Message) */ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub //super.handleMessage(msg); String message = msg.obj.toString(); ! ! ! ! ! 52
  • 59. Toast.makeText(mSelf, message, 1).show(); } }; //private final BlockingQueue<DataStream> packetQueue; public static final byte[] shortToByteArray(short value) { if (value < 0) return new byte[]{0,0}; return new byte[] { (byte)(value >>> 8), (byte)value}; } public static final short byteArrayToShort(byte [] b) { return (short)(((b[0] & 0xFF) << 8) + (b[1] & 0xFF)); } public static DataPacket decrypt(byte[] buffer){ DataPacket pkt = new DataPacket(); pkt.Ctr = buffer[0]; pkt.Src = new String(buffer,1,17); pkt.Dest = new String(buffer,18,17); pkt.PktId = new String(buffer,35,21); pkt.HopCount = buffer[56]; byte[] dataSize = new byte[]{buffer[57],buffer[58]}; pkt.dataSize = byteArrayToShort(dataSize); pkt.SeqNo = buffer[59]; pkt.data = new byte[pkt.dataSize]; for(int i = 0; i<pkt.dataSize;i++){ pkt.data[i] = buffer[i+60]; } dataSize = null; buffer = null; return pkt; } /* (non-Javadoc) * @see android.app.Service#onCreate() ! ! ! ! ! 53
  • 60. */ @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); mContext = this; } public static byte[] encrypt(DataPacket pkt){ byte header[] = new byte[1]; header[0] = pkt.Ctr; byte packetAsBytes[] = joinByteArray(header,pkt.Src.getBytes()); packetAsBytes = joinByteArray(packetAsBytes,pkt.Dest.getBytes()); packetAsBytes = joinByteArray(packetAsBytes,pkt.PktId.getBytes()); byte hop[] = new byte[1]; //hop[0] = (byte) (pkt.HopCount+1); hop[0] = pkt.HopCount; packetAsBytes = joinByteArray(packetAsBytes,hop); packetAsBytes = joinByteArray(packetAsBytes,shortToByteArray(pkt.dataSize)); byte seq[] = new byte[1]; seq[0] = pkt.SeqNo; packetAsBytes = joinByteArray(packetAsBytes,seq); packetAsBytes = joinByteArray(packetAsBytes,pkt.data); // //add a stop // packetAsBytes = joinByteArray(packetAsBytes," ".getBytes()); // packetAsBytes[packetAsBytes.length-1] = 0; header = null; hop = null; seq = null; pkt = null; return packetAsBytes; } public static byte[] joinByteArray(byte[] a, byte[] b){ int count = a.length + b.length; byte[] result = new byte[count]; for(int i =0; i<a.length; i++){ ! ! ! ! ! 54
  • 61. result[i] = a[i]; } for(int i =0; i<b.length; i++){ result[a.length+i] = b[i]; } return result; } public static String generatePacketId(String mDeviceAddress){ String id = Integer.toString( (int)(Calendar.getInstance().getTimeInMillis() %(10*1000))); int length = id.length(); if(length<0) length = 0; for(int i = length; i<4;i++){ id = "0"+id; } return mDeviceAddress+id; } public synchronized boolean isPacketRepeated(DataPacket pkt){ for ( Iterator<Long> iter = packetWatcher.values().iterator(); iter.hasNext(); ){ Long time = iter.next(); if ( (Calendar.getInstance().getTimeInMillis() - time )> 1000){ // remove from any state with a space in its long name. iter.remove();// avoids ConcurrentModificationException } //Log.e(TAG,""+time); } //Clean up memory r.gc(); if(packetWatcher.containsKey(pkt.PktId)){ return true; } else{ packetWatcher.put(pkt.PktId, Calendar.getInstance().getTimeInMillis()); return false; } } public ConnectionService() { mSelf = this; ! ! ! ! ! 55
  • 62. mBtAdapter = BluetoothAdapter.getDefaultAdapter(); mDeviceAddress = mBtAdapter.getAddress(); mDeviceName = mBtAdapter.getName(); mApp = ""; mBtSockets = new HashMap<String, BluetoothSocket>(); mBtDeviceAddresses = new ArrayList<String>(); mBtStreamWatcherThreads = new HashMap<String, Thread>(); packetWatcher = new HashMap<String,Long>(); seqNoWatcher = new HashMap<String,Byte>(); recievedSeqNoWatcher = new HashMap<String,Byte>(); recievedSeqNoWatcherLock = new Object(); seqNoWatcherLock = new Object(); mBtLock = new Object(); webService = new GeoscribeComms2(); //packetQueue = new LinkedBlockingQueue<DataStream>(); r = Runtime.getRuntime(); if (T) Log.e(TAG, "Total Memory at Creation: "+r.totalMemory()); if (T) Log.e(TAG, "Free Memory at Creation: "+r.freeMemory()); mUuid = new ArrayList<UUID>(); // Allow up to 7 devices to connect to the server mUuid.add(UUID.fromString("a60f35f0-b93a-11de-8a39-08002009c666")); mUuid.add(UUID.fromString("503c7430-bc23-11de-8a39-0800200c9a66")); mUuid.add(UUID.fromString("503c7431-bc23-11de-8a39-0800200c9a66")); mUuid.add(UUID.fromString("503c7432-bc23-11de-8a39-0800200c9a66")); mUuid.add(UUID.fromString("503c7433-bc23-11de-8a39-0800200c9a66")); mUuid.add(UUID.fromString("503c7434-bc23-11de-8a39-0800200c9a66")); mUuid.add(UUID.fromString("503c7435-bc23-11de-8a39-0800200c9a66")); } @Override public IBinder onBind(Intent arg0) { return mBinder; } private class BtStreamWatcher implements Runnable { private String address; private final PriorityBlockingQueue pktQueue; private Thread pktRouter; public BtStreamWatcher(String deviceAddress) { address = deviceAddress; ! ! ! ! ! 56
  • 63. pktQueue = new PriorityBlockingQueue(); pktRouter = new Thread(new PacketRouter(pktQueue)); pktRouter.start(); } @Override public void run() { //byte[] buffer = new byte[DataPacket.HEADER_SIZE]; BluetoothSocket bSock; synchronized(mBtLock){ bSock = mBtSockets.get(address); } try { InputStream instream = new BufferedInputStream(bSock.getInputStream()); int bytesRead = -1; while (true) { // DataStream dataStream = new DataStream(); byte[] dataBuffer = new byte[DataPacket.PACKET_SIZE]; bytesRead = instream.read(dataBuffer,0,DataPacket.HEADER_SIZE); if (bytesRead != -1) { //ensure HEADERSIDE Byte is read. if (T) Log.e(TAG,"HeaderbyteRead:"+bytesRead); int bytesRead2 = bytesRead; int bufferSize = DataPacket.HEADER_SIZE; while(bytesRead2 != bufferSize){ bufferSize = bufferSize - bytesRead2; bytesRead2 = instream.read (dataBuffer,bytesRead,bufferSize); bytesRead = bytesRead+bytesRead2; } byte[] temp = new byte[]{dataBuffer[57],dataBuffer[58]}; short dataSize = byteArrayToShort(temp); if (T) Log.e(TAG,"decoded DataSize:"+dataSize); //THIS IS A HACK???? if(dataSize > DataPacket.DATA_MAX_SIZE || dataSize <0){ dataSize = DataPacket.DATA_MAX_SIZE; Log.e(TAG,"ERROR DATASIZE!!!! :"+dataSize); } if(dataSize>0){ ! ! ! ! ! 57
  • 64. bytesRead = instream.read (dataBuffer,DataPacket.HEADER_SIZE,dataSize); if (bytesRead != -1) { if (T) Log.e(TAG,"DatabyteRead:"+bytesRead); bytesRead2 = bytesRead; bufferSize = dataSize; while(bytesRead2 != bufferSize){ bufferSize = bufferSize - bytesRead2; bytesRead2 = instream.read (dataBuffer,DataPacket.HEADER_SIZE+bytesRead,bufferSize); if(T) Log.e(TAG,"insufficient bytes, reading:"+bytesRead2); bytesRead = bytesRead+bytesRead2; } } if(dataBuffer[0] != 1){ DataStream dataStream = new DataStream (address,dataBuffer); pktQueue.put(dataStream); dataStream = null; } else{ DataStream dataStream = new DataStream (address,dataBuffer,0); pktQueue.put(dataStream); dataStream = null; } } } //Clean up dataBuffer = null; r.gc(); } } catch (IOException e) { Log.i(TAG, "IOException in BtStreamWatcher - probably caused by normal disconnection", e); } ! ! ! ! ! 58
  • 65. // Getting out of the while loop means the connection is dead. try { synchronized(mBtLock){ mBtDeviceAddresses.remove(address); mBtSockets.remove(address); mBtStreamWatcherThreads.remove(address); } synchronized (recievedSeqNoWatcherLock){ recievedSeqNoWatcher.remove(address); } synchronized (seqNoWatcherLock){ seqNoWatcher.remove(address); } //to do inform other in network of connection lost DataPacket packet = new DataPacket(); packet.Dest = mDeviceAddress; packet.Src = mDeviceAddress; packet.Ctr = 3; packet.SeqNo = 125; packet.PktId = generatePacketId(mDeviceAddress); packet.data = address.getBytes(); packet.dataSize = (short) packet.data.length; //get Current network device List //reseting networkDevices = new HashMap<String,String>(); DataPacket queryPacket = new DataPacket(); queryPacket.Dest = mDeviceAddress; queryPacket.Src = mDeviceAddress; queryPacket.Ctr = 1; queryPacket.SeqNo = 125; queryPacket.PktId = generatePacketId (mDeviceAddress); synchronized(mBtLock){ for(int i=0; i< mBtDeviceAddresses.size(); i++){ sendPkt(packet,mBtDeviceAddresses.get(i)); sendPkt(queryPacket,mBtDeviceAddresses.get(i)); } } //inform webservice String results[] = webService.deviceConnectionLost(address); ! ! ! ! ! 59
  • 66. if(mMasterDevice.compareTo(address)==0){ mMasterDevice = ""; recoveryMode = true; recoveryDevicesList = new ArrayList(Arrays.asList (results)); } mCallback.connectionLost(address); } catch (RemoteException e) { Log.e(TAG, "RemoteException in BtStreamWatcher while disconnecting", e); } } public int sendPkt(DataPacket pkt,String target) throws RemoteException { try { String destination = target; BluetoothSocket myBsock; synchronized(mBtLock){ myBsock = mBtSockets.get(destination); } if (myBsock != null) { OutputStream outStream = myBsock.getOutputStream(); //pkt.HopCount = (byte) (pkt.HopCount+1); byte[] packetAsBytes = encrypt(pkt); outStream.write(packetAsBytes); if (T) Log.e(TAG,"sendPkt To:"+target+" Ctr:"+pkt.Ctr+" Src:" +pkt.Src+" Dest:"+pkt.Dest+" HopCount:"+pkt.HopCount+" ID:"+pkt.PktId); } else{ return Connection.FAILURE; } } catch (IOException e) { Log.i(TAG, "IOException in Forwarding packets", e); } return Connection.SUCCESS; } ! ! ! ! ! 60
  • 67. } private class PacketRouter implements Runnable{ private final BlockingQueue pktQueue; private ArrayList<DataPacket> queue; private Comparator<DataPacket> comperator = new Comparator<DataPacket>(){ @Override public int compare(DataPacket object1, DataPacket object2) { // TODO Auto-generated method stub if(object1.SeqNo == object2.SeqNo){ return 0; } else if((object1.SeqNo - object2.SeqNo) <0){ return -1; } else{ return 1; } } }; PacketRouter(BlockingQueue q){ pktQueue = q; queue = new ArrayList<DataPacket>(); } /* (non-Javadoc) * @see java.lang.Runnable#run() */ @Override public void run() { // TODO Auto-generated method stub while(true){ try { DataStream dataStream = (DataStream) pktQueue.take(); if (T) Log.e(TAG,"Read one dataStream :"+dataStream.seqNum); DataPacket pkt = new DataPacket(); ! ! ! ! ! 61
  • 68. pkt = decrypt(dataStream.data); routePacket(pkt,dataStream.address); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private void routePacket(DataPacket pkt, String address) throws RemoteException { if(!isPacketRepeated(pkt)){ if (T) Log.e(TAG,"ACCEPTED From:"+address+" Ctr:"+pkt.Ctr +" Src:" +pkt.Src+" Dest:"+pkt.Dest+" HC:"+pkt.HopCount+" ID:"+pkt.PktId+" Size:"+pkt.dataSize+" SN:"+pkt.SeqNo); byte request = 1; byte reply = 2; byte connectionLost = 3; if(mDeviceAddress.compareTo(pkt.Dest) ==0){ if (T) Log.e(TAG,"Packet reach Dest!"); if(pkt.Ctr==reply){ if (T) Log.e(TAG,"Control packet Received!"); if(!networkDevices.containsKey(pkt.Src)){ if (T) Log.e(TAG,"Found device:"+pkt.Src); String name = new String(pkt.data, 0,pkt.data.length); networkDevices.put(pkt.Src, name); Intent i = new Intent (ConnectionService.NEW_NETWORK_DEVICE_FOUND); i.putExtra (ConnectionService.DEVICE_ADDR, pkt.Src); ! ! ! ! ! 62
  • 69. i.putExtra (ConnectionService.DEVICE_NAME, name); Log.e(TAG,"SendBroadCast"); sendBroadcast(i); } } else{ byte missingPkt; synchronized (recievedSeqNoWatcherLock){ if(recievedSeqNoWatcher.containsKey (pkt.Src)){ missingPkt = recievedSeqNoWatcher.get(pkt.Src); } else{ missingPkt = 0; recievedSeqNoWatcher.put(pkt.Src, missingPkt); } } if(pkt.SeqNo != missingPkt){ Log.e(TAG,pkt.Src+": "+missingPkt+" MISSING!, adding"+pkt.SeqNo); queue.add(pkt); Collections.sort(queue,comperator); } else{ Log.e(TAG,pkt.Src+": "+missingPkt+" Found!"); mCallback.messageReceived(pkt.Src, pkt.data); missingPkt++; if(missingPkt>100){ missingPkt = 0; } synchronized (recievedSeqNoWatcherLock){ recievedSeqNoWatcher.remove(pkt.Src); recievedSeqNoWatcher.put(pkt.Src, missingPkt); } int index = queue.size(); ! ! ! ! ! 63
  • 70. for(int i = 0; i<queue.size();i++){ if(queue.get(i).SeqNo == missingPkt){ index =i; } } //if not found index = queue.size; while(true){ if(index == queue.size()){ //missing pkt not found break; } Log.e(TAG,pkt.Src+": "+missingPkt+" Release Found!"); missingPkt = (byte) (queue.get (index).SeqNo+1); if(missingPkt>100){ missingPkt = 0; } synchronized (recievedSeqNoWatcherLock){ recievedSeqNoWatcher.remove (pkt.Src); recievedSeqNoWatcher.put(pkt.Src, missingPkt); } DataPacket temp = queue.remove(index); mCallback.messageReceived (temp.Src,temp.data); index = queue.size(); for(int i = 0; i<queue.size();i++){ if(queue.get(i).SeqNo == missingPkt){ index =i; } } } ! ! ! ! ! 64
  • 71. } } } else{ if(pkt.Ctr==request || pkt.Ctr == connectionLost){ if (T) Log.e(TAG,"Control packet Received!,"+pkt.Ctr); DataPacket packet = new DataPacket (); if(pkt.Ctr == request){ //Send message to dest. packet.Dest = pkt.Dest; packet.Src = mDeviceAddress; packet.PktId = generatePacketId (mDeviceAddress); packet.Ctr = reply; packet.dataSize = (short) mDeviceName.length(); packet.data = mDeviceName.getBytes(); packet.HopCount = pkt.HopCount; boolean contains; synchronized (mBtLock){ contains = mBtDeviceAddresses.contains(packet.Dest); } if(contains){ if (T) Log.e(TAG,"Reply connected"); sendPkt(packet,packet.Dest); } else{ if (T) Log.e(TAG,"Reply to Source!"); sendPkt(packet,address); } } else{ String deviceLost =new String(pkt.data, 0,pkt.dataSize); ! ! ! ! ! 65
  • 72. //no need to check for mMasterDevice lost. mCallback.connectionLost(deviceLost); synchronized (recievedSeqNoWatcherLock) { if (recievedSeqNoWatcher.containsKey(deviceLost)){ recievedSeqNoWatcher.remove(deviceLost); } } synchronized (seqNoWatcherLock){ if(seqNoWatcher.containsKey (deviceLost)){ seqNoWatcher.remove (deviceLost); } } } synchronized (mBtLock){ if (T) Log.e(TAG,"mBtDeviceAddress size:"+mBtDeviceAddresses.size()); if (T) Log.e(TAG,"mBtDeviceAddress Addr:"+mBtDeviceAddresses.get(0)); if (T) Log.e(TAG,"mBtDeviceAddress Addr:"+mBtDeviceAddresses.get(0).compareTo(address)); if (T) Log.e(TAG,"mBtDeviceAddress Addr:"+mBtDeviceAddresses.get(0).compareTo(pkt.Dest)); //forward to all peers other than the one who u just replied to. for (int i = 0; i < mBtDeviceAddresses.size (); i++) { if(mBtDeviceAddresses.get (i).compareTo(address) != 0 && mBtDeviceAddresses.get (i).compareTo(pkt.Dest) != 0){ //nodes that u have not replied to if (T) Log.e (TAG,"Forwarding to Peer:"); sendPkt (pkt,mBtDeviceAddresses.get(i)); ! ! ! ! ! 66
  • 73. } } } //clean up packet = null; } else{ if(pkt.HopCount < 10){ forwardPkt(pkt,address); } else{ //do nothing, dun forward. } } } } else{ if (T) Log.e(TAG,"Rejected From:"+address+" Ctr:"+pkt.Ctr+" Src:" +pkt.Src+" Dest:"+pkt.Dest+" HC:"+pkt.HopCount+" ID:"+pkt.PktId+" Size:"+pkt.dataSize+" SN:"+pkt.SeqNo); } } public int sendPkt(DataPacket pkt,String target) throws RemoteException { try { String destination = target; BluetoothSocket myBsock; synchronized (mBtLock){ myBsock = mBtSockets.get(destination); } if (myBsock != null) { OutputStream outStream = myBsock.getOutputStream(); pkt.HopCount = (byte) (pkt.HopCount+1); byte[] packetAsBytes = encrypt(pkt); outStream.write(packetAsBytes); if (T) Log.e(TAG,"sendPkt To:"+target+" Ctr:"+pkt.Ctr+" Src:" ! ! ! ! ! 67
  • 74. +pkt.Src+" Dest:"+pkt.Dest+" HopCount:"+pkt.HopCount+" ID:"+pkt.PktId); } else{ return Connection.FAILURE; } } catch (IOException e) { Log.i(TAG, "IOException in Forwarding packets", e); } return Connection.SUCCESS; } public int forwardPkt(DataPacket pkt, String Source) throws RemoteException { synchronized (mBtLock){ for (int i = 0; i < mBtDeviceAddresses.size(); i++) { try { if(mBtDeviceAddresses.get(i).compareTo(Source)!=0){ // dun forward back to source String destination = mBtDeviceAddresses.get(i); BluetoothSocket myBsock = mBtSockets.get (destination); if (myBsock != null) { OutputStream outStream =myBsock.getOutputStream (); pkt.HopCount++; byte[] packetAsBytes = encrypt(pkt); DataPacket test = decrypt(packetAsBytes); if (T) Log.e(TAG,"Forwarding To:"+destination+" Ctr:"+test.Ctr+" Src:" +test.Src+" Dest:"+test.Dest+" HopCount:"+test.HopCount+" ID:"+test.PktId+" dataSize:"+test.dataSize); outStream.write(packetAsBytes); if (T) Log.e(TAG,"Forwarding To:"+destination+" Ctr:"+pkt.Ctr+" Src:" +pkt.Src+" Dest:"+pkt.Dest+" HopCount:"+pkt.HopCount+" ID:"+pkt.PktId+" dataSize:"+pkt.dataSize); ! ! ! ! ! 68
  • 75. //Clean up packetAsBytes = null; //pkt = null; r.gc(); } else{ return Connection.FAILURE; } } } catch (IOException e) { Log.i(TAG, "IOException in Forwarding packets", e); } } return Connection.SUCCESS; } } } private class ConnectionWaiter implements Runnable { private String srcApp; private int maxConnections; public ConnectionWaiter(String theApp, int connections) { srcApp = theApp; maxConnections = connections; } @Override public void run() { try { for (int i = 0; i < Connection.MAX_SUPPORTED && maxConnections > 0; i++) { BluetoothServerSocket myServerSocket = mBtAdapter .listenUsingRfcommWithServiceRecord(srcApp, mUuid.get(i)); BluetoothSocket myBSock = myServerSocket.accept(); String address = myBSock.getRemoteDevice().getAddress(); boolean contains; synchronized (mBtLock){ contains = mBtSockets.containsKey(address); } while(contains){ ! ! ! ! ! 69
  • 76. Log.e(TAG,address+" Already connected"); mHandler.obtainMessage(0, address+" Already Connected").sendToTarget (); myBSock = myServerSocket.accept(); } myServerSocket.close(); // Close the socket now that a proper // connection has been made. synchronized (mBtLock){ mBtSockets.put(address, myBSock); mBtDeviceAddresses.add(address); } Thread mBtStreamWatcherThread = new Thread(new BtStreamWatcher(address)); mBtStreamWatcherThread.start(); synchronized (mBtLock){ mBtStreamWatcherThreads.put(address, mBtStreamWatcherThread); if (T) Log.e(TAG, "Listen Add btDevice:"+address+" Device count:"+mBtDeviceAddresses.size()); if (T) Log.e(TAG, "Listen Add BtStreamThread:"+address+" BtStreamThread count:"+mBtStreamWatcherThreads.size()); } maxConnections = maxConnections - 1; //inform webservice webService.deviceConnected(mDeviceAddress, address); if (mCallback != null) { mCallback.incomingConnection(address); } } if (mCallback != null) { mCallback.maxConnectionsReached(); } } catch (IOException e) { Log.i(TAG, "IOException in ConnectionService:ConnectionWaiter", e); } catch (RemoteException e) { Log.e(TAG, "RemoteException in ConnectionService:ConnectionWaiter", e); } } } private class GPSListener implements Runnable { private UseGPS GPS; ! ! ! ! ! 70
  • 77. private Location GeoCoordinate; public GPSListener() { GPS = new UseGPS(mSelf); GeoCoordinate = null; } @Override public void run() { while(true){ try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } GeoCoordinate = GPS.returnCoordinates(); if(GeoCoordinate!=null){ mGeoCoordinate = GeoCoordinate; Log.e(TAG,"Got Reading:"+GeoCoordinate.getLatitude() +" ,"+GeoCoordinate.getLongitude()); if(mAutoConnect && mMasterDevice=="" &&!recoveryMode){ mHandler.obtainMessage(0, "Attempting to AutoConnect, Searching...").sendToTarget(); Log.e(TAG,"LAT:"+GeoCoordinate.getLatitude()); double geoY = GeoCoordinate.getLatitude(); Log.e (TAG,"LONG:"+GeoCoordinate.getLongitude()); double geoX = GeoCoordinate.getLongitude(); RegisterDeviceResult[] result = webService.registerDevice (mDeviceAddress, geoX, geoY); if(mAutoConnect){ boolean connectSucceed = false; if(result !=null){ for( RegisterDeviceResult value: result){ if (value.hardwareId.compareTo(mDeviceAddress)!=0){ ! ! ! ! ! 71
  • 78. Log.e(TAG,"Auto connecting to "+value.hardwareId); mHandler.obtainMessage(0, "Connecting to "+value.hardwareId).sendToTarget(); //Toast.makeText (mSelf, "Connecting to "+value.hardwareId, 1).show(); try { if(connect ("AutoConnect",value.hardwareId)==Connection.SUCCESS){ connectSucceed = true; webService.deviceConnected(value.hardwareId, mDeviceAddress); mMasterDevice = value.hardwareId; break; } } catch (RemoteException e) { // TODO Auto- generated catch block e.printStackTrace(); } } } } else{ mHandler.obtainMessage(0, "Unable to a response from webservice").sendToTarget(); //Toast.makeText(mSelf, "Unable to a response from webservice", 1).show(); } if(!connectSucceed){ if((result.length==0) || (result [0].hardwareId.compareTo(mDeviceAddress)==0 && result.length==1 ) ){ ! ! ! ! ! 72
  • 79. mHandler.obtainMessage(0, "No available Cluster found").sendToTarget(); //Toast.makeText(mSelf, "No available Cluster found", 1).show(); } else{ mHandler.obtainMessage(0, "AutoConnection Unsucessful").sendToTarget(); //Toast.makeText(mSelf, "AutoConnection Unsucessful", 1).show(); } } //try again 1 min later. try { Thread.sleep (1*60*1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } if(recoveryMode){ //Recovering from lost Masterconnection for( String value: recoveryDevicesList){ if(!networkDevices.containsKey(value) && value! =null){ //not in current networkDevices Log.e(TAG,"Recovery connecting to "+value); mHandler.obtainMessage(0, "Recovery Connecting to "+value).sendToTarget(); //Toast.makeText(mSelf, "Connecting to "+value.hardwareId, 1).show(); try { if(connect ("AutoConnect",value)==Connection.SUCCESS){ webService.deviceConnected(value, mDeviceAddress); ! ! ! ! ! 73
  • 80. mMasterDevice = value; break; } } catch (RemoteException e) { // TODO Auto- generated catch block e.printStackTrace(); } } } recoveryMode = false; } } } } public int connect(String srcApp, String device) throws RemoteException { // if (mApp.length() > 0) { // Log.e(TAG, "Return failure"); // return Connection.FAILURE; // } synchronized (mBtLock){ if(mBtSockets.containsKey(device)){ mHandler.obtainMessage(0, "Already connected to "+device).sendToTarget(); return Connection.FAILURE; } } mApp = srcApp; BluetoothDevice myBtServer = mBtAdapter.getRemoteDevice(device); BluetoothSocket myBSock = null; for (int i = 0; i < Connection.MAX_SUPPORTED && myBSock == null; i++) { for (int j = 0; j < 3 && myBSock == null; j++) { myBSock = getConnectedSocket(myBtServer, mUuid.get(i)); if (myBSock == null) { try { Thread.sleep(200); } catch (InterruptedException e) { Log.e(TAG, "InterruptedException in connect", e); ! ! ! ! ! 74
  • 81. } } } } if (myBSock == null) { return Connection.FAILURE; } synchronized (mBtLock){ mBtSockets.put(device, myBSock); mBtDeviceAddresses.add(device); if (T) Log.e(TAG, "Connect Add btDevice:"+device+" Devicesss count:"+mBtDeviceAddresses.size()); } Thread mBtStreamWatcherThread = new Thread(new BtStreamWatcher(device)); mBtStreamWatcherThread.start(); synchronized (mBtLock){ mBtStreamWatcherThreads.put(device, mBtStreamWatcherThread); if(T) Log.e(TAG,"Adding new threads"); if (T) Log.e(TAG, "Listen Add BtStreamThread:"+device+" BtStreamThread count:"+mBtStreamWatcherThreads.size()); } mMasterDevice = device; return Connection.SUCCESS; } } private BluetoothSocket getConnectedSocket(BluetoothDevice myBtServer, UUID uuidToTry) { BluetoothSocket myBSock; try { myBSock = myBtServer.createRfcommSocketToServiceRecord(uuidToTry); myBSock.connect(); return myBSock; } catch (IOException e) { Log.i(TAG, "IOException in getConnectedSocket", e); } return null; } ! ! ! ! ! 75
  • 82. private final IConnection.Stub mBinder = new IConnection.Stub() { @Override public int startServer(String srcApp, int maxConnections, boolean AutoConnect) throws RemoteException { // if (mApp.length() > 0) { // return Connection.FAILURE; // } // mApp = srcApp; mAutoConnect = AutoConnect; (new Thread(new ConnectionWaiter(srcApp, maxConnections))).start(); (new Thread(new GPSListener())).start(); //GPS //start discoverable Intent i = new Intent(); i.setClass(mSelf, StartDiscoverableModeActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(i); return Connection.SUCCESS; } @Override public int connect(String srcApp, String device) throws RemoteException { // if (mApp.length() > 0) { // Log.e(TAG, "Return failure"); // return Connection.FAILURE; // } synchronized (mBtLock){ if(mBtSockets.containsKey(device)){ mHandler.obtainMessage(0, "Already connected to "+device).sendToTarget(); return Connection.FAILURE; } } mApp = srcApp; BluetoothDevice myBtServer = mBtAdapter.getRemoteDevice(device); BluetoothSocket myBSock = null; for (int i = 0; i < Connection.MAX_SUPPORTED && myBSock == null; i++) { for (int j = 0; j < 3 && myBSock == null; j++) { myBSock = getConnectedSocket(myBtServer, mUuid.get(i)); if (myBSock == null) { try { ! ! ! ! ! 76
  • 83. Thread.sleep(200); } catch (InterruptedException e) { Log.e(TAG, "InterruptedException in connect", e); } } } } if (myBSock == null) { return Connection.FAILURE; } synchronized (mBtLock){ mBtSockets.put(device, myBSock); mBtDeviceAddresses.add(device); if (T) Log.e(TAG, "Connect Add btDevice:"+device+" Device count:"+mBtDeviceAddresses.size()); } Thread mBtStreamWatcherThread = new Thread(new BtStreamWatcher(device)); mBtStreamWatcherThread.start(); synchronized (mBtLock){ mBtStreamWatcherThreads.put(device, mBtStreamWatcherThread); if (T) Log.e(TAG, "Listen Add BtStreamThread:"+device+" BtStreamThread count:"+mBtStreamWatcherThreads.size()); } mMasterDevice = device; return Connection.SUCCESS; } @Override public int broadcastMessage(String srcApp,String destination, byte[] message) throws RemoteException { // if (!mApp.equals(srcApp)) { // return Connection.FAILURE; if (T) Log.e(TAG,"BroadCasting"); byte zero = 0; String dest; byte seqNo = 0; synchronized (mBtLock){ for (int i = 0; i < mBtDeviceAddresses.size(); i++) { if(destination == ""){ dest = mBtDeviceAddresses.get(i); ! ! ! ! ! 77
  • 84. } else{ dest = destination; } //for broadcasting, seqNo should not increase. if(destination ==""){ //sending to everyone if(sendByte(zero,mBtDeviceAddresses.get(i),dest,message,false) ==Connection.FAILURE){ return Connection.FAILURE; } } else{ //sendint to a specific target if(i ==0){//first packet if(sendByte(zero,mBtDeviceAddresses.get (i),dest,message,false)==Connection.FAILURE){ return Connection.FAILURE; } } else{//subsequence packet is the same seqNo if(sendByte(zero,mBtDeviceAddresses.get (i),dest,message,true)==Connection.FAILURE){ return Connection.FAILURE; } } } // if(i ==0){ // if(sendByte(zero,mBtDeviceAddresses.get(i),dest,message,false) ==Connection.FAILURE){ // return Connection.FAILURE; // } // // } // else{ // if(sendByte(zero,mBtDeviceAddresses.get(i),dest,message,true) ==Connection.FAILURE){ // return Connection.FAILURE; // } // } } } ! ! ! ! ! 78
  • 85. return Connection.SUCCESS; } public int broadcastPacket(DataPacket pkt) throws RemoteException{ if (T) Log.e(TAG,"PacketBroadCasting"); synchronized (mBtLock){ for (int i = 0; i < mBtDeviceAddresses.size(); i++) { if(sendPacket(pkt,mBtDeviceAddresses.get(i))==Connection.FAILURE){ return Connection.FAILURE; } } } return Connection.SUCCESS; } @Override public String getConnections(String srcApp) throws RemoteException { if (!mApp.equals(srcApp)) { return ""; } String connections = ""; synchronized (mBtLock){ for (int i = 0; i < mBtDeviceAddresses.size(); i++) { connections = connections + mBtDeviceAddresses.get(i) + ","; } } return connections; } @Override public int getVersion() throws RemoteException { try { PackageManager pm = mSelf.getPackageManager(); PackageInfo pInfo = pm.getPackageInfo(mSelf.getPackageName(), 0); return pInfo.versionCode; } catch (NameNotFoundException e) { Log.e(TAG, "NameNotFoundException in getVersion", e); } return 0; } @Override public int registerCallback(String srcApp, IConnectionCallback cb) throws RemoteException { // if (!mApp.equals(srcApp)) { ! ! ! ! ! 79
  • 86. // return Connection.FAILURE; // } mCallback = cb; return Connection.SUCCESS; } public int sendPacket(DataPacket pkt,String target) throws RemoteException { try { String destination = target; BluetoothSocket myBsock; synchronized (mBtLock){ myBsock = mBtSockets.get(destination); } if (myBsock != null) { OutputStream outStream = myBsock.getOutputStream(); pkt.HopCount = (byte) (pkt.HopCount + 1); byte[] packetAsBytes = encrypt(pkt); outStream.write(packetAsBytes); if (T) Log.e(TAG,"SendPacket To:"+destination+" Ctr:"+pkt.Ctr+" Src:" +pkt.Src+" Dest:"+pkt.Dest+" HC:"+pkt.HopCount+" ID:"+pkt.PktId+" SN:"+pkt.SeqNo); //Clean up packetAsBytes = null; pkt = null; r.gc(); return Connection.SUCCESS; } } catch (IOException e) { Log.i(TAG, "IOException in Forwarding packets", e); } return Connection.FAILURE; } //Only 1mb of data can be send including 57byte of header, 17src, 17dest,21 pktId, 2 hop count, 967 data public int sendByte(byte Ctr,String target ,String destination, byte[] data, boolean offSeqNo) ! ! ! ! ! 80
  • 87. throws RemoteException { try { if (D) Log.e(TAG,"Free memory at SendByte: "+r.freeMemory()); if(data.length > DataPacket.DATA_MAX_SIZE){ Log.e(TAG,"Data should not exceed"+DataPacket.DATA_MAX_SIZE+"byte!"); return Connection.FAILURE; } BluetoothSocket myBsock = mBtSockets.get(target); if (myBsock != null) { OutputStream outStream = myBsock.getOutputStream(); DataPacket packet = new DataPacket(); byte seqNo =0; if(Ctr != 0){ seqNo = 125; } else{ synchronized(seqNoWatcherLock){ if(seqNoWatcher.containsKey(destination)){ seqNo = seqNoWatcher.get(destination); if(!offSeqNo){ seqNo = (byte)(seqNo +1); if(seqNo >100){ seqNo = 0; } seqNoWatcher.remove(destination); seqNoWatcher.put(destination, seqNo); } } else{ seqNoWatcher.put(destination, seqNo); } } } packet.SeqNo = seqNo; packet.Ctr = Ctr; packet.Src = mDeviceAddress; ! ! ! ! ! 81
  • 88. packet.Dest = destination; packet.PktId = generatePacketId(mDeviceAddress); //packet.PktId = mDeviceAddress+"1234"; packet.dataSize = (short) data.length; //packet.data = joinByteArray(data," ".getBytes()); packet.data = data; byte[] packetAsBytes = encrypt(packet); outStream.write(packetAsBytes); if (T) Log.e(TAG,"SendBtye To:"+target+" Ctr:"+packet.Ctr+" Src:" +packet.Src+" Dest:"+packet.Dest+" HC:"+packet.HopCount+" ID:"+packet.PktId+" SN:"+packet.SeqNo); //Clean up packetAsBytes = null; packet = null; data = null; destination = null; target = null; outStream.flush(); outStream =null; myBsock = null; r.gc(); return Connection.SUCCESS; } } catch (IOException e) { Log.i(TAG, "IOException in sendMessage - Dest:" + destination + ", Msg:" + data.toString(), e); } return Connection.FAILURE; } @Override public int sendMessage(String srcApp, String destination, byte[] message) throws RemoteException { if(message ==null){ Log.e(TAG,"Unable to Send NULL byte Message"); return Connection.FAILURE; } ! ! ! ! ! 82
  • 89. // Location test = GPS.returnCoordinates(); // if(mGeoCoordinate != null) { Log.e(TAG,"LAT:"+mGeoCoordinate.getLatitude()); Log.e(TAG,"LONG:"+mGeoCoordinate.getLongitude()); } else { Log.e(TAG,"location is null"); } byte zero = 0; synchronized (mBtLock){ if(mBtDeviceAddresses.size() == 0) return Connection.FAILURE; } boolean contains; synchronized (mBtLock){ contains = mBtDeviceAddresses.contains(destination); } if(contains){ return sendByte(zero,destination,destination,message,false); } else{ return broadcastMessage("",destination,message); } } @Override public void shutdown(String srcApp) throws RemoteException { try { synchronized (mBtLock){ for (int i = 0; i < mBtDeviceAddresses.size(); i++) { BluetoothSocket myBsock = mBtSockets.get(mBtDeviceAddresses.get(i)); myBsock.close(); } mBtSockets = new HashMap<String, BluetoothSocket>(); mBtStreamWatcherThreads = new HashMap<String, Thread>(); mBtDeviceAddresses = new ArrayList<String>(); mApp = ""; ! ! ! ! ! 83
  • 90. mAutoConnect = false; mMasterDevice =""; recoveryMode = false; } } catch (IOException e) { Log.i(TAG, "IOException in shutdown", e); } } @Override public int unregisterCallback(String srcApp) throws RemoteException { // if (!mApp.equals(srcApp)) { // return Connection.FAILURE; // } mCallback = null; return Connection.SUCCESS; } @Override public HashMap<String,String> getDevices(){ //List<String> devices = new ArrayList<String>(); if (T) Log.e(TAG,"Getting devices!"); //reseting networkDevices = new HashMap<String,String>(); //fire signal to get reply DataPacket packet = new DataPacket(); packet.Dest = mDeviceAddress; packet.Src = mDeviceAddress; packet.Ctr = 1; packet.SeqNo = 125; packet.PktId = generatePacketId(mDeviceAddress); try { broadcastPacket(packet); } catch (RemoteException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } //Clean up packet = null; return networkDevices; ! ! ! ! ! 84
  • 91. // try // { // Thread.sleep(3000); // do nothing for 1000 miliseconds (3 second) // } // catch(InterruptedException e) // { // e.printStackTrace(); // } // // return networkDevicesAddresses; } @Override public String getAddress() throws RemoteException { return mBtAdapter.getAddress(); } @Override public String getName() throws RemoteException { return mBtAdapter.getName(); } }; } ! ! ! ! ! 85