1 6 NOV 2006 ~------------~ ~ - Repositorio UDEM

122
UDEM 16 NOV 2006 Recepción de Tesis \

Transcript of 1 6 NOV 2006 ~------------~ ~ - Repositorio UDEM

UDEM

1 6 NOV 2006

Recepción de Tesis ~

~------------~ ~

\

UNIVERSIDAD DE MONTERREY

DIVISIÓN DE ARQUITECTURA, DISEÑO E INGENIERÍA

({)tf.O . o O\ fo

9 l- ¿p p

2..00Co

P2P Personal Video Recorder Applications

PROGRAMA DE EVALUACIÓN FINAL QUE PRESENTA:

JOSE LUIS GARDUÑO GARCIA

en opción al título de :

LICENCIADO EN TECNOLOGIA DE LA INFORMACION

San Pedro Garza García, N. L. Septiembre, 2006

.. BIBLIOTE(:.\

UNIVERSIDAD DE MONTERREY

Dedicated

To my fathert, Jase Luis Garduño, who is m y inspiration and guide.

To my mother, Margarita Garcia, who has supported me al! my lite. To m y sister Monica and m y brother in law Luis Alfonso Ramirez.

Thanks

To Maitham AI-Essawi, Matthieu Godéré and Marcin Kot for doing this work with me.

To Simen Hagen and Oslo University College for supporting us in Norway.

To the University of Monterrey and it's professors: Marta Silvia del Rio, Luis Aceves,

Consuelo Jimenez, Ghassan Kahwati, Elizabeth Gutierrez, Lucia Maria Treviño and

specially to m y project supervisor Manuel Prieto de Hoyos for helping me from 8, 652Km away.

To Brenda Garcia and the staff of the lnternational Programmes department of UDEM for encouraging me to study abroad.

To Per-Steinar Hansen, Torb}0rn Sund and all the people working at Telenor R&D for hosting the project and for guiding us.

lng . Lucia Maria Treviño Villarreal

San Pedro, Garza Garcia, Nuevo Leon

19 of September of the year 2006

Director of the programme of the bachelor of information technology Architecture, Design and Engineering Division University of Monterrey

By means of this letter 1 confirm that 1 reviewed the final document of the project "P2P Personal Video Recorder Applications" in form and content. The document presented by the team of students formed by Jose Luis Garduño, Maitham AI-Essawi, Matthieu Godéré and Marcin Kot complies with all the qualities of execution and quality that the University of Monterrey requires; furthermore it satisfies the goals and reach established in the first draft authorized by the PEF committee at the beginning of the semester.

From my behalf, 1 am at your disposition for any question or doubt you might have.

Sincerely,

lng. anuel Prieto Hoyos Department of Computer Science

c.c.p. lng Alejandro Pozas G. c.c.p. Jose Luis Garduño

" telenor

Faculty of Architecture, Design and Engineering

FINAL EVALUATION PROJECT

TITLE:

P2P Personal Video Recorder Applications

MEMBERS OF PROJECT TEAM:

Maitham AI-Essawi, José Luis Garduño, Matthieu Godéré, Marcin Kot

PROJECT COMMISSIONED BY:

Telenor R&D

ABSTRACT:

DATE OF PROJECT START:

24 March 2006

DATE OF REPORT SUBMISSION:

Oslo: 31 May 2006 Monterrey: 04 Oct 2006 NUMBER OF PAGES:

11 o SUPERVISOR:

Manuel Prieto de Hoyos Simen Hagen

CONTACT PERSONS:

Per-Steinar Hansen Torbj0rn Sund

This document contains the results of our project on a peer-to-peer solution for sharing television content commissioned by the company Telenor ASA

Thanks to an Electronic Program Guide the users can select the shows they want to see, even if the content has already been broadcasted. A modified version of the Bit T orrent protocol allows a client to download shows recorded by other users. In addition a scheduler is provided to automate recordings on the client side.

INDEXTERMS

Peer-to-peer television

Broadcasting

Electronic Program Guide

Bit Torrent Protocol

Telenor

P2P PVR Applications

Preface

This report is the result of our work during the European Project Semester (EPS) conducted at Oslo University College during spring 2006. The EPS program gáthers students with different background from all over the world . Project management and methodology is taught and the students carry out a project in groups of tour for a client.

Our group was assigned todo a project for the company Telenor. Originally, we should have worked on AJAX with the college, but the company came to our supervisor Simen Hagen with a tapie for us. First, it was related to developing an IMS (IP Multimedia Subsystem) application, but dueto some technical restrictions and lack of software we moved on to another project: work on a peer-to-peer personal video recorder system. The project codename Springfield was chosen by the students after the names of the computers used during the project: Homer, Marge, Bart and Lisa.

We would really like to thank Oslo University College, the EPS coordinators Johnny Berre, Jorunn Fergus and Terje Harberg, the tutors David Swetnam, Agnes L. Hayman, Reidar Kvadsheim and the various lecturers.

We particularly thank our supervisor Simen Hagen for his support and advice all along the project, as well as Per-Steinar Hansen and Torbj0rn Sund from Telenor R&D.

P2P PVR Applications

Declaration of authenticity

This report is the result of group A's work and not copied from anyone. All used references are mentioned in the report.

Oslo University College, 31 May 2006

Maitham AI-Essawi

José Luis Garduño

Matthieu Godéré

Marcin Kot

P2P PVR Applications

Table of contents

1. INTRODUCTION ........................................................................................... 1

2. BACKGROUND ANO OBJECTIVES ............................................................ 3

2.1. INSTITUTIONS ....... ... ....... ...... ..... .. ....... ......... ..... .... .................... ... ........ ..... 3 2. 1. 1. Oslo University College - European Project Semester ... .... ................ 3 2.1.2. Telenor ......... ... ........ .. .... ... ... .......... .... .. .... .. .. ..... ... .. ..... .. ...... .. ... ... .. ... .... 3

2.2. CONTRIBUTORS ....... . .... ........ . .......... ..... .. .... ...... ..... ... .. .... . ... .... ... ..... . ......... 4 2.2.1. Team members ........ ............... ... .... .. ... ... ... ... ...... .... .. .. ................ ..... ... . 4 2.2.2. Telenor coordinators .... ...... ... ................. ......... .... ............ .. .. ................ 4 2. 2. 3. Supervisor ................. ... ...... ........ ... ........... .. ........ .... ........... .... ...... ........ 4

2.3. ÜBJECTIVES . ... ... .......... ................... ....... ... .... ........ .. .... ... ... ...... . .. . ..... .. ...... 4

3. METHODOLOGY ................................... ~ ...................................................... 6

3.1 . EXTREME PROGRAMMING ........ ....... ...... ......... ..... ... .. ....... .......... .... ...... .. .. ... 6 3.1.1. Rule$ and practices of Extreme Programming .. .................. .... ..... .. ..... 7

3.2. SVN .... ............ ... ............ .. ................................ .............. ...... .. .............. . 11 3.3. LAB NETWORK OVERVIEW .... .... . .. .. .. . .... .. ..... .. .... ... ............ ....... .. ............... 11

3. 3. 1. Settings ............. ..... .. ... .. ............. .. ................ ...... .. ...... ... .... .... ..... .. ..... 11 3. 3. 2. lssues and improvements to the network ........ ... ..... .... .. ... .. ... ... .. ... ... . 13

3.4. PROGRAMMING LANGUAGES ..... .... ... ........ . .......... .. ...... ... ..... .. . ... .... .. .. . .. .... 14 3.4. 1. Client programming ..... .... ... .. ......... ..... ... .... ...... .. ... ..... ... .. ..... ....... ... .... 14 3. 4. 2. Server programming ...... ...... ..... .... ... ..... ....... ...... .. .. ... .. .. ... ..... ... .... ..... 15

4. GLOBAL SYSTEM OVERVIEW ................................................................. 16

5. PLA YERIRECORDER ............................ ..................................................... 18

5.1. REQUIRED FEATURES .................. .. .. ... .... ... .. . .. .......... ............ .. .. ... . ... . ... .... 18 5.2. CURRENT ALTERNATIVES ..... ...... ... ... ...... ... .... .. .......... .. ................... ... .. ..... 18 5.3. VLC MEDIA PLAYER .......... ..... .... ..... ... . ...... ....... .. .. ... ........ ....... ... .. ...... .... .. 19

5.3.1 . Reasons ..... .. .... .. ....... ... ...... .... .... ... ....... ...... ................ ..... .... ... ..... ...... 19 5.3.2. Functioning .... ..... .... ......... .. ......... ......... .. .... ... .................................... 19

5.3.2.1. VLC Media Player arguments .. . .. .... .................... .. .. .................. . 19 5.3.2.2. Class Record .py ................. ..... ..... .. ......... ........ . ..... .. .. . ... .. .. ....... . 20

5.4. CURRENT ISSUES ANO FUTURE IMPROVEMENTS . ....... ... . ...... . . ............... ...... 24

6. SCHEDULER .............................................................................................. 25

6.1. REQUIRED FEA TU RES ......... ... ....... .... .. .... .. .......... .... ............... .............. . ... 25 6.2 . CURRENT AL TERNATIVES ... ...... .. ... ... ... .. ... ..... ..... ...... ............ ... .... ..... ........ 25 6.3. PYTHON SCHEDULER MODULE ... .. ....... .. ... .... .. ..... ... . ..... .... ........ ........... .. ... 27

6. 3. 1. Functioning ... .. ...... ...... .. ....... .... .... ...... ... ... .................. ... .... ... ............. 27 6.3.2. Classes overview ....... .................... ... ........... ......... ........ ........ ....... ..... 28 6.3.3. scheduler.py ..... .................. ... ....... .. ................ ... ... .. ... ....................... 29 6.3.4. modsched.py ................................. ........................ .... ... .. .. ................ 32 6.3.5. xmlparser.py ..... ..... .... .... ........................ ..... ........ .............................. 35 6.3.6. record.py .... ........ .. ...... .......... .... ...... ..... ..... ..... ... ... .... .. ... .. .. ................. 37 6.3. 7. run.py.: ............... .... .. ....... ......... ........ ....... ... ...... .......................... ....... 37 6.3.8. GUI ..... .. ........... ........ ... ....... ... .. .. .. .. .. .... .... .. ..... ..... ... .... .. .... ..... ..... ....... 39

6.3.8.1 . Login Form ... ........ ..... .... .............................. .... ...... .. ....... ...... ...... 39 6.3.8.2. ry1edia Library ........... . ....... . . ......... . .. ... ......................... ................ 40 6.3.8.3. Schedule ...... .. ....... ......... ....... .. .............. ....... .... .... ... . ...... . ........ .. . 40

6.4. CURRENT ISSUES ANO FUTURE IMPROVEMENTS ......... .. ............... .. ... .......... 41

P2P PVR Applicat ions

7. BITTORRENT PROTOCOL ........................................................................ 42

7.1. INTROOUCTION TO BITTORRENT ........ .. ................... ................... .......... ..... 42 7. 1. 1. General information .... ............ ... .......... ...... .. .... ...... .. ........ .. ............... 42 7. 1. 2. Serving files .. ..... .................. ........ ............ .... ... ................. .... ........ ..... 45 7.1.3. Downloading files .. ...... ... .. ... ............. ... ... .. ..... .... ........ .... ...... ... ...... .... . 45

7.1.3.1. Exchanging data ......... ..... .. ... ....... .. ...... ............ .... ...... .............. .. 46 7.1.3.2. Peer wire protocol .......... ...... ... .. ...... .... ....................................... 46 7.1.3.3. Piece selection algorithm ... ......... ..... .. ..... ................ .. ... ..... ... ...... 46

7.1.4 .. torrent files .... .. .......... ...... ..... .......................................... ...... ........ .... 47 7.1.4.1. Generalities .. ... ................. ............ .. ........... .. ... ............................ 47 7.1.4.2. ~encode format ................. .............. ...... ............ ......... ....... ... ... .. 47

Byte strings ........... .. ........ ... .................................. ..... ... ........ ..... ............ 47 1 ntegers ..................... ........... ........ ...... .... .. ..... ............ ...... .. ................... 48 Dictionaries ....... .. ...... ... .. ...... ...... ......................... ...... ........... ................. 48 Lists .............. ..... .. ..... ..... .. .......... .... .... .......... ..... ............ ... ..... ... .... ... ... ... 48

7. 1. 5. Tracker's HTTP Pro toco l .. ... ... ............... .. .. .... .... ..... ... ... ...... ............... 48 7.2. CURRENT ALTERNATIVES .... .... .. ........ ....... ........ ...... ..... .. ........ ... .. ..... .... ..... 51

Peercast ... ............ ... ...... ... .. .... ............. ........................... ...................... 51 Gnutella .... ......................... ... .. ..... ... .. .... .. ......... ............. ... ....... .............. 51 Direct Connect.. .. .. ... .... ................ ....... ...... .................... ........................ 51 Bittorrent ... ........ ............. ..... ....... ............ .................... ...... .. ....... ............ 51 Democracy .... .. .. ....... .. ... .. .... .. ... ....... ... ..... ....... ... ... ... .. ...... ............ ........ . 51

7.3. ORIGINAL BITTORRENT CLIENT ............ ........................ ...... ... ................... 52 7.3.1 . Reasons .. ...................... .................................... ...... ........ ... ...... ..... .... 52 7. 3. 2. Functioning ....... .. ... .... ... .. ... .... .............. ...... .... ... .... .. .... .......... .. .......... 53

7.3.2.1. Putting in arder the pieces to retrieve ................. ... .. .. ... .. .. ......... 53 7.3.2.2. Channel surfing capability ........ ..................... .... ................ ......... 54

7.4. PHPB'FTRACKER ·················· ······· ··· ······· ·············· ······· ·· ·· ·· ······ ····· ······ ···· 54 7.5. CURRENT ISSUES ANO FUTURE IMPROVEMENTS ................. ... ............. .. ...... 55

8. ELECTRONIC PROGRAM GUIDE ........ ...... ................................. .. ............ 56

8.1. REQUIREO FEA TU RES ............................... ... ... .................... ...... ... ... ... ..... . 56 8.2. CURRENT AL TERNATIVES ........ ................ ....... ...... ........... ... ..... ......... ... ... .. 57

8.2.1. lnformation source ........... ...... .... ...... ... .... ..... .... ...... ........ .. ...... ........... 57 8.2.1.1. XMLTV .............. .... ....... ..... ... .... .......... .. ..... ............. .. ..... ....... .. .. .. 57 8.2 .1.2. Other solutions? ...... ................ .. ........ ...... ... ....... ......................... 58

8. 2. 2. Storage ...................... ..... .. .. ... ......... .......... .. ... .... ....... ... ..... ................ 58 8.2.2.1. XML Files ... .. ........ .. ... ....... ....... .... ....... .. ............. ...... ........ ........... 58 8.2.2.2. Database Management System (DBMS) ..... ...... ..... ....... ............ 59

B. 2. 3. Display ................................... ............ ..... .............. ............................ 60 8.2.3.1. lntegrated to the client .... ....... ... ....... ...... .... ...... ............ ..... ... ... ... 60 8.2.3.2 . Webpage ................ ...... ... .... .. .... .... ... .... ..... ............. .... ............... 60

XML and XSL T .... ....... ....... ..... ....... .... ....... .......... .... ..... ....... .. .... ... .. .... ... 60 PHP ............... ... ......... ........ ... .......... .... ....... ... ...... .. ............... ... .. .... .... .... 61

8.3. XML TV, DATABASE ANO WEBPAGE ...... ............... ............. ..... .................. 61 8.3.1. Reasons .............................................................................. .............. 61 B. 3. 2. Functioning .................... ................. .............. ........... ... ..... ................. 62

8.3.2 .1. Configuration settings ..... ....................... ...... ............ .. ................ 62 8.3.2.2. Getting the TV listing ...................................... .............. .... ........ . 63 8.3.2.3. lnserting it into the database .................... .. ..... .... .... ...... ..... ... ..... 64 8.3.2.4. Automating these operations ... ........ ..... .. ... ... .... .. ....................... 64 8.3.2.5. The website ....... .......... .... ..... .......... .. ......... ..... .. ... ... .. ............ ... .. 65

PL. P PVRApplications

8.4. CURRENT ISSUES ANO FUTURE IMPROVEMENTS ............... ...... ........ ... .... .. .. . 90

9. INTEGRATION ............................................................................................ 92

9.1. INTRODUCTION ...... ... ... .. . ..... .. ... .. ... ... ... .. ... ..... ... ... ...... .. .. . ...... .. .. ..... ........ . 92 9.2. FINAL FUNCTIONAL MODEL ....... ........... ... ........ .................. ... ......... .. ...... . ... 93 9.3. INDICAT,ING TO THE CLIENT APPLICATION WHAT PROGRAMS TO RECORD . ... ... 93 9.4. LAUNCHING ANO STOPPING A RECORDING .. ... ... .... ... .................. ... ...... . .. . .. . 94 9.5. CREATING A .TORRENT FILE ............ ....... ..... ... .. .... .. ... ............ . ....... ... ...... .. 94 9.6. REGISTERING A NEW .TORRENT FILE ........... .... ... ..... ...... ....... .. ....... ......... ... 94

1 O. CONCLUSIONS ...................................................................................... 96

REFERENCES ................................................................................................... 97

APPENDIX A- EXTREME PROGRAMMING USE STORIES ........................... 99

APPENDIX B- MODIFIED BITTORRENT CLIENT ........................................ 100

APPENDIX C- SUPPORTING CODE FOR THE WEBPAGE ......................... 103

A) JAVASCRIPTS .. ....... ... ...... ... .... . .. ... .. ... . ......... .. ............. ... ... ... .... ... . ... ...... .... 103 B) CASCADING STYLE SHEETS ... .... ........ .. ................... .. .. .. .... ... .. ... . ..... ... ... . .. . . 104 C) XML . .............. ... .. ....... ...... ... .............. . ........ ............... .. ... .. .... .. ... .... . .. .. .. .. . . 106

APPENDIX D- TEAM MEMBERS' SHORT DESCRIPTION ........................... 110

P2P PVR Applications

Table of figures

Figure 1 - Lab network at Telenor...................................................... 13 Figure 2- Global system overview..................................................... 16 Figure 3- Scheduler functioning....................................................... 27 Figure 4- The login form.................................................................. 39 Figure 5- The Media Library GUI....................................................... 40 Figure 6- Schedule......................................................................... 41 Figure 7- BitTorrent swarming technology......................................... 43 Figure 8- The pirate bay.................................................................. 44 Figure 9- Structure of a BitTorrent deployment.................................. 45 Figure 1 O- Bittprrent GUI.............................................................. ... 52 Figure 11 - XSL T transformation scheme........................................... 61 Figure 12- EPG Databas e Model....................................................... 63 Figure 13 - EPG View..................... .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ... 66 Figure 14- Pro]ect logo...................................... ............................... 67 Figure 15- Search Form.................. ............................................. ... . 67 Figure 16- Channel and Program View.............................................. 68 Figure 17 - Final Functional Model......... .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

P2P PVR Applications 1/11 o

1. lntroduction

Hard drive capacities have reached a leve! where storing video content can become as common as storing music and photos. Moreover, broadband access speeds are still increasing. In the meantime most TV channels have become digital. [Steiner, 06]

During the European Project Semester of spring 2006 in Oslo, Telenor, starting from these three observations, has assigned our group to work on developing a peer-to-peer solution for viewing and storing TV content.

Our hypothesis is that a computing system to record , store and share video programs via peer-to-peer methods can be built using existing technologies .

To begin with this project, we spent the main part of our time researching and documenting the available solutions. After a few meetings, we ended up with a solution using a TV listing source, a storing device, an Electronic Program Guide, a player/recorder, a modified BitTorrent application and a scheduler to automate everything .

The best alternatives for each of these modules had to be found , considering the time left to carry out the proj.ect and our leve! of competence.

P:LP PY 1<. A ppli cat ions 2/1 1 o

XML TV turned up to be the most suitable solution for getting TV listings, while the storing device was going to be implemented as a database. As for the EPG, we planned to do it as a website. On the client side, VLC Media Player was considered as the best solution for the player/recorder module and we decided to modify the original BitTorrent client, coded in Python. Since we were going to use a database for storing the TV listings, we chose PHPBTTracker to be our BitTorrent tracker. lt is a tracker coded in PHP. For easier integration, a Python based scheduler seemed more appropriate.

The scheduler is a central module in our system. Fetching the information from the database about the recordings to perform, it launches and stops VLC Media Player and then calls the needed function for creating a .torrent file . In the next step, this file is stored on the web server and becomes available to the user through the EPG.

In the EPG, the user can access the whole list of available shows, either already broadcasted or still to be aired. In the first option, if a .torrent is available then the user can start downloading it, and thanks to our modified BitTorrent client, he is able to view it in the meantime. In the second option, the user can select shows to be recorded directly from the stream.

P2P PVR Applications 3/ 11 o

2. Background and objectives

2.1. lnstitutions

2.1.1. Oslo University College- European Project Semester

This project has been led by students from Oslo University College (OUC). lt is the largest state university college Norway with more than 10,000 students. The Faculty of Engineering propases the European Project Semester (EPS) program that is also carried out in universities in Poland , the Netherlands, Denmark and Spain.

2.1.2. Telenor

For this project, Telenor gave the tapie to our group. This company is a majar telecommunications operator based in Norway which also operates in Scandinavia , Eastern Europe and Asia. lt is mainly a mobile services company but also provides broadband access and TV-distribution . The project has been commissioned by the Research & Development division.

P:LP PY K Appl ications 4/110

2.2. Contributors

2.2.1. Team members

Maitham AI-Essawi - Norway & lraq.

José Gardu.ño - Mexico.

Matthieu Godéré- France.

Marcin Kot- Norway & Poland .

2.2.2. Telenor coordinators

During its execution, the project has been coordinated at Telenor R&D by Per-Steinar Hansen and Torbj0rn Sund. They provided needed hardware and network equipment, and gave advice and feedback on our work.

Per Steinar Hansen has experience in the field of satellites, radio systems and computer networking . He also has experience in digital video networking, design and deployment of both pilot and commercial triple-play services.

Torbj0rn Sund has extensive experience working with the application of ICT within the health sector. He currently is engaged in the field of wireless solutions for multimedia distribution.

2.2.3. Supervisor

Throughout this semester, the work of our team has been supervised by Simen Hagen. He lectures computer science to students from the master in Network and system administration, and from the bachelor in computer engineering. He used to work at Telenor as a Research scientist. He followed our work, giving ideas and advice for the development of the project.

2.3. Objectives 1

Today, normal storage capacity in a PC or PVR (Personal Video Recorder) is in hundreds of gigabytes and will soon enter the terabyte range. Therefore, storage of digital video will become as common as storage of music and photos.

1 In spired from the project presentation of Per-Steinar Han sen at Telenor the 24 March 2006

P2P PVR Applications 5/ 11 o

At the same time, traditional TV broadcast is approaching analogue shutdown and the chain from production to consumption will soon be digital only. In addition, new video compression technologies are emerging, allowing bit rate reduction while maintaining quality. As a result, using the broadband access for video-on-demand and live broadcast TV is the next "natural" broadband service or application.[Steinar, 06]

The idea of our project is to use this increasing storage capacity to store TV shows. As expressed by our Telenor coordinators, "users shall be able to view live TV and all broadcasted content from the past". We considered this as the main guideline of the project. To achieve it, the objectives are rather clear:

• Use file sharing and web feed technology to design, develop and build an automated peer-to-peer PVR system.

• Develop and demonstrate an EPG (Eiectronic Program Guide) application with "past" viewing possibilities. On-demand delay shall be less than 1 O seconds.

• Dev~lop an application running on a Windows PDA for remate control of the PVR.

• Transcode and stream content from the PVR to the PDA.

Since there was a delay in the start of the project, our work was limited to the two first objectives.

The developed applications had to be based on open source, and legal issues were not addressed .

P2P PVR Applications 6/11 o

3. Methodology

The circumstances of our project merited a deliberate and disciplined approach to software development which is also capable of being flexible and working with a tight deadline. The methodology that most suited our needs was a relatively new agile methodology called extreme programming.

3.1. Extreme Programming

According to extremeprogramming.org , XP was created in response to the problem domains whose requirement change. Possible reasons could be:

• Customers m ay not ha ve a firm idea of what the system should do. • You may have a system whose functionality is expected to change

every few months. • In many software environments dynamically changing requirements is

the only constant. [Wells, 06]

The Extreme Programming Pocket Guide states that using this methodology the team (Íncluding the customer) must agree on an acceptable leve! of quality. Agree considering the time and resources constraints. [Chromatic, 03]

P2P PVR Applications 7/110

XP is intended for the use of small groups of programmers. The average group of programmers recommended is between 2 and 12. [11] In our case we are 4 which fit just right.

Another requirement is testability. You must be able to create automated unit and functional tests. [Wells , 06] As you will see in this document, all the system can be divided into smaller parts or subsystems, which can be individually ·tested .

The real goal XP has always been to deliver the software that is needed when it is needed.[Wells, 06] and in our experience we can confirm that this goal can be easily achievable.

3.1.1. Rules and practices of Extreme Programming

There are 4 main phases in XP which are described in the extremeprogramming.org webpage as this :

• Planning

o User stories

This stories are created by the users, this are used instead of use cases. They are also used instead of a big requirements document.

o Release plan

A release plan is created in the beginning of a project; this will lay out the overall of the project. In our case we did this just after the brainstorming session which is not part of this methodology but was very useful.

o Small releases

The programmers need to release iterative versions of the system to the customers often, in our case the costumers were the researchers, us. The release planning meeting is used to discover small units of functionality that make good business sense and can be released into the customer's environment early in the project.

o Project velocity

P2P PVR Applications 8/1 1 o

The project velocity is a measure of how much work is getting done on the project. In our case we had a page with the tasks written and the percentages which were changed by each of

, the members.

o lterative planning

Each iteration, a planning of the tasks has to be done. In our case there were few tasks that took long time so the iteration planning sessions were used to give ideas to a colleague who had difficulties.

o Move people around

To move people around in the different tasks was not very convenient due to the deadline for us. This was only done when we got definitely stucked on a certain task.

o Daily standup meeting

This is a short meeting at the start of every workday, due to the already mentioned time constrains this were only performed two times a week and if a member chose to have one.

o Fix XP when it breaks

This step or rule of XP tells us that the methodology should be fixed or adapted depending the needs of the project, organization or individuals.

• Designing

o Simplicity

"A simple design always takes less time to finish than a complex one. " We created from the first days a really simple design and architecture.

o Choose a system metaphor

"Choose a system metaphor to keep the team on the same page by naming classes and methods consistently." In our project, we named all of the classes with appropriate and descriptive names such as uploadformsubmitter.py, which submits a form for uploading a metafile.

P2P PVR Applicat ions 9/11 o

o Use CRC cards for design sessions.

"Use Class, Responsibilities, and Collaboration (CRC) Cards to design the system as a team. " We hada room made with whiteboard walls , which we used to design the system; this replaced the CRC cards but kept the design collaborative .

o Create a spike solution

"Create spike solutions to figure out answers to tough technical or design problems. A spike solution is a very simple

· program to explore potential solutions." We usually referred to this as hacks, as the objective of the project was to research possibilities, sorne of this spikes or hacks were kept.

• Coding

o The customer is always available

"One of the few requirements of extreme programming (XP) is to have the customer available. Not only to help the development team , but to be a part of it as well. " As we, the researchers, and our supervisors were the users, we were always available to ourselves.

o. Coding standards

"Code must be formatted to agreed coding standards ." We agreed on basic things such as the following :

• Names of classes should always begin with capital letter. An example is the String class.

• Document every main function with the triple quotes option so python can generate documentation automatically.

• Names of the functions start with lowercase and if the function consists of two or more words, then capitalize each after the first one. One example could be: uploadForm()

• lnclude an example of the usage of the class in the documentation so the process of plugging the components of the system could be done easily.

P2P PV 1{ Applicatíons 1 0/llü

o Code the unit test first

"When you create your tests first, befare the code, you will find it much easier and faster to create your code ." We decided to write the template of the classes first and then continue adding new ones as they were needed. The changes done had to be

' reported to everybody if they changed something significantly.

o Pair coding

"AII code to be included in a production release is created by two pe o pie working together at a single computer". We actually managed to do this in the most important pieces of the client software such as the scheduler and the recorder. For the scheduler Jase and Marcin worked together and for the recorder Maitham and Jase were assigned. What helped notably was the space of the organization in which we were located. We worked in a laboratory with all the equipment needed not so far from each other. We could say we were working side by side.

o Sequential lntegration

"Without controlling source code integration developers test their code and integrate believing all is well. " This was carried out very carefully not to break things. We also used technologícal tools that helped us ín the version control , more precisely SVN, so that we wouldn't loase everything in case of breakage.

o lntegrate often

"Developers should be integrating and releasing code into the code repository every few hours, whenever possible." We agreed on following this rule as much as possible. Updating the code via SVN proved to be an effective and efficient way to

, do it.

o Collective code ownership

"Collective Code Ownership encourages everyone to contribute new ideas to all segments of the project. Any developer can change any line of code to add functionality, fix bugs, or refactor. ". We decided to not follow this rule completely; only suggesting the ideas and not adding features

P2P PVR Applications 11 / 11 o

to code not owned by the developer was allowed but fixing bugs without changing the structure was permitted .

o Optimize last

"Do not optimize until the end." We didn't optimize the system coding as the project objectives didn't require it.

• Testing

o Unit tests

"Unit tests are one of the corner stones of Extreme Programming (XP) ." We developed the unit tests with every class we made; in other words, the unit test was contained inside the code.

o When a bug is found tests are created

"When a bug is found , tests are created to guard against it coming back". We actually kept the same unit test inside our code but modified it in order to test the bug found .

3.2. SVN

When we were actually in the coding phase we realized that a code repository was needed. We searched for the solution that suited our needs and met the requirements.

The most adequate product we found was SVN, Wikipedia defines itas:

"An open source application used for revision control. lt is sometimes abbreviated to svn in reference to the name of its command line interface. Subversion is designed specifically to be a modern replacement for CVS and shares.a number of the same key developers."[Wikipedia, 06]

3.3. Lab network overview

3.3.1. Settings

Telenor provided us with the required equipment for setting up a lab network. Essentially, we got a rack with four computers that could be used for different purposes. Two of those computers were brand new with quite good specifications; the other ones would serve more as clients and for testing . The computers were connected to two KVM switches.

P:LP PV 1{ Appl ications 12/110

A separate class-C subnet was created for us: 192.168.204.0/24. Our computers had also access to multicast TV-streams. All the computers had access to the Internet, although being firewalled . The equipment proved to work quite well , except for some issues that are explained in the next section.

All the computers were installed in a dual-boot configuration with both Ubuntu Linux (Dapper beta) and Windows XP pro. In practice, we primarily used those computers with either Linux or Windows. The best setup proved to be letting the new ones run Linux all the time and Windows on the old ones.

Computerlhostname Sp~cifications Software and purpose

Primarily used as a work station.

homer AMO 3500+ , 2GB RAM and 200GB hard drive

Marge

Lisa

Bart

[AMO 3500+ , 2GB of RAM and 200GB hard drive

¡-

Web server (Apache2/PHP), database (MySQL 4.1 ) and project files.

PII 700Mhz, 512MB of RAM and Running BitTorrent clients and 250GB hard drive various tests .

1 -

P4 1. 7GHz, 768MB of RAM and Running BitTorrent clients and 250GB hard drive various tests.

A network diagram is provided to for an overview:

homer·

192.168.204.21

bart

192. 168.204.22

3.3.2.

P2P PVR Applications

Lab Network: 192.168.204.0/24

marge

192. 168.204.22

192. 168.204.23

Cisco PIX

192.168.100.1

f•lult icast streams:

239.192.100.10 - Canal+ Film 239.192.100.11 - Canal+ Film 2 239.192. 1 OO. 12 - Canal+ 239. 192. 1 OO. 13 - CI'Jiore Fi lm 239.192.100.20- BBC World 239. 192. 100.49- NRK1 239.192.100.50- NRK2 239.192.100.52- N2 239.192. 100.56- NNorge 239. 192. 100. 100 - 0·1ore HDN

Figure 1 -- Lab network at Telenor

lssues and improvements to the network

13/ 11 o

In the beginning, we experienced sorne issues with our setup. Sorne of us had a more Unix-oriented background and wanted to primarily focus on running Linux. We had to keep in mind the mainstream user who is usually running sorne version of Windows. We ended up with installing both Linux!Windows on all computers. This took quite a bit longer time than expected . .

Another related issue is that running Linux on both the new computers did cause a couple of problems. The first one was that the onboard audio­chipset was quite new and not well supported in Linux. lnstalling an almost released new version of Ubuntu solved the problem, but another one emerged . The two new computers had network cards from Marvell which had a bit unstable drivers. The computers could lock up under load or even when acquiring an IP-address.

P2P PVR Applications 14/ 11 o

This did not happen too often, and we did not give it much priority. In the end, the problem was solved in a new release of the kernel and no lockups ever occurred. The lessons learnt from this are that Linux is a great operating system, but one must still expect sorne minor issues on bleeding edge hardware.

We also experienced sorne differences with the VLC media-player on both Linux and Windows. The Linux version had sometimes problems with transcoding. This was ultimately solved by installing VLC 0.8.5 which worked rather smoothly.

3.4. Programming languages

3.4.1. Client programming

We decidetl to program in Python for the client side application of our system because the original BitTorrent client was coded in this language.

Python is a clear and powerful object-oriented programming language, comparable to Perl , Ruby, Scheme or Java. lt is a very flexible programming language. lt enables programmers to adopt the kind of methodology that is more useful for them or that makes more sense for any particular application. lt supports object orientation, structural programming, functional programming and others. [Wikipedia , 06]

Most notable features are:

• Programs written in python are easy to read because of its elegant syntax .

. • Easy to use language, ideal to build prototypes without compromising

maintainability.

• Comes with a large standard library that supports many common programming tasks such as connecting to web servers, searching text with regular expressions, reading and modifying files.

• Python's interactive mode makes it easy to test short snippets of code.

• Can also be embedded into an application to provide a programmable interface.

• Runs on many different computers and operating systems: Windows, MacOS, many brands of UNIX and OS/2.

• lt is free and open source . .

P2P PVR Applications 15/1 1 o

[Python, 06]

3.4.2. Server programming

In this project, we needed to set up a web server with a database. We also created a website; to do it, we mainly used PHP for generating dynamically the XHTML code of the webpage and for querying the database (using MySQL).

The graphical layout of the site is done thanks to a CSS style sheet. Besides, to add more dynamism to the site, we used some JavaScript functions, and AJAX techniques have even been demonstrated in some part of the webpage.

P2P PVR Applications

4. Global System Overview

Here is a functional model of the system we designad.

TV-Iisting source

stored in

Storage device

fetch es information

Scheduler

U ser

Figure 2 -- Global system ovetview

16/11 o

e reates

. torrent files

We have identified four modules relatad to the player/recorder, the scheduler, the BitTorrent protocol and the Electronic Program Guide.

P2P PVR Applications 17/1 10

Each of these tour modules will be the subject of a chapter in this report. The interactions between all these modules will be detailed in the chapter "lntegration" . .

P2P PVR Appl ications 18/ 110

5. Player/Recorder

5.1. Required features

As indicated by its name, this module has to play and record video content. In our case, we needed an application able to read stream flows, transcode and save them as video files . We also needed it to be executable from command IÍne since it will be opened by an externa! component (scheduler). The application must be open-source and cross-platform.

As it is a module, we need to program functions that will link this application to the scheduler.

5.2. Current alternatives

For this module, we did not have so many options. We could not develop one application on our own so we needed to use an existing solution. Numerous players are available to read streams. But very often, either the application did not meet the requirements or it worked only on Windows or was not free. The only one that met our expectations was VLC Media PI ayer.

P2P PVR Applications 19/ 11 o

5.3. VLC Media Player

5.3.1. Reasons

We chose VLC (initially Video LAN Client) Media Player because it fulfilled the requirements perfectly:

• Runs on most operating systems. • Open source. • Free software. • Easy to use. • Supports many multimedia formats without any additional libraries. • Can transcode and record while playing.

To program the function that will help us integrating VLC Media Player into our system, we chose Python, as for the other modules.

5.3.2. Functioning

5.3.2.~. VLC Media Player arguments

VLC Media Player offers a command line mode in which you can specify the arguments in order to achieve a specific result like playing a file, saving or transcoding it. . He re are the m a in arguments which we u sed to interact with VLC:

• Play locally (: sout=#duplicate{ dst=display}) This option enables the local reproduction of the stream on screen. The transcoding options which we are using with the file can be monitored he re.

• File (:sout=#duplicate{dst=std{access=file,mux=ts,}}) Saves Hle stream to a file . In this case, we use MPEG TS as the encapsulation method .

• Transcode (:sout=#transcode{vcodec=mp4v,vb=,scale=,acodec=,ab=) Transcodes (converts from one codee to another or lowers the bitrate). The options are video codee, video bitrate, scale, audio codee and audio bitrate.

P2P PVR Applications 20/ 11 o

Description of the syntax variables :

dst=: specifies where the stream is going to be saved .

display: Module to display the stream.

access=: Sets the destination in which we are going to save the file .

mux=: Used to set the encapsulation method.

[Videolan , 06]

5.3.2.2. Ciass Record.py

To integrate VLC Media Player into our system, we created a Recorder class in Python. The class it's just an interface that glues all the functionality of the VLC player to our system. lt is explained in detail in the following code:

P2P PVR Applications 21/ 110

import os import time import popen2 import uploadformsubmitter

....

from BitTorrent.platform import install_translation install_translation()

import sys from BitTorrent.defaultargs import get_defaults from BitTorrent import configfile

record.py

from BitTorrent.makemetafile import make_meta_files from BitTorrent.parseargs import parseargs, printHelp from Bi!Torrent import BTFailure

defaults = gel_ defaults('maketorrent-console') defaults.extend([

('comment', ". _("optional human-readable comment to put in .torren!")), ('target', ", _("optional target file for the torrent")), ])

defconfig = dict([(name. value) for (na me. value, doc) in defaults]) del name, value, doc

class Recorder: ''""Ciass that ca lis the recording of a stream using vlc

Example Usage: r = Recorder("udp:/[email protected] 00.20:8208",'c:/rnovie.mpg',"234") r.start() r.kill()

MAE@ JLG@

def _init_(self,ut1,destinationName,progld): .... from BitTorrent.platform import install_translation install_ translation() print prog Id self. url = url self.destinationName = destinationNarne self.progld = str(progld)

Note: In python you don't need to import modules at the beginning but we did so to be consistent.

Constructor: This class is initialized with three arguments: the address of the stream, the destination path in the file system in which we intend to save the file and the program Id .

self.config , self.args = configfile .parse_configuration_and_args(defaults,'maketorrent-console' ,O,O.None)

def start(self, filepath='C:/Program FilesNideolANNLC/vlc.exe', vcodec="mp4v",vb=512.scale=1 ,acodec="mp3".ab=64):

'""'lt builds the recording string and then launches VLC, if you dont specify the variables, the defaults are u::.ed ."""

#filepath of the VLC binary self.filepath = filepath #na me of the video codee to use self.vcodec = vcodec #Video bitrate self.vb = vb #scale of the output video, [e.g .. 2 .. 5, 1, .. ] self.scale = scale #audio codee self.acodec = acodec #audio bitrate self.ab = ab #print self.url

....

Start: As the function name says, it starts the VLC client with the right parameters , if the class that uses it doesn't specify them, the defaults are used.

P2P PVR Applications 22/ 110

if os.name == "nt": self.argsforprogram = str(self.url) + '--plugin-path="C:\Program Files\VideoLAN\VLC\plugins'" + '

:sout=#transcode{vcodec=' + str(self.vcodec) + ',vb=' + str(self.vb) + '.scale=' + str(self.scale) + ',acodec=· + str(self.acodec) + ',ab=' + str(self.ab) + '.channels=2}:duplicate{dst=display,dst=std{access=file,mux=ts,dst="' + str(self.destínationName) + "'}}'

self.píd = os.spawnl(os.P _NOWAIT.self.filepath ,self.url,self.argsforprogram) else:

self.argsforprogram = str(self.url) + '\':sout=#transcode{vcodec='+ self.vcodec + ',vb=' + str{self.vb) + '.scale=' + str(self.scale) + ',acodec=' + self.acodec + ',ab=' + str(self.ab) + ',channels=2}:duplicate{dst=display,dst=std{access=file.mux=ts,dst="'+ self.destinationName + '"}}\"

opener = popen2.Popen3(self.filepath + "" + self.argsforprogram) self.pid = opener.pid #self.pid = os.spawnlp(os.P _NOWAIT.self.filepath,self.filepath, self.argsforprogram.stríp()) #self.pid = os.spawnl(os.P _NOWAIT,self.filepath," ", self.argsforprogram)

print self.argsforprogram,'self.argsforprogram: record .py' #print self.pid '

def kill(self) : print ''killing process", self.pid, "on OS'', os .name if os.name == 'nt' :

import win32api prínt self.pid win32api.TerminateProcess(self.pid.O)

el se: prínt self.pid. os.name os.kill(int(self.pid),9)

print "creating .torren! file" self.create Torren!()

def dc(self,v): pass #print v

def prog(self,amount): '"'"prints the percentage of file complete"'"' print '% .1f%% complete\r' % (amount • 1 00)

kili : This function ends the recording by killing the VLC player directly from the Operating System.

def crea te T orrent{ self, urttracker= "hltp ://ma rge/spríngfield/tracker/tra cker. php") : self.file = [os.path.abspath(self.destinationName)] ,

make _meta _files(urltracker,self. file .progressfunc=.:;elf. prog, filefunc=self. de. piece _len _pow2=18. comment="Created by Spríngfield".target=self.destinationName + ". torrent",filesystem_encoding=self.config['filesystem_encoding'] ,use_tracker=self.config('use_tracker') ,data_dir=self.c onfig['data _ dir'])

self.ascíifilepath = self.destinationName+". torren!" self.ascíifilepath = self.asciífílepath.encode('ascíi') f = uploadformsubmitter.UploadFormSubmitter(self.ascíifilepath ,self.progld)

There is also a function createTorrent that will be used, as its name says, to create a torrent file after the recording . This will call the functions in the class uploadformsubmitter.py, which will update the tracker and upload the metafile created by createTorrent.

import httplib, mimetypes import urllib, stríng

class UploadFormSubmitter:

P2P PVR Applications

uploadformsubmitter.py

"""Ciass to submi(the .torren! file to the PHPBTiracker and to fill out the fonn. requires Hostname.path,Usernam.a, Password , and the path to the .torren! file. Built u pon the code {OSS python license) of Wade b..eftwich found at:

http :1/aspn.actívestate. com/ASPN/Cookbook/Python/Recipe/146306

Example usage: #ufs = UploadFormSubmítter("C:\file.torrent")

JLG@Mon May 13 15:21:05 2006 111111

23/1 1 o

def _init_(self,pathtotorrentfile,progld,host="marge",pathtoform="/spríngfieldftracker/newtorrents.php",username="eps", password="eps"): ......_

self.host = host "111111...,.,.•••••••-J self.username = usemame self.password = password self.pathtotorrentfile = pathtotorrentfi le self.pathtoform = pathtoform self.progld = str(progld) self.filename = string.splitfíelds(self.pathtotorrentfile,"f')[-1 :][O]

self.f = open(self.pathtotorrentfile,"rb") self.filebody = self.f.read() self.campos = f ("usemame" ,self. username), ("password" .self. password), ("autoset" ,"enabled"), ("url"," . ./torrentfiles/"+self. filen ame), ("prog Id" ,self. prog Id) J self.archívos = [("torrent",self.pathtotorrentfile.self. filebody)] self.msg = self.post_multlpart(self.host.self.pathtoform.self.campos.self.archivos) self.enable_torrent(self.progld) print self.msg.'self.msg uploadformsubmítter.py'

def post_multipart(self.host. selector, fields, files) :

Function taken from Wade Lettwich Post fields and files toan http host as multípart/form-data. fields is a sequence of (name, value) elements for regular form fields.

The constructor requires the path to the torrent file and accepts optionally other parameters such as the host to upload the file to, and the path to the upload script, username and password. lf this are not given all the parameters will use their default settings.

files is a sequence of {name, filename, value) elements fo~a to be uploaded as files Return the server's response page. ,....,.. _______ .¡------------''---------, ...... ""' Functions taken from content_type, bocty = selt.encocte_multipart_tormctata(fietcts. files) Open sourced code at h = httplib.HTIP(host) h.putrequest('POST', selector) the ASPN. h.putheader('content-type', content_type) h.putheader('content-length', str(len{body))) h.endheaders() h.send(body) errcode, errmsg . headers = h.getreply() return h.file.read()

f

def encode_multipart_formdata(self, fields, files): ......... _______ , 1!1111 ............

fields 1s a sequence of (name, value) elements for regular form fields.

This will convert the data into a format in which can be transmited to a html form .

files is a sequence of (name, filename. value) elements for data to be uploaded as files L------ ----.------' Return (content_type, body) ready for httplib.HTIP instance

BOUNDARY = '--------Thls_ls_tHe_bouNdaRY _$' CRLF = '\r\n' L=[] print 'fields: ', fields for (key, value) in fields:

L.append('--' + BOUNDARY) L.append('Content-Disposition: form-data; name="%s"' % key) L.append(") L.append(value)

prínt 'files: ', files for (key, filename, value) ín files :

L.append('-' + BOUNDARY) L.append('Content-Disposition: form-data ; name="%s"; filename="%s"' % (key, filename))

P2P PVR Applications

L.append('Content-Type: %s' % self.get_content_type(filename)) L.append(") L.append(value)

Lappend('--' + BOUNDARY + '--') L.append(")

body = CRLF.join(L) content_type = 'multipart/form-data; boundary=%s'% BOUNDARY return content_type, body

def get_ content_ type( self, filename): return mimetypes.guess_type(filename)[O] or 'application/octet-stream'

~

def enable_torrent(self,progld.username="".password='"'): ~ self.progld = progld params = urllib.urlencode({'logín': self.username,'password':self.password,'progld':

self.progld}) path = 'http:/f + self.host + '/spríngfield/epg/process/enable_torrent.php' print self.password, self.usemame. params, patll f = urllib.urlopen(path,params) print f.read()

5.4. Current issues and future improvements

24/ 110

The enable torrent function will enable the torrent in the Springfield portal.

The stream recording in our implementation is not as sophisticated as it could be. Solutions that read the metadata in the streams should be integrated tD have a better control of the streams. Moreover, if there were sorne flags in the streams indie;ating the start and the end of a show, then it might be a good idea to use them to have a more accurate recording .

Also, the starting and ending of the recordings should be done through an API and not through the spike or hack we did, which consists of killing the VLC application directly with a system call to the OS and killing it the same way.

P2P PVR Applications 25/11 o

6. Scheduler

6.1. Required features

During the planning phase, we discovered that we needed a solution on the client-side. What we needed was not entirely clear, but after some initial rounds with planning and brainstorming, we came to the conclusion that in addition to the modified BitTorrent client, a scheduler would be a good solution. Since the beginning , we had in mind a solution that would work on both Linux and Windows.

6.2. Current alternatives

We tried to figure out how the scheduling would be done, and looked around for different alternatives. For our purposes, the chosen program had to be both free and open source. After all , why reinvent the wheel if a good solution already exists? This preved to be quite difficult. Although there are several different programs that can record a multicast stream, they usually just do this with no extras, and by no means maintain a schedule. Examples of such programs are vlc, mplayer or xine.

One solution that provides all the functionality is MythTV. lt's both open source and provides almost everything for recording , scheduling and playing

P2P PVR Applications ------------------------------- 26/ 110

TV-streams. We hada vague idea on using it in the beginning of the project, but after investigating it further, it proved to be too complex.

The main réason for this is that MythTV is actually a client-server application with very high demands on the hardware, and can be quite difficult to insta!!. lts main focus is also on the Linux operating system, although there are front ends that can run in Windows.

Essentially, MythTV converts a computer into a recording station that fetches the schedule from web, records programs and takes care of the playback. This was not really an alternative for us since we already had chosen to use VLC and our focus on using Python/PH P would make it much easier to integrate.

Another issue is that it is of no use to let a client install such demanding software, and then apply sorne modifications to it. We also wanted as lightweight application as possible that would let the computer be used for other task~ simultaneously. That is usually how p2p client work (while running in the background) .

We needed a solution that could both fetch the schedule in a custom format (XML-file created to our specifications) and also execute the recording . At a later time, it would be feasible if the client could create a torrent-file from the recording and publish it to the tracker.

Because of time constraints , we figured out that using a script that executes a recorder at the appropriate moment would be a good thing . The recorder was already an obvious choice.

VLC runs on both Linux and windows and we already had sorne experience with using it. lt also provides a plethora of features like transcoding a stream to save disk space and is an overall good solution. Look at section 8 for more details about VLC.

The requirements for the application would be:

• Run on both Unix and Windows. • Use sorne kind of scheduling system to trigger a recording . • Be able to fetch and parse a custom XML-file from a web-server. • lntegrate well with the modified BitTorrent client. • Possibly create a torrent, and send an update to a database.

P2P PVR Applications 27/ 110

We already had started looking at the Python scripting language during the modification of the BitTorrent client. This language is portable , well­documented and very readable. But most importantly, after sorne searching, it also provides a large library quite useful.

Things like parsing XML, simple scheduling and running threads are made easier by sorne of the provided modules. The choice was even easier when taking into account that the BitTorrent client is originally made in Python too. As we later discovered, this still required a lot of modifications but nonetheless proved to be a very good choice.

When it comes to the integration with other parts, Python proved to be excellent as "glue". Making it work with both the torrent client and recording class was s'eamless.

6.3. Python Scheduler Module

6.3.1. Functioning

In this section , we will describe the technical details of the scheduling application. From the beginning, the main focus was on keeping the application divided into severa! classes for future maintenance and integration. Below is an image with an overview of how the scheduler works:

Execute scheduler

User authentication

Fetch schedule (XML)

Trigger recording

Figure 3 -- Schedu/er functioning

First, a user visits the EPG, then authenticates and creates a schedule with programs to record . Then the user runs the scheduler and fetches the created schedule in XML-format. Once the scheduler is running , a recording will be made at the specified time. In our implementation this would probably be an application that runs all the time in arder to make updates in the schedule and does not miss any shows to record.

P2P PVR Applications 28/ 11 o

6.3.2. Classes overview

The scheduler itself is just one Python class, scheduler.py. In this class, we made use of several smaller classes (each in its own file) with certain specialized functionalities . Here is a small overview of all the classes:

c/ass

scheduler.py

modsched.py

xmlparser.py

record .py

run.py

uploadformsubmitter.py

description

Main class for the scheduler.

A class that does the queuing of scheduled recordings.

Parsing of the fetched program list in XML-format.

Responsible for launching/terminating VLC when a recording starts/ends.

Executable class to show how the scheduler works .

This class takes care of submitting a form after creating the torrent (to update the tracker)

P2P PVR Applications 29/ 110

6.3.3. scheduler.py

The main class of the scheduling application is scheduler.py. lt joins the other classes an<:l has an instance of the scheduling queue. lt does not provide any kind of user interface, this could be implemented in a class that instantiates an object (run .py is provided as an example) . We will explain some of the methods in this class further down.

from xmlparser import Xmlparser from record import Recorder import modsched, xml.sax, datetime. time. os

class Scheduler:

scheduler.py

""" This class is a container for an instance of a recording schedule. The executable class ...,. can then interact with it to show the schedule. -4~1---~ An instance of this class takes exactly one argument. and that's the xml-file to process: '""'

"'"'Sample usage: First open a file-h¡mdle for the xml-file in the class your're going to use the scheduler from.

file = open('test.xml' . 'r'}

Then create an instance of the scheduler:

s = Scheduler{file)

To create tlle schedule one must start a scheduling thread. This is simply done by:

s.createSchedule{ file )

Look also at test.py for an example of a runnable class.

MK@ Friday. May 26th 2006 11111!

def _init_(self, user=None, pwd=None): self.recordings = {} self.threads = [) self.current = None

# for compa!ibility between Iinux and windows if os.name == 'posix' :

self.vlcpath = 'vlc' else:

self.vlcpath ='C:!Program FilesNideoLANNLC/vlc.exe'

homedir = os.environ['HOME'] self.rec_store = 'rec' # recpath = os.path.abspath{os.path.join( hornedir, rec_store )) self.rec_path = os.path.expanduser('-1' + self.rec_store)

if os.path.exists(self.rec_path): print 'Saving recorded prograrns in:',self.rec_path

else: print 'Crealing the directory:' ,self.rec_path os.rnkdir{ self.rec_path)

continues ...

Documenting the code was one of the most important parts of the project.

Constructor (_init_):

lt can accept the username and password for fetching XML from the EPG, but it is not required . The constructor also creates a directory for saving files and checks which platform the program is running on (Linux/Windows). self is a reference to the method itself. When creating a module in Python, this is required .

P2.P PVR Applications 30/ 11 0

def parseFile( self. file ): """Create an instance of the xrnl-parser and store the contents in a dictionary'"''' handler = Xmlparser() <11111...,_1-----~ xrnl.sax.parse( file , 11andler) """~~ self.recordings = handler.get_prograrns()

def createSchedule(self, file): """Create a schedule from the dictionary created by reading the xml-fíle. Each recording is just another dictionary with start/end time, tille and url for the channel"""

if self. current: print 'removing old schedule' self.current.deiQueue() self.current = None

# self.current = None

self.parseFile(file) self.s=modsched .scheduler(time. time, time .sleep)

for entry,in self.recordings : program = self.recordings[entry] start = float(program['start'J) end = program['end') tille = program('title'] chanurl = "udp://@" + program['chanurl'] tille = title.replace(' ·. '_')

.....

filenarne = tille+ '_'+ self.epochToFile(start) + '.rnpg' filenarne = os.path .abspath( os.path.join(

self.rec_path, filenarne))

'"'"Create an instan ce of the recorder and store it in a scheduler queue""" start = float(start) end = float(end)

now = datetime.datetirne.now() now = tirne.rnktime(now.timetuple())

if start > now: r = Recorder(chanurl. filename. entry)

prograrn['start_entry'] = 1 self.s.enterabs(start, 1, r.start. (self.vlcpath. ), prograrn)

#create a copy of the prograrn dictionary prograrn_copy = self.clone_dict(prograrn) prograrn_copy['start_entry'] =o #kili entry self.s .enterab~(end , 1, r.kill , () . program_copy)

else: print 'time passed for the recording . skipping'

Continues ...

parseFile:

This is just a helper method , not meant to be used. lt accepts a file handle to an XML-file. That creates an object of the XML­parser and extracts data from it (program schedule) .

createSchedule:

This is the main function of the scheduling application . The only input is the file to parse. The file is parsed , and the extracted data is the one used to create recording objects in a queue. File names are generated by using the program's

P2P PVR Applications 31 / ll o

self.s.start() self.current = self.s self.s.showQueue() self.threads.append(self.s)

def checkThreads(self): """Show which threads are alive (running)""" i =o for x in self. threads:

print i if self.s.isAiive():

print 'Schedul\ir alive: '.i, 'x: ', x i = i + 1

def clone_dict(self, o): """Return a copy of the dictionary'"'" n = {} for k in o.keys(): n[k] = o[k] return n

def epochToFile(self, epoch) : """Crea te a timestamp to use in the filename""" date= datetime.datetitne.fromtimestarnp(epoch) return date.strftime("%d-%m-% Y _%H_ %M")

def showQueue(self) : if self. current:

self.current.showQueue() 1...,1---~ else: .... ....,. print 'no items in queue'

check Threads:

This function prints on the standard output (usually the screen) the current running threads. This proved usefull while debugging .

showQueue:

This function prints on the standard output (usually the screen) the current queue of programs to be recorded .

P2P PVR Applications 32/ 110

6.3.4. modsched.py

The scheduling part could be performed by built-i n functionality in the operating system, Cron on UNIX and task scheduler on Windows. But we discovered that Python has a very simple and rudimentary scheduling module. This module did provide a queue for scheduling tasks , but it lacked some functionality that would let our program run while the scheduling was in place (the program utilizing the scheduler would be stuck in a while loop) . This looked like the best solution as it would run cross-platform and we could modify the code to let it run more interactively.

This class inherits some methods for threading (threading.thread module) . Every time an instance is created a new thread is executed.

P2P PVR Applications 33/ 11 o

modshed.py

"'"'Modified scheduler class. The code is partially reused from sched.py (part of Python library), but most functions are modified to accommodate recording objects. Also the queue is externa! to make it possible to display it while the scheduler is running. 1 didn't override the class because that wouldn'l save any time.

MK@ Friday, May 26th 2006

import bisect. time. datetime, sys from threading irnport Thread _all_ = ["scheduler"]

class scheduler(Thread): def _init_(self, tirnefunc, delayfunc) :

....

"""lnitialize a néw instance, passing the time and delay functions""" Thread._init_(self) self.queue = [] self.timefunc = timefunc self.delayfunc = delayfunc

def enterabs(self, time. priority, action. argument, obj) : """Entera new event in the queue atan absolute time. + Returns an ID for the event which can be used lo remove it, if necessary.

The last ítem is'the recording object to store in lhe queue. This is modified lo rnake it 'easy' lo display the queue.

event =time, priority. action, argurnenl, obj bisect.insort(self.queue, event) return event #The ID

def enter(self, delay, priority. action, argurnenl, obj): '"'"A variant that specifies lhe time as a relalive time .

This is actually the more commonly used interface.

time = self.timefunc() + delay return self.enterabs(time, priority, action. argument, otlj)

def cancel(self. event): '""'Remove an event from the queue.

This must be presented the ID as returned by enter(). lf the event is not in the queue. this raises RuntimeError.

self.queue.rem9ve(event)

def empty(self): """Check whether the queue 1s empty."'"' return len(self.queue) == O

Constructor (_init_):

The constructor is as simple as possible. timefunc and delayfunc are references to time.time and time.delay. lt is just a shortcut for using those functions in the queue.

Enterabs:

This is the main method for appending an ítem to the queue. Time is a timestamp on when to execute <action argument>. The action argument is usually a reference to a recording object, with the argument start() or kili() .

The obj parameter is in our case a program object from which we can extract needed information to show the queue.

P2P PVR Applications 34/ 110

def de!Queue(self): """Remove all items from the queue""" print 'modsched.py: de!Queue' while self.queue :

del self.queue[O]

def run( self):

q = self.queue while q:

time, priority, action. argument, obj = q[O) now = self.timefunc() if now < time:

self.delayfunc(time - now) el se:

del q[O) print 'argument:',argument'4....,.~--~

void = action(*argument) ~

self.delayfunc(O) # Let other threads run

print 'modsched.py: run(): last line'

def showQueue(self):

deiQueue:

We needed this method to be able to create a new schedule if an old one is already applied. lt removes all the items from the queue. Since the thread checks for items in the queue, it will be stopped when there are no item left.

Run:

This method executes a queued item. In practice, it is a while loop that compares the time. lf the time for a scheduled item has just passed (now < scheduled_time) , the action and argument will be executed . Then the ítem is removed from the queue.

"""Return a formatted lis! of items in the queue (to be displayed on screen) This is of no use if the scheduler ítself is not executed in it's own thread"""

if len(self.queue) ==O: print 'empty queue' retum

for x in self.queue: " program = x(4] #program object is the 5th id = program['progid'] tille= program['title'] start = program['start'] end = program['end')

output = '[start recording]lt' + id if program['start_entry'] == 1:

time= self.epochToDisplay(float(start)) else:

time= self.epochToDisplay(float(end)l output = '[end recording]\t' + id

output += ' ' + time + ' ' + tille print output •

def epochToDisplay{self. epoch): """Function similar to the one above. Returns a string to display in the queue'"'" date = datetime.datetime.fromtimestamp(epoch) return date.strftime("%d-%m-%Y %H:%M:%S")

showQueue:

Runs through the queue and extracts information about the entries. Formats the output and shows if it's an entry to stop the recorder, program name and scheduled time.

P2P PVR Applications 35/11 o

6.3.5. xmlparser.py

lt was possible to use xml.sax.utils from the Python library to parse XML input. To be correct, it is really a handler for the xml.sax.parse(file, handler) method. lt is a definition on what to do if different tags are encountered and extract the data. The extracted information is then returned as a dictionary.

-------.--------P:....:2:..:.P-=-~VR Applications 36111 o

xmlparser.py

"""This class overrides ContentHandler from xmLsax.utils.

Create a dictionary from the fetched xml-file. In this dictionary each recording will have an entry by it's progid .

Example: {progid1 :dict. progid2:dict. progid3:dict, ... )

Then each entry in this díctionary is another díctíonary. So recording('progíd'] contaíns the following information.

Example: { progid: "id number",

chanurl: "url of the channel, title: "program tille". start: starttime (epoch). end: end time (epoch)}

MK@ Friday. May 26th 2006

from xmLsax.handler import ContentHandler import pprint

class Xmlparser(ContentHandler): """Programdata from our data base will be parsed asan xml file."'"'

def _init_(self): self.chars = [ ] self.recordings = {} self. recEntry = { }

def startEiement(self, name, attrs): .,.··----•1 """Check which tags to process, and empty the character array""" self.chars = U

if name == 'prog': self. recEntry = { }

elif na me == 'chanurl': self.recEntry['chanurl'] = None

elif name == 'progid': self.recEntry['progid'] = None

elif name == 'st'art': self.recEntry['start'] = None

elif na me == 'end': self.recEntry['end'] = None

elif na me == 'tille': self.recEntry['title'] = None

def endEiement( self, name ): char_string =". join(self.chars)

íf name == 'prog ': """ldentify each recording by it's progid in the díctíonary. Each scheduled ítem is also a díctionary by itself""' id = self.recEntry['progid'J self.recordings[id] = self.recEntry

Each time a start tag is found in the read file , a call is made to the startEiement() method. One can then do a match on the tag's name. Similarly the defEiement() method is called after the closing tag . The file is not checked for proper formatting .

elif name == 'chanurl': self.recEntry['chanurl'] = char_string

elif na me == 'progid': self.recEntry['progid'] = char_string

elif na me == 'start' : self.recEntry['start'] = char_string Characters:

elif na me == 'end': ....,. self.recEntry['end'] = char_string .... ~ ... -----i

elif na me == 'tille' : self.recEntry['title'] = char_string

def characters(self, content}:

Content between two tags can be extracted with a call to this method. We figured out that the array has to be flushed between tags, or the content would contain all parsed text till now.

self.chars.append(content)

def get_programs(self): """Get the list of recordings parsed from the xml-file""" return self.recordings

6.3.6. record.py

P2P PVR Applications 37/ 110

The scheduler has also references to the record .py class. For more details , see the recorder section.

6.3.7. run.py

Here is an example of a class that runs the scheduler. This served as a simple program and a unit test. When running this class a username and password has to be provided as in the following example:

P2P PVR Applications

run.py

#'lusr/bin/python , """Runnable class lo execute the scheduler. Syntax is as follows:

./run.py <username> <password>

The username and password will be used lo fetch the schedule from the data base by calling a php-script on it that generales an xml-file with the schedule.

MK@ Friday May 26th 2006

import sys, os, urllib. codees from scheduler import Scheduler

scriptname = os.path.basename(sys.argv[O)) if len(sys.argv) != 3:

print 'Syntax: ',scriptname.' <username> <password>' sys.exit(O)

url = 'http:/1192.168.204.22/springfield/epg/xml/records_info.php:_. url += '?login=%s?password=%s'% (sys.argv[1], sys.argv[2]) <0111111--~

~

prompt = 'Enter \'y\' for schedule. \'d\' to display queue, \'q\' to quit:' print prompt , command = str.lower(raw_input())

tempfilename = 'test.xml' t = Scheduler() while command != 'q':

if command == 'd': print 'displaying queue: ' t.showQueue()

if command == 'y': file = codecs.open('test.xml', 'r','ascii',"ígnore")

t.createSchedule( file) t. check Threads() file.close

print prompl, command = str.lower(raw_input())

sys.exit(O)

38/ 11 o

The credentials are then used to fetch an xml-file from the EPG

J

In our case the XML-file also has to be parsed to exclude any characters that are not ASCII . Please look in the issues section why it had to be done that way.

This line creates a file handle and converts the input to plain ASCII ignoring unknown characters.

The file could be input from urllib which provides an interface for opening a web-page as a file.

P2P PVR Applications 39/110

lt also contains a simple command line interface to fetch the XML data from the EPG (list of programs to record).

6.3.8. GUI

We had the chance to develop a simple GUI based on run.py. For this we used the WXWidgets cross platform GUIIibrary.

According to their creators WxWidgets is:

"lets developers crea te applications for Win32, Mac OS X, GTK +, X 11, Motif, WinCE, and more using one code base. lt can be used from languages such as C++, Python, Perl, and C#/.NET." [WxWindows, 06]

This simple interface consists on three views, the login form, the media library and the queue

6.3.8.1. Login Form

This simple login form contains the png logo of the system, the username and password text fields and the login button.

Figure 4 - the login form

P2P PVR Applications 40/110

6.3.8.2. Media Library

After the log in is made, a Multiple Document Interface (MDI) form appears. lt contains two tabs, Media Library and Schedule which shows the queue of the recordings and a refresh button.

The Media Library shows the recorded shows and the size in bytes. We have to say that this GUI is very simple and it was completed after the official time we had for the project following the rule of XP which says to optimize and add new features at the end.

• Springfield· User eps r;J§rgj [~~~I.i.iE~J Sct-edWe

1 Refresh J

En,.mpg Golf j'Jews_OI-06-2006_17 _ 45.mPQ GoW _TV _02·06·2006_15_10.mpg Golf _TV _02·06·2006_15_15.mpg Golf _TV _02-06-2006_15_31.mpg Hellmg_02-06-2006_12_25.mpg Honeymooners_OI-06-2006_17 _30 .... Oddasat_02-Q6-2006_11_05.mpo RovfUQiane_02-Q6-2006_16_39.mpg Rovfuolane _02-Q6-2006_16_ 45 .mpg Siste_nytt_02-06-2006_12_00.mpg st opp! 30-{)5-200615 19.mpo st_oppl_30-05·2006 _14 _27 .mpg st_oppi_J0-05--2006 _14 _39. mPQ st_opp!_30-05-2006_15_03.mpg st_oppi_J0-05-2006 _15_19. mpg

Slze 305350164 143008592 1142476 1231588 1187972 164045604 1082504 19302524 4737036 4715040 3336248 1790324 1757236 628296 1679404 1790324

Figure 5- The Media Library GUI

6.3.8.3. Schedule

The schedule tab displays information of the shows to be recorded. Currently the information shown is: time of the show, name and channel. Other information can be added easily in the code but it was kept like this for the sake of simplicity.

P2P PVR Applications

• Springfield: User eps L;J[g]~ Media Library SchedtAe

1 Refresh l nme N..me Channel 2006-06-08 14:25.. . Sprln<jield TV 239. 192.100.49:8208 2006-06-{)9 18:11 .. . Terminal:or 239.192.100.29:8208

Figure 6 - the schedule

6.4. Current issues and future improvements

1

41/11 o

Another issue is using threads in the scheduling application. Since the program only requires one thread for the schedule, there should be a way to avoid using them at all. In our opinion it is more efficient to use a thread and therefore leave room for further expandability. lf a thread for the queue was not used, then one would have to let the loop in the queue to be part of the application. That is not very object oriented. One possible solution that could be explored is the use of an event reactor such as the one provided by the python Twisted Networking Framework.

What also matters is better integration between the parts. We are currently using VLC because it has a lot of functionality and we could never manage to create another player/recorder during the time we had. But it could be possible to look around for a module, or even creating one by ourselves, though it is quite a task for a project on its own.

What is also lacking is an interface for the scheduler. An intuitive and self­explaining GUI matters for a lot of people. Since the application is very modular with classes, then creating an interface should not be too difficult. We just started looking at using wxWindows GUI toolkit, and made a simple client program but a friendlier interface should be done in further development.

P2P PVR Applications 42/ 110

7. BitTorrent Protocol

7.1. lntroduction to Bittorrent

7.1.1. General information

BitTorrent is a protocol for distributing files , especially large ones, such as full-length movies , to multiple people. lt uses parallel download technology, also known as swarming, to enable users to get a file from multiple peers. lt picks a number of peers and downloads the file in parallel from them. While the transfer is still in progress, the client becomes a server of the pieces of file that it got. [Cohen, 03] [Wally, 04]

Peer 1 (seed)

Peer 3 (leecher)

P2P PVR Applications

Figure 7 ·· BitTorrent swarming technology

43/110

Peer4 (leecher)

There is no official centralized repository for BitTorrent files; information on how to get the file is contained in a ".torrent" metafile which has information about the files shared. The metafile points to a tracker which is the server application that keeps track of all the downloaders (or leechers) and seeds (clients who have the complete file but continue uploading it) .

The most common method for the distribution of the torrent metafiles is through sites known as indexes, some of the most famous are:

The Pirate Bay (http://thepiratebay.org/) - The world's largest bittorrent tracker

Mininova (http://mininova.org/)

lsohunt (http://isohunt.com/)

Torrent Finder (http://torrent-finder.com/)- Searches multiple indexes

P2P PVR Applications 44/11 O

' The- P1rate- Bay- Lo m s grandE? B1tTorrent tracker dt?l mundo- Mozdla fnefox ~ ·._::y~

&"CtM~~·~HIIT.m~Al\doJ

• · f/J ~ A tmpJ,......._.aq¡ • O t i:l 1-tltrNilfT~ Plnor'oibvi-culi::l$ Wlrldi;1w$~ Whbw'l

)( DIUblgo ,1. CoQc¡n.. CSS• Cj Fl:rn.. f' I!NQ~M" 0 ~mato1- ...J Milcvliniiwr J/ ()Jtlflll" CJ Rollzr · 1) Too5- Jt Villw ~ · 1 0pbcr'l5- 0 'J'

Qau.c..; pi'"ftl

"'"

l!l "todo D sonrdo Dvlll•o D AI)l•...o• nn D J111;oJ O ovo

[ &11C6pi!llla [[ TenQoSU8JIII I

··~ .JI.TMPirateU.op

Figure 8- The Pirate Bay,

~:::::,···

The most popular bittorrent tracker and index

The difference between a tracker and an index is that the tracker doesn't necessarily show the files being shared while the main purpose of the index is to display and share the information needed to get the file. [Wikipedia, 06]

When a client contacts the tracker, it receives a list of peers that are currently downloading or seeding that same file. This list usually contains the information about 50 peers but it depends on the implementation of the tracker. [BitT orrent, 06]

The main components of a regular BitTorrent file distribution consist of:

• An ordinary web server. • A static "metainfo" file. • A BitTorrent tracker. • An 'original' downloader. • The end user web browsers. • The end user downloaders.

P2P PVR Applications 45/11 o

Web server

metafile

Figure 9 -- Structure of a BitTorrent deployment

7.1.2. Serving files

According to the official BitTorrent protocol specification, to start serving files a host needs todo the following :

1. Start running a tracker (or have one running already). 2. Start running an ordinary web server, such as apache, or have one

already. 3. Associate the extension .torrent with mime type application/x-bittorrent on

their web server (or have done so already). 4. Generate a metainfo (.torrent) file using the complete file to be served

and the URL of the tracker. 5. Put the metainfo file on the web server. 6. Link to the metainfo (.torrent) file from some other web page. 7. Start a downloader which already has the complete file (the 'origin') .

[BitT orrent, 06]

7.1.3. Downloading files

To download a file , a user has to follow these simple steps:

P2P PVR Applications 46/ 110

1. lnstall BitTorrent (or have done so already) . 2. Surf the web. 3. Click on a link to a .torrent file . 4. Select where to save the file locally, or select a partial download to

resume. 5. Wait for download to complete. 6. Tell downloader to exit (it keeps uploading until this happens).

[BitT orrent, 06]

7.1.3.1. Exchanging data

The actual process of exchanging the data works like this:

1. Peer requests file chunk from peer or seed. 2. Peer gets the chunks in parallel. 3. Verifies each chunk using the SHA 1 hash it has on the .torrent

metafile 4. Advertises to all the peers which chunks we received . 5. Send interested request to the peers for the pieces we need.

7.1.3.2. Peer wire protocol

The actual protocol for the exchange of data is called peer wire and it operates directly over TCP. The messages sent to both directions of the peers are symmetrical and look the same. The messages include:

• Handshake • Keep-alive • Choke 1 Unchoke • lnterested 1 Not interested • Have • Request 1 piece • Cancel • Port

7.1.3.3. Piece selection algorithm

The piece selection algorithm líes on the client, and the current implementation in the official BitTorrent client is as following :

1. Choose four random pieces at the beginning. 2. Get the rarest pieces first (the ones that less peers have). 3. Continue sharing in a tit for tat manner, as in the game theory.

P2P PVR Applications 47/ 110

7.1.4. .torrent files

7.1.4.1. Generalities

To start to deploy a file on the web, a static .torrent file has to be created. This file contains information encoded with the bencode format. The key information in this file is:

announce: This indicates the URL of a tracker.

info: A dictionary with the following information

• nam~ : suggested na me of the file. • piece length: number of ~ytes of each piece the file is split into. • pieces: A string containing the SHA 1 hash of each piece

concatenated , the length of each hash is 20 characters long . • length or files (exclusively one) : if length is present then the

download is only one file , it consists of the size in bytes of the file. Otherwise if file is present, it will represent the files in a directory structure.

• path: a list of strings corresponding to subdirectory names, the last one being the name of the file in the single file case or the directory name in the case of multiple files .

[BitTorrent, 06]

7.1.4.2. Bencode format

The information in the .torrent file is encoded in the bencode format. This encoding supports byte strings, lists, integers, and dictionary values. Extensibility of the metadata is guaranteed by the BitTorrent clients by ignoring unexpected keys .

We will proceed to explain the encoding of the values in the next paragraphs.

Byte strings

Byte strings are represented as [length in base ten ASCII]:[string data] . To represent the string "Springfield" we would do itas:

11 :Springfield

P2 P PVR Applications 48/11 o

lntegers

lntegers are encoded as i[integer encoded in base 1 O]e . You can specify negative values but you cannot prefix any value with O. An example encoded number eight would look like:

i8e

Dictionaries

Dictionaries are encoded the following way: d[bencoded string][bencoded value]e. · In arder to represent a bencoded dictionary { banana => yellow, tomato => red} , we would do it like this:

d6:banana6:yellow6:tomato3:rede

Lists

Lists are encoded in the following way: l[bencoded values]e. An encoded list of famous people would look like this:

15: Elvis4: Pele6:Zidane5: Frodoe

The encoded famous people would be ["Eivis", "Pele", "Zidane", "Frodo"].

7.1.5. Tracker's HTTP Protocol

The tracker is a HTTP service that responds to common HTTP GET requests. The requests include parameters that help the tracker in keeping their statistics. The tracker then responds with a list of peers along other bencoded data so it can then start downloading the file .

The most important parameters sent by the client are:

• info_hash: SHA1 hash of the info key in the .torrent file . • peer_id: The unique id for the client, generated by itself. • port: Port the client is listening to. • uploaded: Bytes (usually) sent since the started event. • downloaded: Bytes (usually) received since the started event. • left: number un bytes still to download . • evEmt:

o started first key to send when connected . o stopped to be sent when quitting BitTorrent. o completed sent when the download completes .

The bencoded information received is the following :

• failure reason • interval • min interval • tracker id • complete • inéomplete • peers

o peerid o ip o port

[Theory.org , 06]

P2P PVR Applications 49/11 o

To get a better understanding of the BitTorrent HTTP GET protocol and bencoding we now take a look at an example session. We set up a file in a tracker and download it on four clients in the laboratory.

Request

GET /tracker/tracker.php?info_hash=%93% 15h4%F4% 1 O%F1 %F6%A 1 %EE%85%BCt%CBf%8E2 M%B5Q&peer_id=M3-4-2--c4a000d3d559&port=6881 &key=8bbaec39&uploaded=O&downloaded=O&Ieft=4 7125177 4&co mpact=1 &event=started HTTP/1 .1 Host: 192.168.204.22 Connection : close Accept-encoding : gzip User-agent: Python-urllib/2.4 Response

HTTP/1 .1 200 OK Date: Wed , 24 May 2006 14:44:59 GMT Server: Apache/2.0 .55 (Ubuntu) PHP/5 .1.2 X-Powered-By: PHP/5.1 .2 Pragma: no-cache Content-Length : 84 Connection : close Content-Type : textlplain ; charset=UTF-8

d8 : intervali1800~12:min intervali300e5:peers18: .. ... .. ....... .. .. 1 O:tracker id3: 128e

HEX view of response

O 1 2 3 4 5 6 7 8 9 a b e d e f

0000 00 13 72 6c 64 65 00 01 80 60 9d 9c 08 00 45 00 .. rlde ... · .... E. 0010 01 4c f4 f3 40 00 40 06 2b 32 cO a8 ce 16 cO a8 .L. .@.@.+2 .. ... . 0020 ce 1e 00 50 07 6f6d ?e 1b 9d 13 96 25 ad 5018 ... P.om-.... %.P. 0030 19 20 f1 ce 00 00 48 54 54 50 2f 31 2e 31 20 32 .. ... HTTP/1 .1 2 0040 30 30 20 4f 4b Od Oa 44 61 74 65 3a 20 57 65 64 00 OK .. Date: Wed 0050 2c 20 32 34 20 4d 61 79 20 32 30 30 36 20 31 36 , 24 May 2006 16 0060 3a 30 30 3a 32 38 20 47 4d 54 Od Oa 53 65 72 76 :00:28 GMT..Serv

P2P PVR Applications

0070 65 72 3a 20 41 70 61 63 68 65 2f 32 2e 30 2e 35 er: Apache/2.0 .5 0080 35 20 28 55 62 75 6e 74 75 29 20 50 48 50 2f 35 5 (Ubuntu) PHP/5 0090 2e 31 2e 32 Od Oa 58 2d 50 6f 77 65 72 65 64 2d .1.2 .. X-Powered-00a0 42 79 3a 20 50 48 50 2f 35 2e 31 2e 32 Od Oa 50 By: PHP/5.1.2 .. P OObO 72 61 67 6d 61 3a 20 6e 6f2d 63 61 63 68 65 Od ragma: no-cache. OOcO Oa 43 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 3a .Content-Length : OOdO 20 39 30 Od O a 43 6f 6e 7 4 65 6e 7 4 2d 54 79 70 90 .. Content-Typ OOeO 65 3a 20 74 65 78 74 2f 70 6c 61 69 6e 3b 20 63 e: text/plain ; e OOfO 68 61 72 73 65 74 3d 55 54 46 2d 38 Od Oa Od Oa harset=UTF-8 .. .. 0100 64 38 3a 69 6e 74 65 72 76 61 6c 69 31 38 30 30 d8:intervali1800 0110 6531323a6d696e20696e74657276616c e12:mininterval 0120 69 33 30 30 65 35 3a 70 65 65 72 73 32 34 3a cO i300e5:peers24:! 0130 a8 ce 1e 1a e1 cO a8 ce 16 1a e1 cO a8 ce 15 1a ............... . 0140 e1 cO a8 ce 181a e1 31 30 3a 74 72 61 63 6b 65 .:..:..:.:..:..10:tracke 0150 72 20 69 64 33 3a 31 33 35 65 r id3:135e

Sample of a HTTP session in our Labs

50/11 o

As we see in the table, the peers value in this case is not returning a dictianary af the peers but instead a string cantaining the IP and part af the peers. In this case , the value cO a8 ce 1e 1a e1 cO a8 ce 16 1a e1 cO a8 ce 15 1a e1 cO a8 ce 18 1 a e 1 corresponds to our client machines sharing the file .

The natatian is: each 6 bytes represent a peer, the first 4 bytes represent the IP in network byte arder and the last two represent the part, alsa in netwark byte arder. This happens because we sent the campact flag in the HTTP request ta the tracker.

CO a8 ce 1 e 1 a e1 COa8cc161ae1 CO a8 ce 15 1 a e1 cO a8 ce 18 1a e1

192.168.204.30:6881 192.168.204.22:6881 192.168.204.21 :6881 192.168.204.24:6881

The table abave shaws the client machines sharing the file in aur lab in bath numbers and dats natatian and in netwark byte arder.

P2P PV R Applications 51/ 11 o

7 .2. Current alternatives

Peercast

Peer-to-peer, centralized , multisource downloading, no data is stored in the computer, we just get streams. This solution is not good for the project as we want to create a database of all the programs shown on TV ever. lt also lacks an EPG.

Gnutella .

Lacked documentation, the development section of the official webpage is under construction .

Direct Connect

lt lacks swarming capabilities, partly centralized .

Bittorrent

We focused on the BitTorrent platform as it was recommended in the initial meetings with Telenor. Because of the open nature of BitTorrent, many clients have been developed, and many are open source.

Sorne of the other cl ients we analyzed are: ABC, Azureus, BitComet, Bitlord , BitT ornado, BitSpirit, Gnome-BitT orrent, JJTorrent.

Democracy

Democracy is a multiplatform program that uses BitTorrent, Python and VLC, the same components that we used . lt has a nice graphical interface but lacks recording capabil ities and a more complete EPG, partially because it is focused on publ ishing the content created by the users, not the one broadcasted by Television companies.

P2P PVR Applications 52/11 o

7.3. Original BitTorrent Client

7.3.1. Reasons

We chose the original BitTorrent client because it was updated, it followed the standards and it is written in python which is easy to read .

The definition of the BitTorrent client according to the official website is:

"The BitTorrent Client is software used for downloading and uploading files with the BitTorrent format. The client has a too/ for searching for torrent files, uses those files to download data, uploads data to other clients looking for the file, and has a utility for making torrents of your own. The client a/so /ets you see detailed information about the files you are downloading and uploading. " [BitTorrent, 06]

BitTorrent : 100.0%: Rovfugtane_02 06 -2006_16_ 45.mpg GJ[g]LEJ Eie ~iew !jelp

illQJ MaxiiTU!l upload rote: 198 KB/s (El)

Rovfuc;¡i«le _02-o&-2006 _16 _ ~5 . mPQ

~ lllllllllllllmlllll!lmiiiiiii!IDDIIIIIIIIIIIIIJ ~ ~ ~load rate: O KB/s Oowrioad rote : O KB/s

V

Figure 10- the BitTorrent GUI

We found the cede of the client very well separated and programmed using object orientation. This preved to be useful in our cede as well as we could take advantage of unit testing, this means, testing each individual module befare putting it all together.

The cede of the main program was located in the files:

• Bittorrent.py- Main GUI client. • Bittorrent-console.py- Console version of the BitTorrent client. • Bittorrent-curses.py- curses version of the BitTorrent client.

P2P PVR Applications 53/ 110

Other classes that we used the most were:

• PiecePicker- To make the sequential downloads. • Makemetafile- To create the .torrent metafile.

7.3.2. Functioning

In our project, part of the requirements was that we could watch the file within 1 O seconds after launching the application. This could not work with the normal piece selection algorithm as we needed a sequential download in arder to watch the file as a stream.

7.3.2.1. Putting in order the pieces to retrieve

The first thing that we had to change in the BitTorrent client was this. Our solution was simple yet functional but with some factors that could make it fail , we will discuss them afterwards.

The piece picking algorithm was made in the BitTorrent client by the class PiecePicker.

The code that we did not need in this case was the rarest piece selecting algorithm and the random piece selection for the first four pieces (file PiecePicker.py lines 120-130).

for i in s: if havefunc(i):

if self.numinterests[i] < bestnum: bests = [i] bestnum = self.numinterests[i]

elif self.numinterests[i] == bestnum: bests.append(i)

if bests: return choice(bests)

choose random píeces until píeces got ís greater than 4 íf self.numgot < self.config['rarest_fírst_cutoff]:

Then in arder to queue the pieces in sequential arder we had to modify the code from line 131 to 135; the end result was the following :

íf True:

for i in self.notscrambled: if havefunc(i):

return i return None

7.3.2.2.

P2P PVR Applications 54/ 110

Channel surfing capability

In our mod.ified BitTorrent client, we added the feature of viewing the file after a small percent or amount of bytes of the transfer was done. This would enable the client to see the file just after starting the download , like a regular digital TV.

The added code in the client was inserted in the _SingleTorrent class line 545 to 560 of the download.py file .

if r['fractionDone'] >= 0.02 and self.fileisplaying == False: self.fileisplaying = True print "more than two percent, í guess we can play", self.fílename if os.name == 'nt':

self.pathvlc = os.path.abspath('C:!Program FilesNideoLANNLC/vlc.exe') self.pathfile = os.path.abspath(str(self.filename)) self.pathfile = "" + self.pathfile + "" self.argsforprogram = str( self. pathfile) + --plugín-path="C:\Program

Files\VideoLAN\VLC\plugins'" self.píd = os.spawnl(os.P _NOWAIT,self.pathvlc,self.pathfile,self.argsforprogram)

else: self.pathvlc = os.path.abspath('vlc') self.pathfíle = os.path.abspath(str(self.fílename)) self.pathfile = "" + self.pathfile + "" self.píd = popen2.Popen3(self.pathvlc +"" + self.pathfile)

7.4. PHPBTTracker

We could have used existing trackers available on the Internet but we would have not been able to access direct information about the torrent files to display on the EPG. Therefore , we had to install our own tracker.

PHPBTTracker is an open sourced BitTorrent tracker and index written in PHP that uses a web server and a database to display the statistics about the peers, seeds, leechers, downloads among other things. The tracker is used to assist communication between peers sharing files with the BitTorrent protocol. An index is a list of .torrent files. Our EPG uses the information of this tracker statistics and displays them online.

P2P PVR Applications 55/1 1 o

7 .5. Current issues and future improvements

The current state of the system has severa! issues that need to be taken into account.

• Testing

The system should be thoroughly tested as we only had the time to test it with a small number of computers. Usage of more computers, virtual machines (VMware,BOCHS) or software simulations should be considered in the future. Besides, we did not test it on a regular DSL network due to lack of time.

• New developments

The BitTorrent protocol is evolving fast. The next big update should be taken into account. The use of trackerless BitT orrent deployments should be considered 1n future developments.

P2P PVR Applications 56/1 1 o

8. Electronic Program Guide

8.1. Required features

According to Wikipedia , "an electronic program guide (EPG) or also an interactive program guide (IPG) or electronic service guide (ESG), is an on­screen guide to scheduled broadcast television programs, allowing a viewer to navigate, select, and discover content by time, title, channel , genre, etc, by use of his remate control , a keyboard or even a phone keypad". [Wikipedia, 06]

To be more general , here are the features usually provided by an EPG:

• Display shows: through a Graphical User Interface (GUI) , information about all broadcasted shows on every available channel.

• lnteractivity: the users can access further information about the program of their choice.

• Search engine: it allows the EPG to display a specific type of shows, according to the users' interests.

An additional feature that interests us a lot is the interactivity with a Personal Video Recorder (PVR). lf the EPG is connected to a PVR, then users are able to schedule the shows they will watch and/or record .

P2P PVR Applications 57/ 110

8.2. Current alternatives

8.2.1. lnformation source

There are not so many ways to fetch information about the programs displayed on the different channels. The most common is XML TV.

8.2.1.1. XMLTV

XML TV is a set of utilities to list TV programs. lt is maintained in a SourceForge.net repository. The current version of it is 0.5.43 released on April 23, 2006. lt is distributed under the GNU General Public License. XML TV is very widely used and externa! applications have even been created around it, the most known of them being MythTV.

The information is in a XML TV format based on the traditional XML; hence a OTO (Document Type Definition) file is associated to the output. This OTO file is used to ensure the homogeneity of the output, so that programs using this information can always fetch and treat it the same way. The file xmltv.dtd is available in Appendix D.

Different grabbers were created to fetch program listings for several countries. They were programmed in Perl by independent contributors. These grabbers must be configured befare being used, mainly by selecting the channels that will be displayed . Once set up, a grabber can be called and starts fetching the TV listing according to its configuration. XML TV has some filters to select only a certain category of program. The users also have the possibility to write the output to a file (whereas only displaying it on a terminal) and choose a range of days to display.

Below is an example with the Norwegian grabber 'tv_grab_no' on a Linux platform. Once XML TV is correctly installed, the first thing to do is to execute the following command :

-$ tv-grab-no -configure

This launches a script asking the user about which channels he wants to list. This setting is kept in a configuration file (default is -/.xmltv/tv_grab_no.conf) .

P2P PVR Applications 58/ 11 o

The main function can be called:

-$ tv-grab-no -output FILE -days N -offset M --quiet

This function fetches information about the programs from the channels specified in the configuration file. lf -output FILE is specified, the process writes to the file 'FILE'. The u ser can al so choose the number of days to display (by -days N, the default being the maximum available) and starts M days in the future (with --offset M, the default being 0). The --quiet option prevents XML TV from displaying error messages. The grabber 'tv_grab_no' can usually provide information for around tour days.

8.2.1.2. Other solutions?

Unfortunately, there are not so many alternatives to XML TV if we want to get this kind of information. One would be to directly look for the sources used by the grabbers. But in most cases , this would require special authorization, and may require heavy processing of data involving regular expressions.

A project called RSSTV was running in 2004 but it seems it did not lead to anything . The aim was to have the XML TV information in RSS Feeds in order to provide syndication for PVR. lf the use of RSS feeds in this domain ever shows results then it would be worth looking deeper into it.

8.2.2. Storage

To store information, there are two main solutions: to use XML files or a Database Management System.

8.2.2.~. XML Files

The storage in XML files consists of saving data in a text format in a markup language. XML (eXstensible Markup Language) is a meta-language able of describing data. The users can define their own tags, according to the nature of the data to store.

P2P PVR Appli cations

Below is an example of an xml file :

<?xml version="1.0" encoding="UTF-8"?> <media_ center>

<book id="1"> <title>Da Vinci Code</title> <author>

<familyname>Brown</familyname> <firstname>Dan</firstname>

</author> <date>2003</date>

</book> <book id="2">

<title>Rainbow Six</title> <author> ' <familyname>Ciancy</familyname>

<firstname> Tom</firstname> </author> <date> 1999</date>

</book> <dvd id="1">

<title> Lost - season 1 </title> <date>2004</date>

</dvd> </media_center>

Example of an XML file

59/ 110

Very often, a OTO file is associated with it, in arder to give the specifications that must be followed by the xml file . The same feature is also provided by XML Schema Oefinition, newer than OTO and also more powerful.

An advantage of using XML files is that it does not require any heavy structure on the server. lt does not require any specific application to work with as well. Also, associated to a XSL (eXstensible Stylesheet Language) file , the XML file can be easily displayed thanks to XSL Transformations.

However, XML files may not be the most appropriate solution for huge quantities of data. Moreover, they use a hierarchical model to represent their data, which is limited compared to the relational model.

8.2.2.2. Database Management System (DBMS)

A database management system is a set of programs "that controls the organization , storage and retrieval of data (fields, records and files) in a database" [Wikipedia , 06] . Several models of organization exist but the relational model is used for its performance and features. Moreover, it fits very well in our system, where we needed for example to establish a link between users and the programs they want to see.

P2P PVR Applications 60/110

Originally created to be a standard for relational databases, the SQL standard has become a category by itself. MySQL is a widely used SQL Database Management System and is very practica! because APJs have been created for it in many programming languages.

Databases have the advantage of being able to handle big quantities of data. The Greation of indexes in the tables proves to be very useful when it comes to retrieve information. With databases, the realization of a search engine is easier than with XML files .

8.2.3. Display

Once we get all the information about the programs, we still need to make them accessible for the users.

8.2.3.1. lntegrated to the client

A first solution can be a direct integration of the displaying module into the client application. This may be done in any programming languages, but in a concern of integration, it would be better to do it in Python. lntegrating directly into the client application would require two main features:

• The possibility of fetching and sorting the information: regarding the storage mode, it would be either parsing XML files or sending request to a database.

• An intuitive user interface: the users must be able to access the information easily, and a search engine should be there to allow them to display their favorite programs.

Even if it can be done otherwise, object-oriented programming would be more appropriate in our case to make the integration and the debugging easier.

8.2.3.2. Webpage

Another soÍution is to create a webpage where the users can connect and perform searches. Since we need a dynamic display of content, we will need programming languages to generate dynamic content in XHTML.

XML and XSLT

In the case of saving data in XML files , a good way of displaying the information is using XSL T. XSL T stands for eXstensible Stylesheet

P2P PVR Applications 611110

Language Transformations. To use it, an XML file containing the information is required, as well as a XSL stylesheet andan XSLT processor.

The XSL T processor takes the XML file and transforms it according to the template rules collection defined in the XSL stylesheet. The output file can be in many different formats, but the most common are XHMTL or XML.

Here is a scheme describing the functioning of a XSL T Transformation:

XSL stylesheet

Output (in XHTML Input file in XML for

Figure 11 -- XSL T Transformation scheme

PHP

PHP is certainly the most widely used programming language in web and server-side applications. lt is polyvalent, interacting with numerous relational database management systems. Whatever the storage format is (XML files or database), PHP handle very well the retrieving of data, thanks to its efficient XML parser and its libraries interacting with DBMS.

8.3. XML TV, Database and Webpage

8.3.1. Reasons

To implement our EPG, we have adopted the combination XML TV, a database and a webpage generated in PHP. Several reasons have led us to choose these solutions.

XML TV has been chosen as the source of information mainly because it was the easiest option to handle and is open source; The XML format is quite simple to parse so it helps a lot to retrieve the information needed. Moreover, the XML TV community is well spread, and updates are common, since it is maintained in a SourceForge open source repository.

P2P PVR Applications 62/11 o

Since we collect the information in XML format, it would not have been senseless to store it in XML files . In our case, the problem comes from the amount of data to store. We have information about programs for 7 channels to store every day. To have an idea of the size needed, one full day of programs on these 7 channels would require approximately 200 entries. Furthermore, the good performance of databases in retrieving and sorting data is precious as we want to create a search engine.

As for the display module, mainly for a reason of competence and time to achieve the project, we decided to do it with a webpage. Each of the available solutions has its advantages and drawbacks, and in the end they were worth trying to implement.

Because some of us already knew about web programming and because we did not have so much time to create a complete module in Python or any other programming language, we chose this webpage approach. Moreover, this solution revealed another advantage. As long as the client application is running , the user can access the EPG from everywhere and schedule its recordings.

We have chosen to use mainly PHP as the programming language because it is one of the references for generating dynamic content and it provides a very good management of MySQL for queries and results processing .

8.3.2. Functioning

In the next' lines, the functioning of the whole EPG is described, and the interactions between the different functions are highlighted.

8.3.2.1. Configuration settings

The web server is installed on a Linux platform. We installed version 2 of Apache, version 4.1 of MySQL and PHP5. During the project, we have also used phpmyadmin for its clear representation of the databases. All files related to the EPG have the path /var/www/springfield/epg/ as root. The database is the same as the one used for the tracker (springfield) because it is simpler to perform queries inside a same database.

XML TV's grabber tv_grab_no is configured to fetch the programs for the required channels: NRK 1, NRK 2, TV 2, BBC World , Canal+, TVNorge and Canal+ spo,rt.

P2P PVR A pplications 6311 1 o

The database design for the EPG is represented by the following scheme, generated by DBDesigner 4.

channels chanld: INT(lD)

<> chanName: VARCHAR(50) ..; chanUrl: VARCHAR(25) v chanWeb: VARCHAR(50)

Rei_Ol

~

programs 1 V progld: INT(lD) ~ chanld : INT(lD) (FK ) ~ start : VARCHAR(14 ) O end: VARCHAR(14)

titleNo: VARCHAR (64 ) '> titleEn: VARCHAR(64 ) -.. dese: TEXT

episode: VARCHAR(16) v status : ENUivJ ( 'O', '1') ,j chan!d

o chanld .,?j stalt

Sti.ll t

records Rei_02 V login : VARCHAR(16) (FK)

___A 'iJ progld: INT(lO) (FK) ..,_,.--- ~ recordStatus: ENUM('0', '1 ', '2') 1

..,.) ¡JrOg1d l.

V progld

1 Rei_03

t :~s~~s-- ------------------~ 1 : \} login: VARCHAR(16) i ' 1

~~}l_a_:s_w~~~~Y-~~~~~~~~~).J

Figure 12 -- EPG Database Model

8.3.2.2. Getting the TV listing

To get the TV listing , we simply need the following command line:

-$ tv_grab_no --quiet --output /var/www/springfield/epg/xml/tvprog.xml

The Norwegian grabber of XML TV gets all the programs available and the output is stored on the web server.

Here is an extract of an example of file tvprog .xml. lt gives a better idea of what inform'ation is provided :

<tv so u rce-i nfo-url=" h ttp :1 /fredag. d ag bladet. no/tv !" url="http://fredag.dagbladet.no/tv/" generator-ínfo-name="XML TV" url="http://membled.com/work/apps/xmltvf'>

<channel íd="nrk1 .nrk.no"> <display-name>NRK 1 </dísplay-name>

</channel> <channel id="nrk2.nrk.no"> <display-name>NRK 2</display-name>

source-data­generator -info-

P2P PVR Applications 64/ 11 o

</channel> <programme start="20060511 062500 +0200" stop="20060511 093000 +0200"

channel="nrk1 .mk.no"> <title lang="no">Frokost-TV</title> <dese lang="no">M0t dagen med nyheter hver halvtime, aktuelle gjester. filmer for de

minste, praktiske tips, underholdningsstoff og mye mer.</dese> </programme> <programme start="20060511100000 +0200" stop="20060511100500 +0200"

channel="nrk1.nrk.no"> <title lang="no">Siste nytt</title> <dese lang="no">fra Dagsrevyredaksjonen. </dese>

</programme> <programme start="20060511140500 +0200" stop="20060511153000 +0200"

channel="nrk2.nrk.no"> <title lang="no">Svisj chat</title>

</programme> </tv>

Example of a tvprog.xml file

8.3.2.3. lnserting it into the database

To insert the information from the file tvprog .xml into the database, we call the function fetch_programs.php situated on the web server in /springfield/epg/process/. This function works thanks to the integrated XML parser in PHP5. The principie is quite simple. First, we need to create a DocDocument element in PHP and we load the xml file in it. Then , we call the main tag of the file, since a well formed XML file must have one.

$tvprog=new DomDocument(); $tvprog->load('/var/www/springfield/epg/xml/tvprog.xml'); $tv=$tvprog->documentEiement;

In the XML file , the channels are referenced by their web address . In the 'programs' table, the channels are identified by their id number. So we need a MySQL query to make the link between the web addresses and the ids . Also, we need a query into the 'programs' table in order to check the last added show for each channel , in order not to insert twice the same program. Then we can start reading the XML file and inserting the data into the data base . The complete code of this function is available in Appendix D.

8.3.2.4. Automating these operations

The task of getting the information about the different programs had to be automated. To do it, we used cron on UNIX. lt is used to execute tasks

P2P PVR Applications 65/ 110

automatically. What we need is first , to schedule XML TV to grab the newest TV listing available, and then to insert the new programs into the database.

Belaw is the file /etc/crontab madified far scheduled these twa tasks:

# /etc/crontab: system-wide crontab # Unlike any other crantab you don't have to run the ·crontab' # command to install the new version when you edit this file. # This file also has a username field, that none of the other crontabs do.

SHELL=/bin/sh PA TH=/usr/locql/sbin :/usr/local/bi n :/sbin: /bin :/usr/sbin :/usr/bin

# m h dom mon dow user command 00 2 * * * root tv_grab_no --quiet --output /var/www/springfield/epg/xml/tvprog.xml 1 O 2 * * * root php /var/www/springfield/epg/process/fetch_programs.php 25 6 * * * root test -x /usr/sbin/anacron 11 run-parts --report /etc/cron.daily 47 6 * * 7 root test -x /usr/sbin/anacron 11 run-parts --report /etc/cron.weekly 52 6 1 * * root test -x /usr/sbin/anacron 11 run-parts --report /etc/cron.monthly #

letclcrontab

Every day, in additian ta the scheduled tasks in /etc/cron.daily , eran executes at 2.00am the Narwegian XML TV grabber and stares the autput in the specific file tvprog .xml , situated an the web server. Ten minutes later, it calls the PHP script fetch_programs.php that parses tvprog .xml in arder ta enter al! the infarmatian inta the data base . .

8.3.2.5. The website

The architecture af the website is quite simple. Every file is lacated in ane falder. This way, when we want to include a file inta another, we can indicate a relative path and be sure that it will be carrectly referenced : we just need ta ga back one level and enter inta the right falder. The falders are the fallawing anes :

• access: contains the files required for authentication and the function add_user.php that we can apen in a web browser ta add a new user.

• db: gathers al! files cancerning the database (creatian , initializatian, connectian) .

• display: contains the main files far displaying the shaws.

• images: al! the images needed are in this falder.

• index: anly cantains the index.php file .

P2P PVR Applications 66/110

• process: contains different PHP scripts that interact with the database for updating it (for example, fetch_programs.php).

• script: this folder contains JavaScript scripts.

• style: contains the CSS file of the site.

• xml: this is where tvprog.xml is saved as well as its associated OTO file.

There is also a PHP script, records_info.php, called by the scheduler for generating an XML output containing information about the scheduled records for a user.

The website has an authentication system. Allowed users are registered into the table 'users' and their passwords are encrypted by the cryptographic hash function M05. The website uses session so that a user does not need to enter his username and password each time he changes of page.

Once logged in, the main window is presented to the user. The next figure shows the main web interface:

t} J'lrOJf!CI ~prtn&flch1 IIE!c:ltonu: Pu1er.:tm Ciuldc Monlld rlr~fox C \~¡ rRJ . . . (/)

Chinnel: A!l "' 11 From: 11-Q5-2006 .., OH v to: 12-Q5-2006 .., 11 h v 11 Tltle:

Confnm IKOidina, lllogout

:····-------··----------····::···························::·········-·····-·-·········::·······-······--···········::···························:r················ ··-········::············-··············:

iNRK 1 Ji NRK 2 ¡rv 2 ii BBC World ¡· canal+ .ITVNorge ¡¡ canal+ sport ¡

j1t621M ll11-f5..lll6 f 1-15-ZII6 ¡t-15-2116 ¡¡11-IIJ-:leM ¡¡11-t'J-1116 t1-tS-2tM ~

¡•11., .,.,. ¡¡ tt••·ttiiJif ~ -~~~~ .,.,,. jj•••·••• ¡¡•"" ., .. ., ¡¡•••-u•• ~ ttlll• · ttlll41 l ¡rrokos t-TV ~Svlsj ch•t ~ God morgen Norge i[ BBC News ¡jN.ng Nak jjtnteraktlv frokost E Golf TV Weekd¡ys ¡ im :; iiEJ ¡: ::m !iw ~ ~~~ :

!~::.. .e::.· ~~~~~{~~·s le::.. le::.. t::.. t:: .. ¡ ¡¡ Perspekth ~ ¡¡ HARDti!k !! :: ~ :oe gr~ ktigame: For~ndrlng:! ~ !! :,:1,Grlp d~gen -· Salze the O;ry 1.1. O~ te M¡ Mom :; W.Otorwortd ; frvder ;;m :: 11-15-Z~M :: ; ,....,.

Figure 13 -- EPG view

P2P PVR Applications 67/110

The webpage can be dissected into smaller parts, we shall explain in more detail each of the parts of the webpage:

Logo

The lago was created by us just to have it in the layout and see how a website could look if released to the public. The lago preved to be of the liking of all of the people involved in the project.

Figure 14 - The project logo

The name Springfield was the codename for our project as the computers of the lab were named like the characters in the popular cartoon series "the simpsons". Below the main letters there is the leyend "p2p television" which describes the use of the system.

lnside the letters "p", "g" , and "d" there are semicircles of hex color #eaffOa. On the top of letters "i" there are semicircles of hex color # 01 e6fa. These semicircles represent the peers that are gathered and sharing the TV which is at the right side of the lago.

Search Form

A search engine allows the users to choose the channel(s) and the scope of time to display. They also have the possibility to look for a particular program. The functioning is quite simple: the search engine is ceded with a form in XHTML. To generate the different options, queries are made in the 'channels' and 'programs' tables in arder to know which channels are available and what is the scope available.

Channel: ' All -'-'----

v 11 From: 11-05-2006 ~ ~ to : 112-05-2006 v 11 h v 11 Title: ¡ __ _

Figure 15- Search Form

There are tour criteria available for searching: Channel, from and to date and title of the show.

The results of the form are treated by this page, through a GET method (the results are sent in the URL). This page is therefore programmed to treat them and it displays the shows corresponding to the request. When the user

P2P PVR Applications 68/1 1 o

first accesses the page, it displays automatically all the shows on each channels of the present day.

The overall display is done by main.php in the folder /display/. lt generates the form and calls the function disp located in the same folder, in the file disp.php. This function takes as arguments the results of the form , and displays the selected shows. lt also calls the sub function disp_chan that performs the same action for one specific channel.

Channel and program view

Another feature of this EPG is displaying the options available for each program. The function disp_chan checks for every show the field 'status' in the table 'programs'. lf th is is set to 1, then it means a torrent file is available and the EPG gives a link to download this torrent. lf it is set to O, then the current time is compared to the start time of the show. When the show is currently broadcast, nothing is displayed . Else, a red record button is accessible.

,. ~- • • • • • • •-- • • •---- • • • • • • • • • .,,. • • • • •- • • • • • • • • • • • •-- • • • • • •- .,,. -- • • •--- • • • • •--- •- • • • •-- • • • ., r -- •-- • •--- --- • •- •- •- '. • • • • •- .,,. • • - •-- • • • • • • • • • • ' " " " " 1 " " " "

' " " " " 1 " " "

!NRK 1 !! NRK 2 !!TV 2 !! BBC World !! Canal+

: 11 · 0 ~-2006 :: 1 1-0~-2006 :: 1 '1-0~-2006 :: 11 -0 ~-2006 :: 1 1 -0~- 2006

: 06 h 25 · 09 h JO :: ~<t h 05 · ~S h JO :: 06 h :Z5 - 09h JO :: 05 h 00 · 05 h JO :: 05 h 20 · 07 h 00

; Frokost-TV ¡¡ Svisj chal ¡¡ God margen No rge :: BBC News ¡¡Nang Nak

- ::e : : 11-0~ -2006

¡¡ Morgensending. Nyl1eter og ¡¡ 11 _0~_ 2006 :: V!Prmelding hver he/e og ::

::hotve time. Mete med !i .. h 10

.06

h 00 ¡¡ ai<tuel/e gjester.

:: 11 -0~- 2006 : 11 - 0~-2006

:: i 5 h 10 - t6 h m

:09 h JO · tohoo :: 07 h 00 - 08h )!i

:: Pe rspektiv :: HARDtalk

Figure 16 - Channel and program view

The recording management is done using an AJAX (Asynchronous JavaScript And XML) approach. Thanks to it, when the user clicks on the record button, the whole page is not reloaded. Only the record button changes to yellow and an option to cancel the recording becomes available.

At the same time, a background process is executed. An entry in the 'records' table is created, associating the log in of the connected user to the id of the chosen program. The record status is initially set to O, meaning that the user still needs to confirm his choices. lndeed , once the user has selected the shows he wants to record and/or see, he needs to click on

P2P PVR App lications 69/ 1 10

"Confirm records", so that the status of every new entry in the 'records' table is set to 1.

Interna! and administration functions

Access

Add_user.php

The file add_user.php adds a new user to the EPG.

add_user.php

<?php $message="Complete all fíelds." ;

if(isset($ _POST[' login']) && isset($ _POST[' pass']) && isset($ _POST['pasFs2=-'lL.L..<)) )....____{ ___ .........__--. $1ogin=$_POST['Iogin']; .............. ~ $pass=$_POST['pass']; ~ $pass2=$_POST['pass2'] ;

..... require_once(' . ./db/connect.php'); ~

$query="SELECT 'login' FROM users WHERE 'login'='$1ogin'"; $result=mysql_query($query) or die ("lnvalid query ".mysql_error()) ; if($row=mysql_fetch _ array($result) ){

$message="Login already taken."; } el se{

if($pass==$pass2){ $hash=md5($pass);

Requires the login information to be passed via post requests .

The database connection code is separated in the db folder in the

..._ connect.php file

$query="INSERT INTO users SET 'login'='$1ogin','password'='$hash"'; $result=mysql_query($query) or die ("lnvalid query ".mysql_error());

} ?>

echo "<a href=' . ./index/index.php'>Back to main page</a>"; fmessage="Add another user."; '

el se{ $message="Passwords don't match. Try again.";

} } mysql_close();

<div class="error"><?php echo $message;?></div> <div class="form">

<form method="post" action=" . ./access/add_user.php"> <p>

The password is stored as a MD5 hash, this is the Standard procedure for storing passwords.

<label for="login">Login: </label><ínput type="text" name="login" maxlength=16 /> </p> <p>

P2P PVR Applications 70/11 o

<label for:;:"pass">Password: </label><input type="password" name="pass" /> </p> <p>

<label for="pass2">Confírm password: </label><input type="password" name="pass2" />

</p> <p>

<input type="submit" value="Add user" /> </p>

</form> </div>

P2P PVR Appl icat ions 7 1/1 10

auth.php (authentication form)

The authentication form posts the required information to lag in to the website.

<div class="form"> <form method="post" action= ... ./index/index.php?pg=verif'>

<p> <label for="login">Login : </label><input type="text" name="login" />

</p> <p>

<label for="pass">Password : </label><input type="password" name="pass" /> </p> <p>

<input type="submit" value="Connect!" /> </p>

</form> </div>

logout.php

The logout.php file destroys the session and redirects the user to the index page.

<?php session_ start(); unset($ _ SESSION['Iogin']); session _ destroy(); header(' Locatíon: . ./í ndex/index. ph p');

?>

verif.php

This file verifies that the user is logged on and regenerates the sessionid if the information is correct, otherwise an error page is displayed.

<?php if(isset($_POST['Iogin']) && isset($_POST['pass'])){

$1ogin=$_POST['Iogín']; $pass=$ _POST['pass'];

include(' . ./access/verification.php');

if(verification($1ogin,$pass)){ sessíon_regenerate_íd();

$_SESSION['Iogin']=$1ogín; $page = 'main';

} el se{

} } else{

$page = 'auth_fail';

$page = 'au.th_fail'; }

P2P PVR Applicat ions 72/1 1 o

?>

verification.php

This file includes the verification function which compares the submitted logon credentials to the ones stored in the database.

<?php function verification($1ogin,$pass){

}

require _once(' . ./db/connect. php');

$query="SELECT "login· ,' password' FROM users WHERE "login '='$1ogin"'; $result=mysq1_query($query);

if($row=mysq 1_ fetch_ array($result) ){ $hash=$row[ 1 ];

if(md5($pass )==$hash ){ return true;

} el se{

return false; }

} el se{

return false; }

mysql_ el ose();

?>

Databas e

Connect.php This file is included on almost all of the others; it is called each time a connection to the database is needed.

<?php $username='toto'; $password='titi' ; $database='springfield' ; $hostname='localhost';

P2P PVR Applications 73/11 o

connect.php

$db=mysql_connect($hostname,$username,$password) or die("Can't connect to database: ".mysql_error());

mysql_select_db($database) or die("Can't select database: ".mysql_error()) ; ?>

P2P PVR Applications 74/ 11 0

create_tables.php

This is the script that is used for the setup of the database, it creates the structure with SQL queries.

<?php require_once('connect.php');

1/TABLE 'channels' $query="CREATE TABLE 'channels· (".

"'chanld' INT (10) NOT NULL AUTO_INCREMENT,". '.''chanName· VARCHAR (50) NOT NULL," . "'chanUrl' VARCHAR (25) NOT NULL , ". "'chanWeb' VARCHAR (50) NOT NULL , " . "PRIMARY KEY('chanld') )";

$result=mysql_ query($query) or die("! nvalid query". mysql_ error());

liT ABLE 'programs' $query="CREATE TABLE ' programs· (" .

"'progld' INT (10) NOT NULL AUTO_INCREMENT,". "'chanld' INT (10),". "'starf VARCHAR (14) NOT NULL,". "'end' VARCHAR (14) NOT NULL,". "'titleNo' VARCHAR (64) NOT NULL,". "'titleEn' VARCHAR (64) NULL DEFAULT NULL,". "' dese· TEXT DEFAULT NULL,". "'episode' VARCHAR (16) NULL DEFAULT NULL," . "'status· ENUM ('0','1') NOT NULL,". "PRIMARY KEY ('progld'),". ~FOREIGN KEY ('chanld') REFERENCES channels('chanld') ON

UPDATE CASCADE ON DELETE SET NULL,". "INDEX ('chanld'),". "INDEX (' starf) )";

$result=mysql_query($query) or die("lnvalid query".mysql_error());

IITABLE 'users' $query="CREATE TABLE ·users· (".

"'login' VARCHAR (16) NOT NULL," . "'password· VARCHAR (32) NOT NULL,". "PRIMARY KEY ('login'))";

$result=mysql_ query($query) or die("l nvalíd query". mysql_ error());

liT ABLE 'records' $query="CREATE TABLE ·records' (" .

"'login' VARCHAR (16) NOT NULL," . "'progld' INT (10) NOT NULL,". "'recordStatus· ENUM ('0','1'.'2') NOT NULL,". :'PRIMARY KEY ('login·,·progld'),". "FOREIGN KEY ('login') REFERENCES users('login') ON UPDATE

CASCADE ON DELETE CASCAD E," . "FOREIGN KEY ('progld') REFERENCES programs('progld') ON

UPDATE CASCADE ON DELETE CASCADE )";

$result=mysql_query($query) or die("lnvalid query".mysql_error());

P2P PVR Applications 75/ 110

mysql_close();

?>

P2P PVR Applications

init_tables:php

This script fills the database with sample data.

<?php require_once('connect.php');

//lnítialisation of the table 'channels'

76/11 o

$chanNames=array('NRK 1','NRK 2','TV 2' ,'BBC World','Canai+','TVNorge','Canal+ sport');

$chanWebs=array('nrk1.nrk.no','nrk2.nrk.no','tv2.no','world.bbc.co.uk','canalplus.can alplus. no', 'tvnorge. no' ,'sport.canalplus.no');

$chanUrls=array('239.192.1 00.49:8208', '239.192.1 00.50:8208', '239.192.1 00.52:8208', '239.192.100.20:8208' , '239.192.1 00.12:8208', '239.1 92.1 00.56:8208'' '239.192.1 00.46:8208') ;

$1=count($chanNames );

for($i=O;$i<$1;$i++ ){

$chanName=utf8_encode($chanNames[$i]); $chanWeb=utf8 _ encode($chanWebs[$i]); $chanUrl=utf8_encode($chanUrls[$i]);

$query= "INSERT INTO channels SET e han ld='NU LL', e han Name='$chanName' ,chan Url='$chan Url', chanWeb='$chanWeb'";

$result=mysql_ query($query) or die("lnvalid query". mysql_ error());

}

mysql_close(); ?>

P2P PVR Applications 77/ 1 10

Display

The two following functions are very important since they are in charge of displaying the TV listing.

disp.php

This file will generate the html , puttirig the right information into the program span. lf the file is being shared , this will put the information from the tracker.

<?php

//Convert date from YYYYMMDDHHMMSS format to date 'DD-MM-YYYY' and time 'HH h MM'

function date_conv($date){

if(strlen($date)!=14){ echo "lnvalid argument in date_conv function: Must be

YYYYMDDHHMMSS format.";

nd);

} el se{

$year=" ;$month=";$day=";$hour=";$minute=";$second=";

sscanf($date,"%4s%2s%2s%2s%2s%2s",$year,$month,$day,$hour,$minute,$seco

} }

return array("$day-$month-$year","$hour h $minute");

//Display one specific channel (indicated by its id Schan) function disp_chan($chan ,$from_date,$from_time,$to_date,$to_time,$title){

$deadline=3; //in minutes, time margin befare the program where the user cannot record.

//Fetch channel name $query="SELECT 'chanName· FROM channels WHERE 'chanld'='Schan"'; $result=mysql_query($query) or die("lnvalid query ".mysql_error()); $row=mysql_fetch _ array($result);

echo "\t\t\t\t\t\t<h1 >".utf8_decode($row['chanName'])."</h1 >\n"; echo ''\t\t\t\t\t\t<hr />\n";

//Fetch programs $from=$from_date.$from_time; $to=$to_date.$to_time;

$query="SELECT * FROM programs WHERE " . ' "'chanld'='$chan'".

if($title!="){

"ANO 'start'>='$from' ''. "ANO ·start'<='$to' ";

$query.="AND ('titleNo'='$title' OR 'titleEn'='$títle') "; }

B\Bl\0\ECA UNWERSIDAO DE MON1ERREY

P2P PYR Applications

//Perform query

$result=mysql_query($query) or die("lnvalid query ".mysql_error());

//Results treatment while($r'ow=mysql_fetch_array($result)){

//$row=array_map(utf8_decode,$row);

$progld=$row['progld'];

$start=$row['start'];

$dat=date _ conv( $start); $day=$dat[O]; $start_time=$dat[1];

$end=$row['end']; $dat=date_ conv($end); $end_ time=$dat[1];

$status=$row['status'];

echo "\t\t\t\t\t\t<h5>$day</h5>\n"; echo "\t\t\t\t\t\t<h6>$start_time - $end_time</h6>\n";

$title=$row['titleNo']; $titleEn=$row['titleEn']; if($titleEn != 'NULL'){

$title.=" -- $titleEn"; } $title=stripslashes($title) ; echo "\t\t\t\t\t\t".$title."<br /><br />\n";

$desc=$row['desc']; if($desc != 'NULL'){

78/ 110

echo "\t\t\t\t\t\t<input type='image' src=' .. /ímages/open.gif alt='Show description' id='disp$progld' onCiick='dísplay_desc($progld);' /> \n";

$desc=strípslashes($desc);

}

echo "\t\t\t\t\t\t<span id='desc$progld' style='display:none'>\n"; echo "\t\t\t\t\t\t\t<em>$desc</em>\n"; echo "\t\t\t\t\t\t</span><br />\n";

//Display the actíon available

P2P PVR Applications

echo "\t\t\t\t\t\t<span id='prog$progld'>\n";

I!We check the status $1og in=$_ SESSION['Iogin'];

if($status == O){

79/ 110

$status_query="SELECT * FROM records WHERE 'login'='$1ogin' ANO · progld' ='$progld"';

$status _results=mysql_ query($status _ query);

//lf the user already selected this recording if($tab=mysq !_fetch_ array($status _results) ){

$recStatus=$tab['recordStatus'];

//if the client still needs to confirm if($recStatus==O ){

echo "\t\t\t\t\t\t\tProgram selected: <img src=' .. /images/yellow-button.gif' alt='Program selected' /><br />\n" .

"\t\t\t\t\t\t\tDelete from selection: <input type='image' src=' . ./images/delete-button.gif' alt='Delete program from selection' onCiick=\"loadF ragmentl ntoEiement(' . ./process/delete _record. php'. 'prog$prog Id');\"!> \n";

}

//the client already confirmed el se{

echo "\t\t\t\t\t\t\tProgram selected: <img src=' . ./images/green-button.gif alt='Program selected' /><br />\n".

"\t\t\t\t\t\t\tDelete from selection: <input type='image' src=' . ./images/delete-button.gif' alt='Delete program from selection' onCiick=\''loadF ragmentl ntoEiement(' . ./process/delete _record. php','prog$prog Id'); \"1>\n";

}

//The user did not select the recording. el se{

$1imit_date=date('YmdHis' ,time()+$deadlíne*60); //$1imit_date='20060512120000'; //Test

//display the record button when the program is to come

if($start > $1imit_date){ echo "\t\t\t\t\t\t\t<strong>Record</strong>: <input

type='image' src=' . ./images/record-button.gif' alt='Record button' onCiíck=\"load Fragmentl ntoEiement(' . ./process/add_record . php', 'prog$prog Id') ;\" /> \n";

}

}

}

//lf a torrent file is available el se{

$torrent_query="SELECT * FROM namemap N, summary S

P2P PVR Applications

WHERE N.progld='$progld' AND N.info_hash=S.info_hash"; $torrent_result=mysql_ query($torrent_ query);

80/ 110

echo "\t\t\t\t\t\t\t<span id='disptorrent$progld' onCiick =\"display_ torrent('$prog Id'); \">\n";

echo "\t\t\t\t\t\t\t\t<img src=' . ./images/torrent.gif alt='Show torrents' !> Show available torrents\n";

echo "\t\t\t\t\t\t\t</span>\n";

echo "\t\t\t\t\t\t\t<span id='torrent$progld' style='display:none'>\n";

while($row=mysql_fetch _ array($torrent_result) ){

$row=array_map(utf8_decode,$row); $url=$row['url']; $seeds=$row['seeds']; $1eechers=$row['leechers']; . echo "\t\t\t\t\t\t\t\t<a href=' . ./$url' alt='Dowload this torrent

file'><img src=' .. /images/torrent.gif' alt='Dowload this torrent' /> Download this torrent</a><br />\n";

}

}

echo "\t\t\t\t\t\t\t\tSeeds: $seeds<br />\n"; echo "\t\t\t\t\t\t\t\tleechers: $1eechers<br /><br />\n";

} echo "\t\t\t\t\t\t\t</span>\n";

}

echo "\t\t\t\t\t\t</span>\n";

echo "\t\t\t\t\t\t<hr />\n";

//Main displaying function

function disp($chan,$from_date,$from_time,$to_date,$to_time,$title){ if($chan=='all'){

echo "\t\t\t<table cellpadding=O cellspacing=O>\n";

$query="SELECT 'chanld' FROM channels ORDER BY 'chanld'"; $result=mysql_query($query); echo "\t\t\t\t<tr>\n"; wh i le( $row=mysq !_fetch_ arra y($ res u lt) ){

$id=$row[O); echo "\t\t\t\t\t<td class='chan'>\n";

disp_chan($id,$from_date,$from_time,$to_date,$to_time,$title); echo "\t\t\t\t\t</td>\n";

} el se{

}

echo "\t\t\t\t</tr>\n"; echo "\t\t\t</table>\n";

?>

} }

main.php

P2P PVR Applications 81/11 o

disp_chan($chan,$from_date,$from_time,$to_date,$to_time,$title);

This file will render the complete main view of the website. lt processes the information of the search and produces the information the user requested .

<?php require_once(' . ./db/connect.php');

$query _stríng=$ _ SERVER['QU ERY _ STRING'];

$uri=$_S~RVER['PHP _SELF']."?".$query_string;

$today=date('Ymd'); $tomorrow=date('Ymd', time()+ 24 *3600); $now=date('His');

$chan=(isset($_GET['chan'])? $_GET['chan']:'all'); $from_date=(isset($_GET['from_date'])? $_GET['from_date']:$today); $from _ time=(isset($ _ G ET['from __ time']) ? $ _ GET['from _time'}: '000000'); $to _date=( isset($ _ GET['to _date']) ? $ _ GET['to _date']: $tomorrow); Sto_ time=(isset($ _ GET['to _time']) ? $ _ GET['to _time']: '000000'); $title=(isset($_ GET['title'])? $_ GET['title']:"); $epísode=(ísset($ _ GET['epísode']) ? $ _ GET['episode']:");

echo "\t\t<div class='form'>\n";

1/Form: channels

echo "\t\t\t<form action='$url' method='get'>\n"; echo "\t\t\t\t<p>";

echo "Channel: \n"; echo "\t\t\t\t\t<select name='chan'>\n";

$query="SELECT 'chanld' ,'chanName' FROM channels"; $result=mysql_query($query) or die("lnvalid query".mysql_error());

while($row=mysql_fetch_array($result)){

$chanld=$row[O); $chanName=$row[ 1]; $selected=(($chanName==$chan)? 'selected':");

echo ''\t\t\t\t\t\t<option value='$chanld'

P2P PVR Applications 82/ 11 o

$selected>$chanName</option>\n": }

$selected=(($chan=='all') ? 'selected':"); echo "\t\t\t\t\t\t<option value='all' $selected>AII</option>\n";

echo "\t\t\t\t\t</select> \n\t\t\t\t\tll ";

//Available scope

$query="SELECT 'start' FROM programs ORDER BY 'starf ASC LIMIT 0,1"; $result=mysql_query($query); $row=mysql_fetch_array($result); $from=substr($row[O], O ,8);

$query="SELECT 'start' FROM programs ORDER BY 'starf DESC LIMIT 0,1" ; $result=mysql_query($query); $row=mysql_fetch_array($result); $to=substr($row[0],0,8);

//Form: date and time of beginning of the scope

echo "From: \n";

echo "\t\t\t\t\t<select name='from date'>\n"· - 1

$date=$from; while($date<=Sto ){

sscanf($date, "%4s%2s%2s" ,$date _year,$date _month, $date_ da y);

$selected=(($date==$from_date) ? 'selected':");

echo "\t\t\t\t\t\t<option value='$date' $selected>$date _ day­$date_month-$date_year</option>\n";

$date=date('Ymd',mktime(O,O,O,$date_month,$date_day,$date_year)+24*3600); }

h</option>\n";

echo "\t\t\t\t\t</select> \n"; echo "\t\t\t\t\t<select name='from_time'>\n";

for($i=O;$i<=23;$i++ ){

$j=sprintf("%02d",$i); $val=$j . "0000";

$selected=(($val==$from_time) ? 'selected':");

echo ''\t\t\t\t\t\t<option value='$val' $selected>$j

P2P PVR Applications

}

echo "\t\t\t\t\t</select> \n";

echo "\t\t\t\t\tto: \n"; echo "\t\t\t\t\t<select name='to date'>\n"· - '

$date=$from; while($date<=$to ){

sscanf($date."%4s%2s%2s",$date_year,$date_month,$date_day);

$selected=(($date==$to_date) ? 'selected':");

83/11 o

echo "\t\t\t\t\t\t<option value='$date' $selected>$date_day­$date_month-$date_year</option>\n";

$date=date('Ymd',mktime(O.O,O,$date_month,$date_day,$date_year)+24*3600); }

echo "\t\t\t\t\t</select> \n"; echo "\t\t\t\t\t<select name='to time'>\n"·

- o

for($i=O;$i<=23;$i++ ){

$j=sprintf("%02d",$í); $val=$j."OOOO";

$selected=(($val==$to_time) ? 'selected':");

echo ''\t\t\t\t\t\t<option value='Sval' h</option>\n";

echo "\t\t\t\t\t</select> \n\t\t\t\t\tll ";

//Form: title

echo "Title: \n";

$selected>$j

echo "\t\t\t\t\t<input type='text' size='25' maxlength='64' name='title' value='$title' />\n";

echo "\t\t\t\t\t<input type='submit' value='OK' />\n"; echo "\t\t\t\t</p>\n";

echo "\t\t\l</form>\n";

//Confirm recording

echo href=' . ./process/confirm_records.php?$query_string'><strong>Confirm recording</strong></a> ";

echo "11";

"\t\t\t<a

?>

P2P PYR Applications

//Logout

echo "<a href=' . ./access/logout.php'>Logout</a>\n"; echo "\t\t.f./div>\n"; echo "\t\t<div id='display'>\n";

//Display information required

include(' . ./display/disp.php');

disp($chan,$from_date,$from_time.$to_date,$to_time,$title);

echo "\t\t</div>\n"; mysql_ clase();

index.php

84/ 1 10

This file pr~sents the main login window form and glues in together the view and the models to start browsing the webpage.

<?php session_start();

?>

if(! isset($ _ SESS ION['Iog in'])){ $page = 'auth';

} else {

$page = (isset($_GET['pg']))? $_GET['pg']: 'main'; }

if (isset($_GET['pg'])) { if ($_GET['pg') == 'verif) { require(' . ./access/verif. php'); } }

<!DOCTYPE html PUBLIC "-/I\/\/3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtmi11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >

<head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1 ">

<link rel="stylesheet" media="screen" type="text/css" title="style" href=" . ./style/style.css" />

<title>Project Springfield -- Electronic Program Guide</title> <script type="text/javascript" src=" . ./script/script_ajax.js"></script> <script type="text/javascript" src=" . ./script/display _dese. js"></script> <script type="text/javascript" src=" . ./script/display _torren t. js"></script>

</head>

<body> <div id='header'>

P2P PVR Applicat ions 85/110

<img src=' . ./images/logo.png' alt='Project Springfield -- The EPG' /> </div>

<?php

$u ser _log=$ _ SESSION['Iogín'];

switch($page){

}

?>

case 'auth': include(' . ./access/auth. php') ; break;

case 'auth_fail': echo "<div class='error'>Authentication failed . Try again. </div>"; include(' . ./access/auth.php'); break;

case 'main': includ~(' . .ldisplay/main.php'); break;

default: echo 'Switching page error'; break;

</body> </html>

Process

add _record. ph p

This file inserts into the database the record information, for example if the user jgarduno wants to record the program with id 30, a record in the table records will'be created setting the login to jgarduno and the prog_id 30.

<?php

session _ start(); require_once(' . ./db/connect.php') ;

$login=$_ S ESSION['Iogin']; if(isset($ _POST['prog_id']) ){

$prog_id=$_POST['prog_id']; $query="INSERT INTO records SET 'login'='$1ogin','progld'='$prog_id"'; $result=mysql_query($query) or die("lnvalid query ".mysql_error());

echo "Program selected : <img src=' . ./ímages/yellow-button.gif' alt='Program selected' /><br />" .

"Delete from selection: <input type='image' src=' . ./images/delete-button.gíf' alt='Delete program from selection' onCiick=\"loadFragmentl ntoEiement(' . ./process/delete _record. php', 'prog$prog_id'); \"!> ";

P2P PVR Applications 86/11 o

} el se{

echo "Error: no specified program Id."; }

mysql_close(); ?>

confirm_records.php

This will update a field in the record status which will tell the application that it should be recorded.

<?php session_ start(); if(! isset($ _ SESSION['Iogin'])){

$page = 'auth'; } else {

$page = (isset($_GET['pg']))? $_GET['pg']: 'main'; }

if (isset($_GET['pg'])) { if ($ _ GEr['pg'] == 'verif) { require(' .. /access/verif. php'); } }

$query_string=$_SERVER['QUERY _STRING'];

$user _log=$_SESSION['Iogin'];

//Processing confirmation require_once(' . ./db/connect.php');

$query="UPDATE records SET 'recordStatus' = '1' WHERE 'login' = '$user_log' ANO 'recordStatus' ='O"';

$result=mysql_query($query) or die("lnvalid query ".mysql_error());

mysql_ close();

?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtmi11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >

<head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1 ">

<link rel="stylesheet" media="screen" type="text/css" title="style" href=" . ./style/style.css" />

P2P PVR Applications

<title>Project Springfield -- Electronic Program Guide</title> <script type="textljavascript" src=" . ./scriptlscript_ ajax .js"></script> <script fype="text/javascript" src=" . ./scriptld isplay _ desc.js"></script> <script type="textljavascript" src=" . ./scriptldisplay_torrent.js"></script>

</head>

<body> <div id='header'>

<img src=' . ./images/logo.png' alt='Project Springfield -- The EPG' /> </div> <div id='display'>

87/ 110

<div class='center'>Recording scheduled! <a href='<?php echo " . ./index/index.php?".$query_string; ?>' alt='back to index'>Back to main menu</a></div>

</div> </body>

</html>

P2P PVR Applications 88/1 1 o

delete_record.php

This file is used when deleting a record ; this could be used for purging the data base , or for the use of the administrator.

<?php sessíon _ start(): require _once(' . ./db/connect. php');

$login=$_ SESSION['Iogin']; if( isset($ _POST[' prog_id ']) ){

$prog_id=$ _ POST['prog_íd']; ~query="DELETE FROM ' records' WHERE ' login '='$1ogín' AND

· progld " ='$prog_id"';

?>

$result=mysql_query($query) or díe("lnvalid query ".mysql_error()) ;

echo "Program deselected.";

} el se{

echo "Error: no specifíed program Id."; }

mysql_close();

enable_torrent.php

This file upc!lates the status of a program in case a torrent for this program is created . This file is accessed directly by the Scheduler program or the GUI.

<?php $login=( isset($_POST['Iogin']) ? $_POST['Iogin'):'fail'); $pass=( isset($_POST['password'])? $_POST¡'password']:'fail'); $progld=( isset($_POST['progld']) ? $_POST['progld']:O) ;

require_once(' . ./access/verification.php');

if(verification($1ogin.$pass)){

} el se{

} ?>

require _once(' . ./db/connect. php') ; $query="UPDATE programs SET ' status· = '1' WHERE 'progld' = '$progld"'; $result=mysql_query($query) or die("lnvalid query: ".mysql_error()); mysql_close();

echo "lnvalid login or password.";

P2P PVR Applications 89/ 110

fetch_programs.php

The fetch_programs.php file will extract all of the channels we select to populate the database daily, this will be done after getting the XML file with the XML TV program.

<?php

require _ once('/var/www/springfield/epg/db/connect. ph p') ;

$tvprog=new DomDocument(); $tvprog->load('/var/www/springfield/epg/xml/tvprog.xml'); $tv=$tvprog->documentEiement;

$chanWebs=array('nrk 1. nrk. no'=>1, 'nrk2. nrk. no'=>2, 'tv2. no'=> 3, 'world . bbc.co. u k'=> 4,'canalplus.canalplus. no'=>5, 'tv norge. no'=>6, 'sport. canalplus. no'=> 7);

//We check the last show entered in the database for each channels

$chanlast=array();

for($i=1 ;$i<=7;$i++){

$query_last="SELECT 'chanld' ,' start' FROM programs WHERE ' chanld'='$i ' ORDER BY 'start' DESC LIMIT 1";

$result_llast=mysql_query($query_last) or die("lnvalid query: ".mysql_error()) ; if($row _last=mysql_fetch_ array($result_last) ){

} }

$1ast=$row _last['start']; $chanlast[$i]=$1ast;

$programs=$tv->getEiementsByTagName('programme'); foreach($programs as $program){

$start=substr($program->getAttribute('start'),O, 14); //substr used here to get the type yyyymmddhhmmss

$chanWeb=addslashes($program->getAttribute('channel')); $chanld=$chanWebs[$chanWeb];

if($chanlast[$chanld] < $start){

$end=substr($program->getAttribute('stop') , O, 14);

$titles=$program->getEiementsByTagName('title') ; //the first title gets the attribute lang='no' and the second one, if any, has the attribute lang='en'

$title_no=addslashes($titles->item(O)->firstChild->nodeValue);

if($titles->length >1 ){

} else{

}

$title _ en=addslashes($titles-> item( 1 )->firstC hild->nodeValue);

$title en='NULL" - 1

>item(O)){

}

PLP PV K Appllcations 90/ 110

Íf($description=$program->getEiementsByTagName('desc')->item(O)){ $desc=addslashes($description->firstCh ild->nodeValue);

} el se{

$desc='NULL'; }

if($episodenum=$program->getEiementsByT ag Name('episode-num')­

$episode=addslashes($episodenum->firstCh ild->nodeValue); } else{

} $episode='NULL';

$query="INSERT INTO programs SET" . "'progld'='NULL',". "'chanld'='$chanld'," . "' starr ='$start' ," . "'end'='$end',". "'titleNo'='$title_no',". "'titleEn'='$title_en',". "'desc·='$desc'," . "' episode '='$episode' ," . "'status· ='O'";

$result=mysql_query($query) or die("lnvalid query ".mysql_error());

} mysql_close();

?>

8.4. Current issues and future improvements

As it is now, our solution fulfils its role as an EPG but it relies for an important part on the Norwegian grabber of XML TV. lf this one ca me to be modified in its way of storing the data, then some functions as fetch_programs.php would have to be modified as well.

Another small issue with the current solution is that two records can be scheduled at the same time. Theoretically, it is nota problem , but in reality, transcoding and recording two streams at the same time requires far too much bandwidth and processing power.

Also, work can still be done to improve the global functioning. lf the information given by the Norwegian grabber of XML TV becomes more complete , it might be a good idea to display them on the EPG. Extra data about the torrent files can also be made accessible.

P2P PVR Applications 91 / 110

The management of the users is currently very simple. The only information about a user is its login. lf we think about further applications of this system, in particular public use, it might be better to add extra fields such as name, first name ...

P2P PVR Applications 92/ 11 0

9. lntegration

9.1. lntroduction

As described before, the system we developed consisted of several parts . In this particular section we will describe the process we followed in arder to join all of the parts into the unified system.

P2P PVR Applications

9.2. ' Final functional model

1 XMLTV

is stored in

Tracker

"' "' "' "' "' "' Indicates the "'"' "' recording to do."' ... --1 .-------------,

Python Scheduler

"' "'

93/1 10

Stream channels

launche the torre Video file ets info and

updates

Web server (EPG)

se lects shows '

' ' ' '

creation

', adds torrent 1

' ' ' ' ' ' ' ' ' ' ' ' \ \

\ \

Server side ,

Figure 17 -- Final functional model

\ \ \

itTorrent

.torrent file

Client side

Two zones appear in our system: the server and the client side. lt means that the users will have to install the application containing the scheduler, VLC Media Player and the modified BitTorrent client on their own computer. The servers will host the database and the Electronic Program Guide.

The actions indicated in red are the interactions between different modules. They will be detailed in the next sections.

9.3. lndicating to the client application what programs to record

Once the scheduler is launched, it regularly executes the function records_info.php on the web server, in the folder xml. This function needs the login the user login as an argument passed in the url. For example, the scheduler of the user 'eps' will call :

http://server_adress/springfield/xml/records_info.php?login=eps

This functi<Dn actually generates xml content that will be parsed by the scheduler. The function looks into the table 'records' to check the user's

P2P PVR Applications 94/ 1 10

associated records. The record status must be set to 1 (recording confirmed , waiting to be treated) to be taken into account. Then a query is launched into the 'programs' table to get the useful information. Here is an example of xml content generated :

<progs> <prog>

<chanurl>239.192.1 00.50:8208</chanurl> <progid>234</progid> <title> U r0 rt </title> <start>1148558700</start> <end>1148563200</end>

</prog> <prog>

<chanurl>239.192.1 00.50:8208</chanurl> <progid>235</progid> <title>Redaksjon EN</title> <start> 1148563200</start> <end>1148565000</end>

</prog> </progs>

Example of the XML output of records_info.php

9.4. Launching and stopping a recording

Once the scheduler gets the xml output, it parses it and extracts the information .jt needs. In particular, it gets the URL of the stream channel , the start and the end of the show. The indicated times are in the UNIX timestamp format, so it can directly schedule tasks by calling the class recorder.py and its functions start() and kili().

9.5. Creating a .torrent file

After the video file is saved on the client computer, the scheduler calls the function createTorrent.py from the class recorder.py. This function takes as an argument the URL of the tracker (in our case, http://server_adress/springfield/tracker/tracker.php) and uses the information provided by the XML output. Then , the principie is simple: createTorrent.py just calls the BitTorrent function make_meta_files used to create the torrent files , passing it the required arguments.

9.6. · Registering a new .torrent file

Just after the .torrent metafile is created , an instance of the UploadFormSubmitter class is created . At this moment the .torrent metafile will be uploaded to the server using an HTTP POST request to the newtorrents.php file .

P2P PVR Applications 95/ 110

On the server side, the newtorrents.php file , which is part of PHPBTTracker, receives the .torrent file together with the program id and the authentication information. lt is currently stored as plain text. lf the implementation of this system would be deployed in an open network, this should be changed for something more secure. Nevertheless, the changes to make the upload of the .torrent file through a secure https connection are minimal.

When the uploading of the .torrent file metafile is completed , the enable_torrent.php script set the status of the program to 1 (a torrent file is available).

P2P PVR Applications 96/ 11 o

10. Conclusions

We explored the use of BitTorrent technology to broadcast content, with positive results . In our experiments we successfully distributed the load a server usually takes to severa! clients. We were also able to use the storage capacity of the peers in creating a repository of broadcast content. We also discovered that open source software is good enough for solving this kind of problems.

Even though making a solution that works on both platforms (Linux!Windows) posed sorne problems, they are not unsolvable and we managed to make it work.

The use of open standards makes things easier as you don't have to salve problems already addressed by others . lt also makes the applications more future proof when it comes to expandability.

P2P PVR Applications 97/ 11 0

References

[Cohen, 03] B. Cohen. Incentives build robustness in BitTorrent. In Workshop on Economics of Peer-to-Peer Systems, Berkeley, USA, May 2003. http://bittorrent.com/.

[Chromatic, 03] Chromatic. Extreme Programming Pocket Guide (2003) ; Sebastopol , California, USA; O'REILLY Media, lnc.

[Wally, 04] Wang, Wally. (2004). Steal This File Sharing Book : What They Won't Tell You about File Sharing . San Francisco, CA, USA: No Starch Press, lncorporated .

[Wells, 06] Wells, Don. (2006). Extreme Programming: A gentle introduction. http://www.extremeprogramming .org/when.html

Internet Resources . [BitTorrent, 06] "Protocol Specification" Retrieved 30 May 2006 from http://www. bittorrent. org/protocol. html

[BitTorrent, 06] "FAQ" Retrieved 30 May 2006 from http://www.bittorent.com/faq .myt

P2P PVR Applícations 98/11 o

[Python , 06] "Begginers Guide Overview" Retrieved 03 June 2006 from http://wiki .python.org/moin/BeginnersGuide/Overview

[Theory.org , 06] "Bittorrent specification" Retrieved 30 May 2006 from http://wi ki . theory. org/BitT orrentSpecification

[Videolan , 06] "Advanced streaming using the command line" Retrieved 29 May 2006 from http://www.videolan .org/doc/streaming-howto/en/ch03.html

[Wikipedia , 06] "Eiectronic Program Guide" Retrieved 30 May 2006 from http://en.wikipedia.org/wiki/EPG

[Wikipedia , 06] "Database Management System" Retrieved 30 May 2006 from http://en. wikipedia . org/wiki/Database _ management_ system

[Wikipedia, 06] "Subversion" Retrieved 30 May 2006 from http://en .wikipedia.org/wiki/Svn

[Wikipedia , 06] "Bittorrent Tracker" Retrieved 28 May 2006 from http:/ /en . wikipedia. org/wiki/BitT orrent_ tracker

[Wikipedia , 06] "Python" Retrieved 29 May 2006 from http://en.wikipedia.org/wiki/Python_programming_language

[WXWindows, 06] "WxWidgets Homepage" Retrieved 30 May 2006 from http://www.wxwindows.org/

P2P PVR Applications 99/ 110

Appendix A...:. Extreme Programming use stories

Viewing

1 want to see which shows are going to be shown today. 1 log in to the webpage and select the day and channels i want to see. 1 want to see a webpage displaying all of my selection criteria .

Recording

1 want to record a show. 1 log in to the website, see the shows that are not aired yet. Select one or more i would like to record. Confirm my arder. The recording should start automatically.

Downloading and watching already aired and recorded shows

1 log in to the webpage, and while i see the EPG i see that a show already aired is being shared by somebody. 1 click on the download button and start watching.

Searching

1 log in to the webpage and fill a form with my search criteria. 1 will then get the results the same way as they are presented in the normal view, to be consistent with the results . 1 can then decide wether to select a show to record or to play from the torrent deployment.

Accessing'the recorded shows

1 open a program on my computer; i log in in arder to see my content. There is a section where i should see everything i have recorded and be able to launch the video pi ayer from that same place.

P2P PVR Applications

Appendix 8- Modified BitTorrent client

piecepicker.py(modified, original/y written by Bram Cohen)

from random import randrange, shuffle, choice

class PiecePicker(object): '""'Ciass that picks the pieces to download"""

def _init_(self, numpieces, config): "'"'just initi~lizing the variables'""' self.config = config self.numpieces = numpieces self.interests = [range(numpieces)] self.pos_in_interests = range(numpieces) self.numinterests =[O]* numpieces self.have = [False] * numpieces self.crosscount = [numpieces] self.started = [] self.seedstarted = [] self.numgot =O self.scrambled = range(numpíeces) self.notscrambled = range(numpieces) shuffle(self.scrambled)

def príntvars(self) : for x in self._dict_:

prínt repr(x), self._díct_[x]

def got_have(self, píece): "to state that a clíent has that píece" numínt = self.numinterests[piece] self.crosscount[numint + self.have[piece]]-= 1 self.numinterests[piece] += 1 try:

self.crosscount[numínt + 1 + self.have[piece]] += 1 except lndexError:

setf.crosscount.append(1) if self.have[piece]:

#print "self.have is true" #print ''under got_have i self.have this piece ", piece return

íf numínt == len(self.interests)- 1: self. interests.append([])

self._shíft_over(piece, self.interests[numint], self. interests[numínt + 1])

def lost_have(self, piece): "tells which pieces we lost" #print "called lost have with piece number" , piece numint = s,elf.numinterests[piece] self.crosscount[numint + self.have[piece]] -= 1 self.numinterests[piece] -= 1 self.crosscount[numint - 1 + self.have[piece]] += 1 if self.have[piece]:

return self._shift_over(piece, self.interests[numint], self.interests[numint- 1])

def _shift_over(self, piece, 11, 12):

100/ 110

p = self.pos_in_interests[piece] 11[p] = 11[-1] self.pos_in_interests[l1[-1]] = p del11[-1] newp = rar;¡drange(len(l2) + 1) if newp == len(l2) :

P2P PVR Applications

self.pos_ín_interests[piece] = len(l2) 12.append(piece)

el se: old = 12[newp] self.pos_in_interests[old) = len(l2) 12.append(old) 12[newp] = piece self.pos_in_interests[piece] = newp

def requested(self, píece, seed = False) : #print "requested" , piece if piece not in self.started:

self. started. append(piece) if seed and piece not in self.seedstarted:

self. seedstarted. append( piece)

def complete(self, piece): #print "complete", piece assert not self.have[piece] self.have[piece] = True self.crosscount[self.numinterests[piece]] -= 1 try:

self.crosscount[self.numinterests[piece] + 1] += 1 except lndexError:

self.crosscount.append( 1) self.numgot += 1 1 = self.interests[self.numinterests[piece]] p = self.pos_in_interests[piece] l[p] = 1[-1) self.pos_in_interests[l[-1]) = p dell[-1] try:

self.started .remove(piece) self.seedstarted. remove( piece)

except ValueError: pass

' def next(self, havefunc, seed = False):

#self. printvars() #print "next called with havefunc ", repr(havefunc) bests = None bestnum = 2 ** 30 if seed:

s = self.seedstarted el se:

s = self.started # for í ín s: # if havefunc(i): # if self.numinterests[i] < bestnum: # bests = [i) # bestnum = self.numinterests[í)

101/110

P2P PVR Applications

# elif self.numinterests[i] == bestnum: # bests.append(i) # if bests: # return choice(bests)

#choose random pieces until pieces got is greater than 4 #if self.numgot < self.config['rarest_first_cutoff]: if self.numgot < 100000:

for i in self.notscrambled: if havefunc(i) :

return i return None

#choose for i in xrange(1, min(bestnum, len(self.interests))):

for j in self.interests[i]: if havefunc(j):

return j return Nene

' def am_l_complete(self):

return self.numgot == self.numpieces

def bump(self, piece) : 1 = self.interests[self.numinterests[piece]] pos= self.pos_in_interests[piece] dell[pos) l.append(piece) for i in range(pos,len(l)) :

self.pos_in_interests[l[i]] = i try:

self. started.remove(piece) self.seedstarted.remove(piece)

except ValueError: pass

102/ 1 10

P2P PVR A pplicat ions

APPENDIX C- Supporting code for the webpage

a) Javascripts display_ desc.js

function display_desc(prog_id){ var spanld="desc"+prog_id; var buttonld="disp"+prog_id;

}

var span=document. getEiementByld( spanld) : var state:;span .style.display; var button=document.getEiementByld(buttonld) ; if( state=='none'){

}

button.setAttribute('src',' . ./images/close.gif') ; button .setAttribute('a!t', 'Glose description'); span.style.display='block' ;

el se{

}

button .setAttribute('src' , ' . ./images/open.gif'); button .setAttribute('alt' ,'Show description'); span .style.display='none';

display_ torrent.js

function display_torrent(prog_id){ var spanld="torrent"+prog_id; var titleld="disptorrent"+prog_id; var span=document.getEiementByld(spanld); var state=span.style.display; var title=document.getEiementByld(titleld) ; if( state=='none'){

103/1 1 o

title.innerHTML="<img src=' . ./images/torrent.gif alt='Hide torrents' /> Hide torrents<br /><br />";

span.style.display='block'; } el se{

title.innerHTML="<img src=' . ./images/torrent.gif alt='Show torrents' /> Show available torrents";

span.style.display='none' ; }

}

P2P PVR Applications

script_ ajax.js

var xhr_object=false; /*@cc_on @*/ /*@if ( @jscript_ version >= 5) 11 JScript gives us Conditional compilation, we can cope with old lE versions . 1/ and security blocked creation of the objects.

try { xhr_object = new ActiveXObject("Msxmi2.XMLHTTP"); } catch (e) { try { xhr_object = new ActiveXObject("Microsoft.XMLHTTP") ;

} catch (E) {

} }

xhr_object = false;

@end @*/ if (lxhr_object && typeof XMLHttpRequest!='undefined') {

xhr_object = new XMLHttpRequest() ; }

/* Load fragment into element */

function loadFragmentlntoEiement(fragment_url , element_id) { var element = document.getEiementByld(element_id); var data= null; element.innerHTML = 'Loading .. .'; xhr _object.open("POST", fragment_url) ; xhr _ object.onreadystatechange = function() {

if (xhr_object.readyState == 4 && xhr_object.status == 200) { element.innerHTML = xhr_object.responseText; }

}

data="prog_id="+element_id. substring( 4);

104/11 o

x h r _ object.setRequestHeader("Content -type!O, "application/x-www-form-urlencoded 10) ;

xhr_object.send(data); }

b) Cascading Style Sheets

html,body{ margin: Opx; font-size: 1 Opt; text-align:left;

style.css

font-family: Optima, "Trebuchet MS", Lucida, Aria! , Geneva, Verdana, IOLucida Grande10,

Tahoma, Helvetica, sans-serif; height 1 00%; background-color: #EEEEFF; }

a{ text-decoration: none; }

a:visited{ color:blue; }

a img{ border:none; text-decoration: none; }

h1{ font-size: 16pt; }

.center{ text-align:center; }

#header{ text-align:center; border: none;

P2P PVR Applications

background-image: url( . ./images/back. png); background-repeat: repeat-x; height: 160px; }

#header img{ margin-top:25px; }

.form{ margin :8px; padding:8px; border: dotted black 1 px; text-align: center; backg round-color:wh ite; } .

. error{ margin:8px; padding :8px; color: red ; font-weight: bold ; text-align: center; }

#display{ margin:8px; padding: 8px; border: dotted black 1 px; backg round-color:wh ite; }

105/ 110

table tr td{ border: dashed black 1 px; vertical-align : top; }

td .chan{ width: 12%; padding: 3px; }

e) xml

<?php header("Content-type: textlxml") ; ?> <?php

P2P PVR Applications

records _info.php

$1ogin=(isset($_GET['Iogin'])? $_GET['Iogin'] :") ;

require _once( ' . .fdb/connect. php');

106/ 110

$query="SELECT 'progld' FROM records WHERE ' login'='$1ogin' ANO recordStatus='1"'; $result=mysql_query($query) or die(" lnvalid query ".mysql_error());

echo "<progs>\n";

while($row=mysql_fetch _ array($result) ){

$progld=$row['progld'];

$query2="SELECT C.chanUrl, C.chanld, P.progld, P.chanld, P.titleNo, P.start, P.end".

"FROM channels C, programs P" . "WHERE P.progld = '$progld'" . "ANO C.chanld = P.chanld";

$result2=mysql_query($query2) or die("lnvalid query ".mysql_error());

$row2=mysql_fetch_array($result2) ;

$e han U rl=$row2['chan U rl']; $title=$row2['titleNo'];

$start=$row2['start']; sscanf($start,"%4s%2s%2s%2s%2s%2s",$year,$month,$day,$hour,$min,$sec); $start=mktime($hour,$mín,$sec,$month,$day,$year);

$end=$row2['end'];

P2P PVR Applications 107/ 110

sscanf($end,"%4s%2s%2s%2s%2s%2s",$year,$month,$day,$hour,$min,$sec); $end=mktime($hour,$min,$sec,$month,$day,$year);

}

echo "\t<prog>\n"; echo "\t\t<chanurl>$chanUrl</chanurl>\n"; echo "\t\t<progid>Sprogld</progíd>\n"; echo "\t\t<títle>$títle</title>\n"; echo "\t\t<start>$start</start>\n"; echo "\t\t<end>$end</end>\n";

echo "\t</prog>\n";

echo "</progs>";

$query3="UPDATE records SET 'recordStatus'= '2' WHERE 'login'='$1ogin' ANO recordStatus='1 "' ; $result3=mysql_query($query3) or die("lnvalid query ".mysql_error());

mysql_close(); ?>

xmltv.dtd

<!ELEMENT tv (channel*. programme*)> <!ATTLIST tv date CDATA #IMPLIED

source-info-url CDATA #IMPLIED source-info-name CDATA #IMPLIED source-data-url CDATA #IMPLIED generator-info-name CDATA #IMPLIED generator-info-url CDATA #IMPLIED >

<!ELEMENT channel (display-name+, icen*, url*) > <!ATTLIST channel id CDATA #REQUIRED >

<!ELEMENT display-name (#PCDATA)> <!ATTLIST display-name lang CDATA #IMPLIED>

<!ELEMENT url (#PCDATA)>

<IELEMENT programme ( title+ , sub-title*, dese*, credits?, date?, category*, language?, oríg-language?, length?, icen*, url*, country*, episode-num*, video?,

audio?, prevíously-shown?, premiere?, last-chance?, new?, subtitles*, rating*, star-ratíng? )>

<!ATTLIST programme start CDATA #REQUIRED stop CDATA #IMPLIED pdc-start CDATA #IMPLIED

P2P PVR Applications

vps-start CDATA #IMPLIED showview CDATA #IMPLIED videoplus CDATA #IMPLIED channel CDATA#REQUIRED clumpidx CDATA "0/1 " >

<!ELEMENT title (#PCDATA)> <!A TTLIST title lang CDATA #IMPLIED>

<IELEMENT sub-title (#PCDATA)> <IATTLIST sub-title lang CDATA #IMPLIED>

<!ELEMENT dese (#PCDATA)> <!ATTLIST dese lang CDATA #IMPLIED>

<IELEMENT cr~dits (director*, actor*, writer*, adapter*, producer*, presenter*, commentator*, guest* )>

<!ELEMENT director (#PCDATA)> <!ELEMENT actor (#PCDATA)> <!ELEMENT writer (#PCDATA)> <IELEMENT adapter (#PCDATA)> <IELEMENT producer (#PCDATA)> <!ELEMENT presenter (#PCDATA)> <!ELEMENT commentator (#PCDATA)> <!ELEMENT guest (#PCDATA)>

<IELEMENT date (#PCDATA)>

<!ELEMENT category (#PCDATA)> <!ATTLIST category lang CDATA #IMPLIED> <!ELEMENT language (#PCDATA)> <!ATTLIST language lang CDATA #IMPLIED>

<!ELEMENT orig-language (#PCDATA)> <!ATTLIST orig;-language lang CDATA #IMPLIED>

<!ELEMENT length (#PCDATA)> <IATTLIST length units (seconds 1 minutes 1 hours) #REQUIRED>

<!ELEMENT icon EMPTY> <!ATTLIST icon src CDATA #REQUIRED

width CDATA #IMPLIED height CDATA #IMPLIED>

<IELEMENT value (#PCDAT A)>

<!ELEMENT country (#PCDAT A)> <!ATTLIST country lang CDATA #IMPLIED>

<!ELEMENT episode-num (#PCDATA)> <!ATTLIST episode-num system CDATA "onscreen">

<!ELEMENT video (present? , colour?. aspect?, quality?)> <!ELEMENT pr~sent (#PCDATA)> <IELEMENT colour (#PCDATA)> <!ELEMENT aspect (#PCDATA)> <!ELEMENT quality (#PCDATA)>

108/ 110

P2P PVR Applications

<!ELEMENT audio (present?. stereo?)> <!ELEMENT stereo (#PCDATA)>

<!ELEMENT previously-shown EMPTY> <!ATTLIST previously-shown start CDATA #IMPLIED

channel CDATA #IMPLIED >

<' ELEMENT .premiere (#PCDA TA)> <!A TILIST premiere lang CDAT A #IMPLIED>

<!ELEMENT last-chance (#PCDATA)> <!ATTLIST last-chance lang CDATA #IMPLIED>

<IELEMENT new EMPTY>

<!ELEMENT subtitles (language?)> <!ATTLIST subtitles type (teletext 1 onscreen) #IMPLIED>

<!ELEMENT rating (value, icon*)> <'ATTLIST rating system CDATA#IMPLIED>

<!ELEMENT star-rating (value, icon*)>

109/ 110

P2P PVR Applications 110/110

Appendix D- Team members' short description

Maitham AI-Essawi - Norway & lraq.

Maitham is 36 years old and is studying computer science at Oslo University College. He already has a Bachelor of Electric Engineering and he owns a hair dresser's salan in Oslo.

José Garduño- Mexico.

He is 23 years old and he is finishing his bachelor of lnformation Technology at the University of Monterrey. He likes computer security, and in particular computer forensics. He also enjoys studying, travelling and working abroad.

Matthieu Godéré- France.

He is 20 years old and is studying telecommunications engineering at the Telecommynication Engineering College of Brittany. He studies various fields such as signa! processing, mobile and fixed networks, electronics, optics, computers and management techniques.

Marcin Kot- Norway & Poland.

He studies computer science at Oslo University College. He is familiar with different operating systems (especially those of UNIX heritage) and also does some system and network administration for a small company. Programming is not his strong field , but he is very much into perl/sh scripting .