Your SlideShare is downloading. ×
  • Like
FYP%3A+P2P+Bluetooth+Communication+Framework+on+Android%0A
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Now you can save presentations on your phone or tablet

Available for both IPhone and Android

Text the download link to your phone

Standard text messaging rates apply

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

  • 617 views
Published

 

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
617
On SlideShare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
34
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 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 INTRODUCTION1.1 Background Figure 1: U.S Smartphone Penetration & ProjectionsIn 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 amobile phone “that offers more advanced computing ability and connectivity than acontemporary feature phone”(Nusca 2009). As seen in Figure 1, the high growth rate of thesedevices bring about many opportunities for entrepreneurs and developer to leverage on the extracomputing and communication power of these devices. However, the high growth rate of thesedata hungry devices is not without it problems.! ! !! ! 1
  • 8. 1.2 ProblemsThe suddenly increase in the demand for mobile data bandwidth brought by these devices tookmany mobile network providers by surprise. Many of these network providers relies heavily ontraditional network architectures that are not designed to handles these kinds of trafficsrequirements. As network infrastructure expands takes times and also a huge amount of capitalinvestment, network outrages are common for smartphone users and thus in many ways limitingthe capabilities of these devices.1.3 MotivationAt such there is a need to redesign the current network architectures to allow for greater networkscalability and more importantly a lower infrastructure cost for each additional devices(clients)added to the network.1.4 ObjectiveThe objectives of the projects are therefore to explore and experiment on other means of networkinfrastructures 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 CasesFigure 2 shows how the framework can serve as an support to the current mobile communicationarchitecture. By leveraging on the Peer-to-Peer capability of the framework, the network stresson the traditional Architecture can be greatly reduced. Figure 2: Mobile P2P NetworkSome 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 ApproachIn 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-Peerone based on a modified Gnutella Peer-to-Peer architecture. Due to the ease of implementationand also the ability to reach a wider open-source community, the Open-Source AndroidOperating System for mobile devices is adopted as the platform for this frameworkimplementation. Extra efforts were also put in to the architecture design so that it would notrequire a “Rooted” android device. By doing so, the author hopes that it would be moreappropriate for mass-market adoptions.1.7 Assumption and LimitationDue to the time constraints and also hardware limitations, the framework currently only relies onbluetooth for it’s Peer-to-Peer communications(Chapter 3). This in turn means that theframework is currently limited by the hardware capability of of the bluetooth chipsets. At thetime of this writing, majority of the android devices available in the market is still usingBluetooth 2.1 + EDR, with some newer devices supporting Bluetooth 3.0. At such, testing andperformance 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 Android2.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 One1.8 Results of Implementation and ExperimentAn Open Source Peer-to-Peer framework focusing on Bluetooth Communication has beenimplemented on Android O.S.It comprises of the following Key Features:- No Rooting RequiredThe framework does not required developer/users to “root” their android phones in order to useit’s features. It’s is designed to work off the shelf and integrates easily with other existingprojects. It leverage on the Android Interface Definition Language(AIDL) to provide a clean andeasy to integrate interface for developer to work with.- Packet RoutingAll devices connected to a network clusters double up as router for the network. Once a devicehas been connected successfully to a device within a network cluster, it can communicatedirectly with any nodes in the network.- No need for a centralized indexing serverThe framework implements a modified “Gnutella” P2P network. This means that the network ispurely decentralized and does not require an indexing server. Through the use of Query Floodingtechniques, similar to that found in classic “Gnutella” P2P network, a device would be able tocommunicated with any node within the network.- Flow ControlAs every device double up as a router within the network, it is crucial that flow control isimplemented 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-ConnectionThis is an experimental features of the framework. Due to the security limitation(Chapter 3) ofthe 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 withit. To overcome this, an indexing server is implemented to allow devices to query for nearbydevices in which they can connect to and form a network. Using geo-location informationcoming from the devices, the server would suggest a list of devices in which the device canconnect to. Suggestion are made so that the bluetooth Scatter net topology is maintained.- Open-SourceThis 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 whichdemonstrates the Apis capabilities of the framework.A Peer-to-Peer network mutiplayer game based on the framework developed by the authortogether with a good of android enthusiasts can also be found.- Performance MetricsAccording to the experimental measurements obtained from the transferring of multiple Imagefiles of 350 - 380 kbytes, we observed that the throughput rate stabilizes at around 54Kbits/s fornodes that are more than 1 jump away from the original node. Figure 3 shows the throughput rateobtained from readings measured from these experiments.! ! !! ! 6
  • 13. 324#565789)6:8-6$ +!" *!" )!" (!" !" !"#$%&% &!" %!" $!" #!" !" !" !," #" #," $" $," %" %," &" &," ()*)+,)-$)./%0120)1 Figure 3: Maximum Throughput Rate1.9 Thesis LayoutIn Chapter 2, a literature review is done to find out the various alternative networkinginfrastructure that can be used to address the current problem and also meet the paper’sobjective. In Chapter 3, we would discuss and look into the various approaches and methodologyused in the implementation of this framework. Chapter 4, would than cover the implementationsoutcome and benchmark the performance of the framework. Chapter 5 would than discuss thelimitation 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 REVIEW2. 1 Server - Client Architecture Figure 4: Server-ClientFigure 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 applicationstructure that partitions task or workloads between the providers of resources or service, calledservers, and service requesters, called clients(Microsystem 2009). The clients and serverstypically communicated over a computer network on network hardware infrastructure providedby ISP. Due to the nature of it’s designs, additional network hardware infrastructures has to beadded in order to support additional capacity(clients).AdvantagesGreater Security assurance:Since data are stored on the servers, which generally have far greater security controls than mostclients. Server can also have better control access with resources, to guarantee that only thoseclients with the appropriate permissions may access and change data.With data storage being centralized , updates to any data are far easier to administer as comparedto other architecture like Peer-To-Peer one.! ! !! ! 8
  • 15. DisadvantagesA major disadvantages of a Server - Client architecture is that it does not scale well when there issudden increase in network traffic. Increase in network bandwidth require prior hardwareinfrastructure investment, which become a problem when there is a sudden increase in networkbandwidth requirement.The client-server architecture also lacks robustness as resources are all centralized, should acritical 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 architecturethat partition tasks or workloads between peers. Peers make a portion of their resources, such asprocessing 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(Scholmeier2002). The peer-to-peer application structure was popularized by file sharing systems likeNapster and Kazaa. Since it’s induction, many different architectural design from P2P networkhas been introduced. They are however generally classified into the below 4 approaches.2.2.1 Centralized Index Figure 6: Centralized IndexThis is the original “Napster” design. The design involved a centralized Index server whichregisters 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 regardingthe clients which holds the resource that it requires. The client will than establish an directconnection to the respective clients to get it’s required resources.! ! !! ! 10
  • 17. 2.2.2 Query flooding (Gnutella) Figure 7: Query FloodingQuery 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 holda list of all clients and resources available in the network. As shown in Figure 7, when a clientrequires a resources, it will send a query message to all nodes connected to it. Each node willthan forward the query message to all of it’s neighbors, hence coining the term “QueryFlooding”. QueryHit will than be sent over in the reverse path back to the client. A directconnection can than be established between the client and the node with the resource required. Apopular 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 OverlayA Hierarchical Overlay Design is a fusion of the Centralized Index and Query FloodingArchitecture Design. The design recognized that not all nodes within a Peer-to-Peer network areequal in term of bandwidth, availabilities and computational power. It therefore introduce theconcept of of “super peers” in the network which server as mini-index which keep track of all theresources 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 TelephonyApplication 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 lookupservice similar to that of a hash table. Key, value pairs are stored in a DHT and any participatingnode can efficiently retrieve the value associated with any given key. The responsibility formaintaining 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 whenthere is a change in the set of participants in the network.2.2.5 Advantages of Peer-to-Peer ArchitectureIn Peer-to-Peer network design, clients provide resources which include bandwidth, storagespace and computing power as it join an network. This allow the total capacity of the network toalso increases as an new node arrive in the network. This allows the network to be well adaptedto sudden increase in network bandwidth requirements. There is also little to no additional costto support an extra client added to the network.The distributed nature of Peer-to-Peer network also increases the robustness of network. For purePeer-to-Peer network like the Gnutella, Hierarchical Overlay and DHT designs, which enabledpeers to find the require resources without relying on a centralized index server, the networkrobustness was very much increase as there is no single point of failure in the architecture.2.2.6 Disadvantages of Peer-to-Peer ArchitectureDue to the nature of the network design , unsecured and unsigned codes may allow unauthorizedremote access to resource on a victims nodes and compromised the entire network.! ! !! ! 13
  • 20. 2.3 Server-Client Vs Peer-to-PeerTo better evaluate the performance of Server-Client network design versus that of a Peer-to-Peernetwork design, let us that a look at a typical network operation: File Distribution (Figure 6) Figure 9: Server Client Vs P2PObjective:- 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/usThe 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 capacityis 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 ClientsFigure 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 theno of clients. The MTD tends towards the maximum time of 1 hour, which is the maximum timetaken for the server to upload one file.2.4 Proposed ArchitectureIn conclusion, the literature review shows us that a Peer-to-Peer architecture design hassignificant advantage in terms of scalability and cost as compared to a traditional client-serverarchitecture design. This suit our requirement for a new architecture design. At such, theproposed framework would be based on a Peer-to-Peer that allows developers to build scalableapplications on top of it. In the next chapter, we would discuss in depth the implementation andits design decision.! ! !! ! 16
  • 23. CHAPTER 3 IMPLEMENTATION APPROACHES AND METHODOLOGY3.1 Platform Figure 11: Mobile O.S Market ShareFigure 11 shows the US smartphone market shares acquisitions rate for the different smartphoneoperating systems in a research done by Nielsen in 2010. As shown in the graph, we can see thatthe 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 softwaredevelopers.Indeed, the openness of the android framework allows developer to unleash the full potential of asmartphone which much more ease. At such, the author choose to use the android framework forthe purpose of this research paper due to potential(high market adoption rate) and also for itsease of implementation.! ! !! ! 17
  • 24. 3.2 Hardware choices and limitationsThe android platform offers a varieties of ways for devices to communicate between themselvesand with the rest of the world(internet). The fews choices that are available are:3.2.1 Bluetooth Figure 12: Bluetooth logoBluetooth™ is a proprietary open wireless technology standard for exchanging data over shortdistances from fixed and mobile devices. Creating personal area network(PANS) with high levelsof security. It uses a radio communication system and therefore do not requires a visual line ofsight between 2 devices for them communicate.Bluetooth™ uses a radio technology called frequency-hopping spread spectrum, which chops updata being sent and transmits chunks of it on up to 79 bands, 1MHz each, centered from 2402 to2480 MHZ in the range of 2400-2483.5MHZ.Bluetooth™ is a packet-based protocol with Master-slave structure. One master maycommunicate up to 7 slaves in a piconet at the same time, with all the devices sharing themaster’s clock. Packet exchange is based on the basic clock defined by the master which ticks at312.5 us intervals.A Bluetooth™ can switch role between a slave and master. This means that a slave device canbecome the master at any time. At any given time, data can be transferred between the masterand one other device, however it can rapidly switches between devices in round-robin fashionswith little over head.! ! !! ! 18
  • 25. Figure 13: Power Class chartThree power classes of Bluetooth™ exist in the market to address various use cases. Due to thelimited power available on mobile devices, most if not all android devices operate on Class 2chipset which limits it range to a 10 meters as shown in Figure 13 above. Figure 14: Version ChartSince it’s inception in 1994 by telecom vendor Ericsson(Wikipedia), Bluetooth™ has under wenta couple of revisions recorded in Figure 14. Each revision brings about different improvement interms 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. Mostandroids device found in the market comes with bluetooth chipsets 2.0 and above.! ! !! ! 19
  • 26. 3.2.2 Wireless Fidelity Figure 15: WiFi LogoWireless Fidelity or Wi-Fi for short is a wireless communication technology developed andcontrolled by the IEEE based on the IEEE 802.11 standards. It allowed a Wi-Fi enabled devicesuch as a personal computer or a mobile phone to communicate with other devices or connect tothe internet. This is usually achieve by having the Wi-Fi device connect to a network through aaccess points via a router.Direct device to device communication is also possible without the involvement of a accesspoint. This form of Wi-Fi communication is called the ad hoc mode. Figure 16: 802.11 protocolSince it induction in 1997(Wikipedia), the IEEE 802.11 protocol has under went many revisionsin 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 datatransfer rates.The Android Operation System supported Wi-Fi connectivity since it’s first release. Most of theandroid devices in the market today are still using the IEEE802.11 g protocols. The androidframework does not support ad hoc mode of Wi-Fi communication by default. Developer wouldneed to “root” their device to enable this feature.3.2.3 Mobile telecommunicationMobile telephony or telecommunication is the provision of telephone services to phones whichmay move around freely rather than stay fixed in one location. Mobile devices connect to aterrestrial cellular network of base station(cell towers) which allows them to communicatebetween one another or with the rest of the world(internet).Most of the world mobile telephone system is based on the Global System for MobileCommunication system, GSM in short.Beside the GSM, another popular mobile telephone system is based on the Code divisionMultiple Access system, CDMA in short.GSM system uses Time Division Multiple Access TMDA and Frequency Division MultipleAccess FDMA techniques to multiple phones in it’s network to communicate simultaneouslywhile the CDMA system employ Code Division Multiple Access techniques to achieve similargoals.3G or 3rd generation mobile telecommunication is a generation of standards for mobile phonesand mobile telecommunication services fulfilling the International MobileTelecommunications-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 serviceprovider. However, a typical 3G cellular network users can expect a minimum data rate of2Mbit/s for stationary or walking users to 384kbit/s in a moving vehicles according to IMT-2000specifications(IMT-2000 2000).Most android power devices in the market comes with 3G data supports. However, they usuallyrequires users to pay additional monthly fees to enjoy this features. At such, not all androiddevices will be able to use this form of communication easily.3.2.4 Design DecisionsAfter reviewing the different communication options that the android framework offers, itbecome clear that Bluetooth™ and Wi-Fi are more feasible choices as compared to mobiletelecommunication such as 3G due to it’s lower availability and more importantly, it’s lack ofoptions 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 themain form of inter-device communication for it’s first release.! ! !! ! 22
  • 29. 3.3 Network Design Figure 17: Scatter NetAs discussed previously in 3.1, Bluetooth™ is a packet-based protocol with Master-slavestructure. 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 Scatternet 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 needto find out which are the nodes in the network that contain the resource that it desires. Dependingon the network architectural, this is achieved by either by doing a query with some form of indexserver(Central Indexing, DHT, Hierarchical Overlay) or through Query Flooding (Gnutella).After the required information with regards to the nodes which contain the desired resource hasbeen acquired, the next time would be establish a direct connection to the respective nodes sothat 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 notbe possible. Taking that into account, a little modifications to the traditional Peer-to-Peernetwork design have to made.After the information with regards to the nodes which contains the desired resources has beenobtained, nodes within a bluetooth Peer-to-Peer scatternet/piconet has to assist in routing datapackets between the 2 nodes.Taking into the account of the framework design objectives of supporting ah-hoc networkcreation and the hardware limitation of the Bluetooth™ communication protocol, the authorfavored a modified version of the Gnutella Peer-to-Peer design as compared to the other designsdiscussed previously. Figure 18 : Data Packet DesignIn order to implement a Gnutella Peer-to-Peer network on a Bluetooth™ Scatter net, a 1024 bytesize data packet is used for data transmission between devices on the network. The data packetuses 60 bytes for header, leaving a dynamic data size of up to 964 bytes. Below is a break downof each field in the header.3.3.1 Control ByteThe first byte of the data packet is used to differentiate between a normal data packet and acontrol 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 addressThis field contains the 17 characters hardware MAC address of the bluetooth device which thepackets originated from.3.3.2 Destination addressThis field contains the 17 characters hardware MAC address of the bluetooth device which thepackets target at.3.3.3 Hop CountThis 1 byte contains the no of time the data packet has jumped across nodes in the network. Thisis necessary for Query Flooding technique to work in a Gnutella network. Current, the cap is 10count before the packet is no longer forwarded.3.3.4 Packet IdThis is a 21 characters string generated by joining the MAC address of the device which generatethe packet with 4 characters string generated from the system clock time. This allows repeatedpackets to be recognized and discard at each nodes and thus reducing unnecessary networktraffic and also repeat data at the destination node. The 4 characters string generated only repeatsonce every 10 seconds.3.3.5 Data SizeThis 2 bytes field contains the information regarding the size of the data field. This value canvaries from 1 to 964.3.3.6 Sequence NoThis is a 1-byte field that stores that Sequence No of a packet. Since the path taken by eachpackets to it’s destination might not be in order, this Sequence No will allow the destination nodeto rebuild the data in sequence. This value current varies from 0 - 99.! ! !! ! 25
  • 32. 3.4 Flow ControlSince packets has to be possibility routed across multiple nodes in the Scatter net before reachingit’s destination, there is a need to implement some form of schedule system/traffic policing toensure a certain level of Quality of Service(QoS). A traditional First-In-First-Out system wouldnot scale well under high network traffic condition, such as a scenario where by there is a largefile transfer between 2 devices in the network. If a traditional First-In-First-Out system isadopted. During the entire period of the file transfer operation, other devices in the networkwould experience low bandwidth thus affecting QoS. Let us look at some possible schedulesystem/traffic policing implementation.3.4.1 Priority Queuing Figure 19: Priority QueuingIn this approach, packets are classified into different priority classes & placed into differentqueues. Figure 19 shows an example implementation of this form of scheduling, The red packetsrepresented 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 QueuingThe round robin queuing is a scheduling mechanism that ensure that fair usage of betweendifferent 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 whenthere are still packets in any other queue. If a Class queue is empty, any Class queue which is notempty will immediately be processed. Figure 20 shows a graphic depiction of this method ofscheduling.3.4.3 Weighted Fair Queuing Figure 21: Weight Fair QueuingWeighted Fair Queuing is a generalized form of a Round Robin scheduling system. It differsfrom a normal round robin scheduling system by allowing each class to have a differentweighted amount of service in a cycle. Similar to a round-robin implementation, the WeightedFair Queuing can be made work-conserving by ensuring the link does not become idle whenthere 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 beguaranteed to received bandwidth equal to that of Eq(4).3.4.4 Leaky Bucket PolicerUnlike a scheduling technique, a policing approach regulate the traffic entering a networkaccording 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 aresent.Peak Rate:This control the network traffic by limiting the max number of packets allowed to be sent over ashort period of time.Maximum Burst Size:This control the network traffic by limiting the max number of packets allowed to be sent overan 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 policingcriteria. Figure 22 shows a graphical description of this policing technique. A “bucket” whichcan hold up to b tokens is first created. Tokens are than generated at the rate of r tokens/sec andadding to the “bucket”. If the bucket is full, newly generated token would be ignored. Before apacket is sent into the network, it must first remove an available token, when the bucket comesempty, 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 overany interval of time of length t. --- Eq(5) Figure 23: Data Rate! ! !! ! 29
  • 36. 3.4.5 Leaky Bucket Policer + Weighted Fair QueuingBy combining the two techniques, the technique can provides a guaranteed upper bound on delayand thus provide a QoS guarantee. Figure 24: LBP + WFQSuppose flow 1’s bucket is initially full, a burst of b1 packets can pass through & join theWeighted 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 decisionGiven the time constraints and also to reduce the complexity of the implementation, a WeightedFair Queueing scheduling technique is chosen as the flow control mechanism in the frameworkimplemented.! ! !! ! 30
  • 37. 3.5 AutoConnectionsIn order to prevent malicious activities to be perform on a user mobile devices via bluetoothconnectivity, the Android Operating System has put in place many security features to sure thatthe end uses will always be keep inform of activities perform via bluetooth. For example, thesystem requires user acknowledge when an application tried to turn on bluetooth connectivity orconnect to a device that it has not paired with before.Although, these security features may have help to increase the security of the android operatingservice, it has also hindered the many possible innovations in Peer-to-Peer networking on theAndroid Operating System.The following two security features of the Android Operating System has been the majorhinderer of Peer-to-Peer networking innovations on Android Operating System so far.3.5.1 Unable to connect to new devices without user acknowledgementThe Android Bluetooth framework also requires 2 devices who have not been previouslyconnected before to undergo an “pairing” process before data is able to be transmitted betweenthem. This pairing process require both phone users to acknowledge a prompt from the systemwithin a short period of time before allowing the 2 devices to be connected. These makes itextremely difficult for a Peer-to-Peer network to be formed.3.5.2 Unable to make device always discoverableThe Android Bluetooth framework only allow a device to be “make discoverable” by otherdevices for a maximum period of 120 second at any given time. Therefore, the frameworkrequire users acknowledge each time to allow a device to “make discoverable” for another 120seconds. The inability for an device to “made discoverable” automatically and persistently makesit 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 devicesFor simplicity sake, the framework currently does not offer a solution to this. Users currently canonly 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 listeningto feedback from developers and making changes to the framework to meet their needs. In latestAndroid release of 2.3.3, the android framework has finally allow unsecured bluetoothcommunication to be established between 2 devices who has never been paired before withoutuser acknowledgement(2.3.3 2010).3.5.4 Geo-Location Indexing serverTo overcome the problem where by a device cannot be set to be always “discoverable” acentralized index server was developed to index the geo-location coordinate of the all mobiledevices on the network. Before connecting to the Peer-to-Peer network, a device would firstquery the centralized indexing server with it’s own Geo-location details to get informationregarding all the devices nearby. The central indexing server is thus responsible for maintain thebluetooth Scatter net formed by the devices.This is currently a temporary experimental solutions as the author believe that with open natureof the framework would see that a alternative would be provided from within the androidframework similar to the modification since previous in Android 2.3.3 release.! ! !! ! 32
  • 39. CHAPTER 4 IMPLEMENTATION RESULTS AND PERFORMANCE METRICS4.1 Key FeaturesAn Open Source Peer-to-Peer framework focusing on Bluetooth Communication has beenimplemented on Android O.S.It comprises of the following Key Features:4.1.1 No Rooting RequiredUnlike most open source Bluetooth application/framework out there, this framework does notrequired developer/users to “root” their android phones in order to use it’s features. It’s isdesigned to work off the shelf and integrates easily with other existing projects. It leverage onthe Android Interface Definition Language(AIDL) to provide a clean and easy to integrateinterface for developer work with. The author hope that by doing so, the framework would beable to have a much larger outreach and would allow it to collect more data from it’s centralindexing server which is used by it’s Auto connect feature.4.1.2 Packet RoutingAll devices connected to a network clusters double up as router for the network. Once a devicehas been connected successfully to a device within a network cluster, it can communicatedirectly with any nodes in the network. This feature allow ah-hoc network to form manually orautomatically between devices. This feature would enable developer to build many interestingapplication should as multi- user chat room and multiplayer games.4.1.3 No need for centralized indexing serverThe 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 Floodtechniques, similar to that found in classic “Gnutella” P2P network, a device would be able tocommunicated with any node within the network.4.1.4 Flow ControlAs every device double up as a router within the network, it is crucial that flow control isimplemented 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 ensurethat control packets has higher priority as compared to normal packet and while ensuring a fairdistribution of the network bandwidth between all the nodes in the network.4.1.5 Auto-ConnectionThis is an experimental features of this framework. Due to the security limitation(Chapter 3) ofthe 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 withit. To over this, an indexing server is implemented to allow devices to query for nearby devicesin which they can connect to and form a network. Using geo-location information coming fromthe 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-SourceThis 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 whichdemonstrates the Apis capabilities of the framework.! ! !! ! 34
  • 41. A Peer-to-Peer networking game based on the framework developed by the author together witha group of android enthusiasts can also be found.4.2 Performance MetricsAccording to the experimental measurements obtained from the transferring of multiple Imagefiles of 350 - 380 kbytes, we observed that the throughput rate stabilizes at around 54Kbits/s fornodes that are more than 1 mores away from the original node. Figure 3 shows the throughputrate obtained from read measure from these experiments. 324#565789)6:8-6$ +!" *!" )!" (!" !" !"#$%&% &!" %!" $!" #!" !" !" !," #" #," $" $," %" %," &" &," ()*)+,)-$)./%0120)1 Figure 3: Maximum Throughput RateThis transfer rate is acceptable for most of the uses proposal earlier. We would also like tohighlight that the test is conducted on Nexus one and HTC Desire Z devices which are usingBluetooth 2.0 chipset. With much high speed of Bluetooth 3.0 chipset(8 times faster than 2.0), itis believe that the performance of this framework could be much better.! ! !! ! 35
  • 42. CHAPTER 5 FRAMEWORK LIMITATION AND POSSIBLE FUTURE WORK5.1 Framework LimitationsThe first release of the framework aims to show a working prototype of an alternative mobilecommunication network based on Peer-to-Peer architectural. However, due to time constraintsand other external/internal factors, the frameworks does has a few limitation. The next fewparagraphs discuss some of them.5.1.1 Pairing between 2 devicesAs of the time of this writing, no android has released an official firmware upgrade which usesAndroid 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 beenpreviously paired. These still remain as the major limitation for the existing framework as ithinder automatic connection between 2 devices who have not been previously paired.5.1.2 Lack of securityThe current framework implementation did not encrypt the data packets in any way. This wouldmeans 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 forusage by data which are “confidential” in nature.5.1.3 Dependency on Geo-Location Indexing serverDue to the Android Bluetooth™ framework security limitation discussed in Chapter 3, thecurrently framework is unable to be fully decentralized and require am external indexing serverfor 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 connectionon the device.5.2 FutureWorkAfter reviewing the limitation of the current framework, the following future work is suggestedto be done:5.2.1 Server-less implementationTo allow the Peer-to-Peer network to be truly scalable, it’s dependency on the Geo-Locationindexing server has be to remove. Future work can be done to use Bluetooth scanning instead ofgeo-location position to determine which device a device should connect to. This would also belargely affected by the implementation changes from the Android framework itself.5.2.2 OptimizationThe current Framework adopted a Gnutella Peer-to-Peer architecture large due to it’s simplicityof implementation. In the next release of the framework, more work can be done to optimize andimprove the efficiency of the Peer-to-Peer framework. More efficient search and routingtechnique could be adopted to improve the data transfer speed of the current framework.5.2.3 SecurityAs discussed previously in the limitation of the framework, the current framework does notimplement any form of data encryption which cause the underlying network to be be anunsecured one. This made it a security risk and thus unsuitable for applications which containssensitive information to be developed on it. At such, it might be good for the next release to takethis into account and implement some form of data encryption to allow better data securitywithin the network.! ! !! ! 37
  • 44. CHAPTER 6 SUMMARY AND CONCLUSION6.1 Future of mobile communicationAs the computation power of mobile devices continue to increase and the cost of these devicescontinue to falls, the term “smartphone” would soon become a term of the past. All mobiledevices 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 higherbandwidth would definitely continue to increase at an exponential rate. At such there would be aneed for us to reconsider the current network infrastructure design to allow for better scalability.6.2 ConclusionIn this thesis paper, we had explored the different alternatives communication architecturaldesign that would allow the current mobile communication to scale better. The prototypeframework that was developed as part of this thesis provided us a platform to evaluate thefeasibility of using Peer-to-Peer communication between mobile devices as an alternative totraditional mobile communication method.From the result of the implementation, namely the success demonstrated in the multi-user chatapplication 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 analternative to support or even replace the current mobile communication architecture. With theincreasing adoption rate of the Android platform and also it’s recognition for the potential inPeer-to-Peer communication (revision 2.3.3), we can concluded that the future for Peer-to-Peercommunication on mobile devices is a bright one. The author hope that the framework developedin 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) throwsRemoteException { 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, OnMessageReceivedListeneromrListener, 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 normaldisconnection", 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 onedataStream :"+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) throwsRemoteException { 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,"Founddevice:"+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 notfound 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 packetReceived!,"+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,"Replyconnected"); sendPkt(packet,packet.Dest); } else{ if (T) Log.e(TAG,"Reply toSource!"); 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,"mBtDeviceAddresssize:"+mBtDeviceAddresses.size()); if (T) Log.e(TAG,"mBtDeviceAddressAddr:"+mBtDeviceAddresses.get(0)); if (T) Log.e(TAG,"mBtDeviceAddressAddr:"+mBtDeviceAddresses.get(0).compareTo(address)); if (T) Log.e(TAG,"mBtDeviceAddressAddr:"+mBtDeviceAddresses.get(0).compareTo(pkt.Dest)); //forward to all peers other than the one whou 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 notreplied 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+" Devicecount:"+mBtDeviceAddresses.size()); if (T) Log.e(TAG, "Listen Add BtStreamThread:"+address+" BtStreamThreadcount:"+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,"Autoconnecting 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, "Unableto a response from webservice").sendToTarget(); //Toast.makeText(mSelf, "Unable toa 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, "Noavailable 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) { // TODOAuto-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, "RecoveryConnecting 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+" Devicessscount:"+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+" BtStreamThreadcount:"+mBtStreamWatcherThreads.size()); } mMasterDevice = device; return Connection.SUCCESS; } } private BluetoothSocket getConnectedSocket(BluetoothDevice myBtServer, UUIDuuidToTry) { 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+" Devicecount:"+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+" BtStreamThreadcount:"+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) throwsRemoteException {// 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 hopcount, 967 data public int sendByte(byte Ctr,String target ,String destination, byte[] data, booleanoffSeqNo)! ! !! ! 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 notexceed"+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