From d1ae5960a68c21b01b298a1658505a3824f2735c Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 19 Mar 2020 14:04:33 +0100 Subject: [PATCH 01/13] Update protocol for #16 --- doc/protocol.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/doc/protocol.md b/doc/protocol.md index b21a615..a2cf4d5 100644 --- a/doc/protocol.md +++ b/doc/protocol.md @@ -17,17 +17,22 @@ x bytes: [(bytes 8-?): PAYLOAD] - `LIST` (0x00) - `LOAD` (0x01) - `HASH` (0x02) + - `DISCOVER` (0x03) + - `REGISTER` (0x04) + - `UNREGISTER` (0x05) - RESPONSES (msb is 1): - `LIST` (0x80) - `LOAD` (0x81) - `HASH` (0x82) + - `DISCOVER` (0x83) - `VERSION ERROR` (0xC0) - `PROTOCOL ERROR` (0xC1) - `INTERNAL ERROR` (0xC2) - `EMPTY DIRECTORY` (0xC3) - `NOT FOUND` (0xC4) - `EMPTY FILE` (0xC5) + - `NOT A TRACKER` (0xC6) ### List Payload size for list request is always zero. @@ -97,6 +102,47 @@ A algo hash bloc contains: ``` +### Tracker specific messages +#### Register +Used by a server to register itself on a tracker. +Payload contains `0x01` if working on udp, `0x02` if working on tcp, `0x03` if working on both. +Server may want to do a free `DISCOVER` to check if they have been registered. + +#### Unregister +Used by a server to unregister itself from a tracker. +Payload contains `0x01` if unregister from udp, `0x02` if unregister from tcp, `0x03` if unregister on both. +No error is raised if the server was not registered. +Server may want to do a free `DISCOVER` to check if they have been unregistered. + +#### Discover request +If payload size is null, lists all servers registered. +If payload contains a filename, list all servers having this file in their list. + +``` +? bytes: [] + +``` + +#### Discover response +Contains: +``` +4 bytes: [(bytes 8-11): FILENAME SIZE] +y bytes: [] +? bytes [multiple server blocks] +``` + +Server block is composed with: + +``` +2 bytes: [port] +1 byte: [protocols (udp: 0x01, tcp: 0x02, tcp+udp: 0x03)] +? bytes: hostname +\n +``` + +#### Not a Tracker +This error is raised when receiving a DISCOVER, a REGISTER, or an UNREGISTER request, +but this application is not a tracker. ### Other response code (errors) #### Version error -- 2.30.2 From f0988e3af3d65d8b5ad25122ba680f209fd77f32 Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 19 Mar 2020 14:42:34 +0100 Subject: [PATCH 02/13] Add sequence diagrams --- doc/tracker_sequence_diagram.drawio | 1 + doc/tracker_sequence_diagram.svg | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 doc/tracker_sequence_diagram.drawio create mode 100644 doc/tracker_sequence_diagram.svg diff --git a/doc/tracker_sequence_diagram.drawio b/doc/tracker_sequence_diagram.drawio new file mode 100644 index 0000000..baa61f9 --- /dev/null +++ b/doc/tracker_sequence_diagram.drawio @@ -0,0 +1 @@ +7Ztfc+I2EMA/DTO5h2RsyzbwmBCS3vR6lwvptdM3YQtQIyxqRP7003eFZYMlbDjHEJOSh4y8lteS9qfVrmRaqDd9uY3xbPIbDwlrOVb40kLXLcfp+B34LwWvicDtdhPBOKZhIrJXggH9lyihpaQLGpJ5rqLgnAk6ywsDHkUkEDkZjmP+nK824iz/1hkeE0MwCDAzpX/QUEyU1Las1Y1fCB1P1Ks7nroxxMHjOOaLSL2v5aDR8i+5PcWpLlV/PsEhf14ToX4L9WLORVKavvQIk0ObDlvy3E3B3azdMYnELg+0h3iI7cAdBk575A6tcyfR8ITZQo3FQwx9IrFqr3hNxwiaPpPFxZR9oSPCaARXVzMS0ykRUB9dMyW+W8munidUkMEMB/LRZ4AHZBMxZXBlQxEMKjA8EmfXjOHZnA6Xb7VAEpNgEc/pE7kn84QbKeULId/Uy3hYVpV2IKFSlQ21tdQ7pYEqMzwk7CozXI8zLl8f8WWH5iLmjxkFUtEI2niDp5RJuH+QOMQRVmJFsg12vMKMjiO4CMAUy66btlHmeiKxIC9rImWrW8Jh2OJXqKLuOq7iRs2rjrp8XoM0ZXSyxqeXVsRqYowz1Ss4oKD42JEVZLDSYxQ6Z59YaQArrtUkVtoGKy10+W34t7TAiZb3p6XrN4mWjkHLgMTQmZNnaQIrdqM8i+sbsHzlghSSEsmbWxFQVrVdKMuRoRAcXqqxFHy2NrKMjIR8AFTRaPwg712f+znDWwc3fP0OAe1oZOTVYOP279E0/pP++tdAXP9zs+j74XRDZHrfv/08eOjfny3CWcu5EsHsk2H1NZPqZhxyIfgUbpAovJRJg5QxHjxms4SERppgjKjA8ZiIAjadzUO8NobplIgJwwL8SU73pjFU2u44hYaspqSXt5bta1NtzhdxQNRT6wmBpiizc5GipL+GoqVJsy5Wt7JrWPkL2Bgk9/3vlYw7hwaL1Lwc9KayG8rShzcAsKyi5lOnPiA6W4Hw6wHC6ebt6FgVgUDeFkUFQMCA4te1ajNZYV7S4M7m96z4SjTWSptXTNvg7mxEGYGB78kdBCg61bxLswAs8EjKCNaF7bYNP18TkrqPypLZn/ZR9hZFBUiuFKUV+Wg0J3vxY12DrOvPg963H/37lK55EtGew+J1DktXwlkidDYJUSo8EgwTa5ZhuAVVdChfiXRfqcepu4Lp6oTrimrylbpPdtEBfGU66YykzDF4PCVllZIyIzjfMK8KXbenMXHYpGwjMLYBTF0R+1GsqfU7Kt+qKcr3/feN8tMM9aOE+cX+8l1i/apYGLH+gbHYsEns+EzuroT0CYpjWczFUd/PPqVV4I1rtY4DotIYCTXJ9RihTbciY54evOuKaoqRXCf/HtS2StuV3i+ov6eYyjxC0xNQZ5WAoiNZLHNUl4WSDUFbW1Ur56Wuv0VRTWh7+tasfsivtwuV1t8T2v/PnTw15OfWhYV8pWcPyGrfAbiVvbG1RVEDtlJsc5cuSTyRgdEp8Tx84ulrC2cDEk/zRPBoE8/ta6nX5LU0XWrevJYaimpaS33Nk9rdQ6yN5vcNR702FnP5LulvVeaM9HdH5mrDwjw0KDmO+jjZwMmDvcWDeXp0725JdDul9ffj8dK+75boHstJa+n2TWcHqguOuLLTWMtCKL88mcFVXaezevLqVeTe6XYvvHJVdX0yoG0lpRFlYcvapfXz5JsDlO/D/vKd7FutgrPj7zBdggkl8YeYJs3a5dTTYbsm528oquskWNvl9A+xteM4BqBfARUw4oTA/2D5IwAoPEbyhzjp9wu27FYUZtdI5oP4iSifD9RdQhHS4YhxLKsFOIL/QzKm0YUB+sG/5my9PVO2Nf/jb0iVUwPmUuW2Bk9931Sa+88/8ZnK6YuUQ/khr+rXe/rWr7+npVjfkEwPmCv6Ibhc/QYuqb76nSHq/wc= \ No newline at end of file diff --git a/doc/tracker_sequence_diagram.svg b/doc/tracker_sequence_diagram.svg new file mode 100644 index 0000000..ee79363 --- /dev/null +++ b/doc/tracker_sequence_diagram.svg @@ -0,0 +1,3 @@ + + +
Tracker
Tracker
Client1
Client1
:Object
:Object
Server1
Server1
Note
Note
REGISTER(udp+tcp)
REGISTER(udp+tc...
LIST REQ
LIST REQ
LIST RESP(file1, file2)
LIST RESP(f...
DISCOVER RESP(server1-udp-tcp, server2-udp-tcp, server3-udp-tcp)
DISCOVER RE...
Server2
Server2
REGISTER(udp+tcp)
REGISTER(ud...
LIST REQ
LIST REQ
DISCOVER REQ()
DISCOVER RE...
LIST RESP(file2, file3)
LIST RESP(f...
LIST REQ
LIST REQ
Server3
Server3
REGISTER(udp+tcp)
REGISTER(ud...
LIST REQ
LIST REQ
LIST RESP(file1, file3)
LIST RESP(f...
LIST RESP(file2, file2)
LIST RESP(f...
DISCOVER REQ(fichier2)
DISCOVER RE...
Now the client knows server1 and server3 have file1: download can begin.
Now the client knows server1 and server3 have file1: download can begin.
DISCOVER RESP(server1-udp-tcp, server3-udp-tcp)
DISCOVER RE...
Viewer does not support full SVG 1.1
\ No newline at end of file -- 2.30.2 From f1beed30e11753ceaa70998225eff79c71bedf61 Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 19 Mar 2020 15:51:02 +0100 Subject: [PATCH 03/13] Update doc --- doc/protocol.md | 3 --- doc/tracker_sequence_diagram.drawio | 2 +- doc/tracker_sequence_diagram.svg | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/doc/protocol.md b/doc/protocol.md index a2cf4d5..a01a6c9 100644 --- a/doc/protocol.md +++ b/doc/protocol.md @@ -105,12 +105,10 @@ A algo hash bloc contains: ### Tracker specific messages #### Register Used by a server to register itself on a tracker. -Payload contains `0x01` if working on udp, `0x02` if working on tcp, `0x03` if working on both. Server may want to do a free `DISCOVER` to check if they have been registered. #### Unregister Used by a server to unregister itself from a tracker. -Payload contains `0x01` if unregister from udp, `0x02` if unregister from tcp, `0x03` if unregister on both. No error is raised if the server was not registered. Server may want to do a free `DISCOVER` to check if they have been unregistered. @@ -135,7 +133,6 @@ Server block is composed with: ``` 2 bytes: [port] -1 byte: [protocols (udp: 0x01, tcp: 0x02, tcp+udp: 0x03)] ? bytes: hostname \n ``` diff --git a/doc/tracker_sequence_diagram.drawio b/doc/tracker_sequence_diagram.drawio index baa61f9..85919a8 100644 --- a/doc/tracker_sequence_diagram.drawio +++ b/doc/tracker_sequence_diagram.drawio @@ -1 +1 @@ -7Ztfc+I2EMA/DTO5h2RsyzbwmBCS3vR6lwvptdM3YQtQIyxqRP7003eFZYMlbDjHEJOSh4y8lteS9qfVrmRaqDd9uY3xbPIbDwlrOVb40kLXLcfp+B34LwWvicDtdhPBOKZhIrJXggH9lyihpaQLGpJ5rqLgnAk6ywsDHkUkEDkZjmP+nK824iz/1hkeE0MwCDAzpX/QUEyU1Las1Y1fCB1P1Ks7nroxxMHjOOaLSL2v5aDR8i+5PcWpLlV/PsEhf14ToX4L9WLORVKavvQIk0ObDlvy3E3B3azdMYnELg+0h3iI7cAdBk575A6tcyfR8ITZQo3FQwx9IrFqr3hNxwiaPpPFxZR9oSPCaARXVzMS0ykRUB9dMyW+W8munidUkMEMB/LRZ4AHZBMxZXBlQxEMKjA8EmfXjOHZnA6Xb7VAEpNgEc/pE7kn84QbKeULId/Uy3hYVpV2IKFSlQ21tdQ7pYEqMzwk7CozXI8zLl8f8WWH5iLmjxkFUtEI2niDp5RJuH+QOMQRVmJFsg12vMKMjiO4CMAUy66btlHmeiKxIC9rImWrW8Jh2OJXqKLuOq7iRs2rjrp8XoM0ZXSyxqeXVsRqYowz1Ss4oKD42JEVZLDSYxQ6Z59YaQArrtUkVtoGKy10+W34t7TAiZb3p6XrN4mWjkHLgMTQmZNnaQIrdqM8i+sbsHzlghSSEsmbWxFQVrVdKMuRoRAcXqqxFHy2NrKMjIR8AFTRaPwg712f+znDWwc3fP0OAe1oZOTVYOP279E0/pP++tdAXP9zs+j74XRDZHrfv/08eOjfny3CWcu5EsHsk2H1NZPqZhxyIfgUbpAovJRJg5QxHjxms4SERppgjKjA8ZiIAjadzUO8NobplIgJwwL8SU73pjFU2u44hYaspqSXt5bta1NtzhdxQNRT6wmBpiizc5GipL+GoqVJsy5Wt7JrWPkL2Bgk9/3vlYw7hwaL1Lwc9KayG8rShzcAsKyi5lOnPiA6W4Hw6wHC6ebt6FgVgUDeFkUFQMCA4te1ajNZYV7S4M7m96z4SjTWSptXTNvg7mxEGYGB78kdBCg61bxLswAs8EjKCNaF7bYNP18TkrqPypLZn/ZR9hZFBUiuFKUV+Wg0J3vxY12DrOvPg963H/37lK55EtGew+J1DktXwlkidDYJUSo8EgwTa5ZhuAVVdChfiXRfqcepu4Lp6oTrimrylbpPdtEBfGU66YykzDF4PCVllZIyIzjfMK8KXbenMXHYpGwjMLYBTF0R+1GsqfU7Kt+qKcr3/feN8tMM9aOE+cX+8l1i/apYGLH+gbHYsEns+EzuroT0CYpjWczFUd/PPqVV4I1rtY4DotIYCTXJ9RihTbciY54evOuKaoqRXCf/HtS2StuV3i+ov6eYyjxC0xNQZ5WAoiNZLHNUl4WSDUFbW1Ur56Wuv0VRTWh7+tasfsivtwuV1t8T2v/PnTw15OfWhYV8pWcPyGrfAbiVvbG1RVEDtlJsc5cuSTyRgdEp8Tx84ulrC2cDEk/zRPBoE8/ta6nX5LU0XWrevJYaimpaS33Nk9rdQ6yN5vcNR702FnP5LulvVeaM9HdH5mrDwjw0KDmO+jjZwMmDvcWDeXp0725JdDul9ffj8dK+75boHstJa+n2TWcHqguOuLLTWMtCKL88mcFVXaezevLqVeTe6XYvvHJVdX0yoG0lpRFlYcvapfXz5JsDlO/D/vKd7FutgrPj7zBdggkl8YeYJs3a5dTTYbsm528oquskWNvl9A+xteM4BqBfARUw4oTA/2D5IwAoPEbyhzjp9wu27FYUZtdI5oP4iSifD9RdQhHS4YhxLKsFOIL/QzKm0YUB+sG/5my9PVO2Nf/jb0iVUwPmUuW2Bk9931Sa+88/8ZnK6YuUQ/khr+rXe/rWr7+npVjfkEwPmCv6Ibhc/QYuqb76nSHq/wc= \ No newline at end of file +7Vtfc+I2EP80zFwfkrEt28BjQkh60+tdEtJrp2/CFqBGWFSI/LlP3xWWDZbAEJ8hZpo8MNJqvZJ2f1rtSkoL9aYvNwLPJr/zmLCW58QvLXTV8rxO2IFfRXhNCX63mxLGgsYpyV0RBvQH0URHUxc0JvMCo+ScSTorEiOeJCSSBRoWgj8X2UacFXud4TGxCIMIM5v6J43lRFNdx1k1/EroeKK77gS6YYijx7Hgi0T31/LQaPmXNk9xJkvzzyc45s9rJNRvoZ7gXKal6UuPMKXaTG3pd9dbWvNxC5LIfT5oD/EQu5E/jLz2yB86Z14q4QmzhdbFg4A5EaHHK18zHcHQZ6q4mLIvdEQYTaB2OSOCTokEfnTFNPl2Rbt8nlBJBjMcqU+fATxAm8gpg5oLRTCoxPCJyOuM4dmcDpe9OkARJFqIOX0i92Se4kZR+UKqnno5Hpasyg4k1qJyVTtLuVMa6TLDQ8Iuc8P1OOOq+4QvJzSXgj/mKFCCRjDGazylTIH7OxExTrAmayS7YMdLzOg4gUoEplhO3baNNtcTEZK8rJG0rW4IB7WJV2DRrZ6vcaPXVUdXn9dAmmF0sobPIGPEemGMc9ErcEBB42NPrCALKz1GYXLuB1YagBXfaRJW2hZWWuji2/AfZYEPtLw/Wrphk9DSsdAyIAIm8+FZmoAVt1GexQ8tsHzlkmxFSqIad0JAW9X1oaw0QyE4vNC6lHy2pllGRlJ9AKJoMn5QbVdnYcHwztENX79DQHsaGQU12Lj9RzIVf9Hf/h7Iq3+vF/0wnm6ITO/7N58HD/37T79Yxl6zpGm9IZeST6GBJPGFyhUUjfHosWxxSCzGRG5BoB4ZiQtJha3ZNdVlK0EQhiW4kUJnm1Snpd1yCiNbrcSgaCQ3NFbYnC9ERPRX63mAISg37zZBqQIsQUtL5lOsblzfMu4XMC1Q7vt3lYw7hwHLzLwc5Ga0a8qyjzcAYMmil1GnMiA6bwdEWA8gvG7Rjp5TERAo2CFoCyBAofh1jW2mGOYlA+5s7meFr1RirWgLtqNtcPtpRBkBxffUwQEUvWre5V0BuK9H0kZwzl2/bbn3miBp+qg8h32zj3J3CNoCyZWgjJGPRnNyED/WtZB19XnQ+/a9f5+ha54FsgpfacVbr6Bmwi01UjncSiGJ3s0nItMnmmHovgD0TSSbgmryiabv9dERfGK2uKycy7Pw+JFzHT/nCoL3zLk2Asa1APOTAflJbJn1+6fQqSmID8P3DeKzvPNEo/gyr9iEUL4qLKxQ/siw2HD064VMnZnE9AmKY1UshEl3yoGkLNDjGlcjQVQaGqFGux4roulWxFhgxuamoJpCI98r9oPaTum4svYt/AcKpeyLMTO/9Fb55SkE/GWusanQNnbVymmnH+4QVBO0A/PA1by6N8eFSvkPBO3/50GdVvmZc+6gUAs+AGSN232/sjd2dghqwEmJax/CpfkmsmD0kW8eP98MjY2zAfmmfc/X8Hxz9xYanNQWmu0wP72FWoJq2kJDw4G63WNsifZjhVPaEstw2YSstyrmrKx3T8zVBgv7KqDkkulkk4APD1ZvEmAG9f6O/LZTyn8Yj5fNfb/8tqH3p6WnNp09UL3vhVZ+x+o4CBW3JzumquvO1cxZg4q497rd86BcVF0PAYwTpCyQ3Dqydil/Efm2gopzOFyak0feW26E72C5RBNKxCkuk4YfbppZsFuT87cE1XXvaxxuhsc40fE8C6BfASpg1QmB32j5oh8Kj4n6r5rslYKrppXEeR2pNBA/Ee3zAXUXUIQsOGEcK7YIJ/A7JGOanFtAP/rTzK1wf8MjWMP/hBsy5MyAhQy5bYCnvgeS9rHzHo9PTiHyPK33JqbfCaq+wTNPeMMDbb3muWN2j1zR70B19Q9sKfvqnwRR/z8= \ No newline at end of file diff --git a/doc/tracker_sequence_diagram.svg b/doc/tracker_sequence_diagram.svg index ee79363..7018a9a 100644 --- a/doc/tracker_sequence_diagram.svg +++ b/doc/tracker_sequence_diagram.svg @@ -1,3 +1,3 @@ -
Tracker
Tracker
Client1
Client1
:Object
:Object
Server1
Server1
Note
Note
REGISTER(udp+tcp)
REGISTER(udp+tc...
LIST REQ
LIST REQ
LIST RESP(file1, file2)
LIST RESP(f...
DISCOVER RESP(server1-udp-tcp, server2-udp-tcp, server3-udp-tcp)
DISCOVER RE...
Server2
Server2
REGISTER(udp+tcp)
REGISTER(ud...
LIST REQ
LIST REQ
DISCOVER REQ()
DISCOVER RE...
LIST RESP(file2, file3)
LIST RESP(f...
LIST REQ
LIST REQ
Server3
Server3
REGISTER(udp+tcp)
REGISTER(ud...
LIST REQ
LIST REQ
LIST RESP(file1, file3)
LIST RESP(f...
LIST RESP(file2, file2)
LIST RESP(f...
DISCOVER REQ(fichier2)
DISCOVER RE...
Now the client knows server1 and server3 have file1: download can begin.
Now the client knows server1 and server3 have file1: download can begin.
DISCOVER RESP(server1-udp-tcp, server3-udp-tcp)
DISCOVER RE...
Viewer does not support full SVG 1.1
\ No newline at end of file +
Tracker
Tracker
Client1
Client1
:Object
:Object
Server1
Server1
Note
Note
REGISTER()
REGISTER()
LIST REQ
LIST REQ
LIST RESP(file1, file2)
LIST RESP(f...
DISCOVER RESP(server1, server2, server3)
DISCOVER RE...
Server2
Server2
REGISTER()
REGISTER()
LIST REQ
LIST REQ
DISCOVER REQ()
DISCOVER RE...
LIST RESP(file2, file3)
LIST RESP(f...
LIST REQ
LIST REQ
Server3
Server3
REGISTER()
REGISTER()
LIST REQ
LIST REQ
LIST RESP(file1, file3)
LIST RESP(f...
LIST RESP(file2, file2)
LIST RESP(f...
DISCOVER REQ(fichier2)
DISCOVER RE...
Now the client knows server1 and server3 have file1: download can begin.
Now the client knows server1 and server3 have file1: download can begin.
DISCOVER RESP(server1, server3)
DISCOVER RE...
Viewer does not support full SVG 1.1
\ No newline at end of file -- 2.30.2 From 5c89bc6957251ad5fbc3ccea43f8d0778cbdd87e Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 19 Mar 2020 17:31:03 +0100 Subject: [PATCH 04/13] Add protocol elements for tracker Needs to implements tracker now. --- src/protocolP2P/CodeType.java | 1 + src/protocolP2P/DiscoverRequest.java | 65 +++++++++++++ src/protocolP2P/DiscoverResponse.java | 111 ++++++++++++++++++++++ src/protocolP2P/FilePart.java | 2 +- src/protocolP2P/Payload.java | 39 +++++--- src/protocolP2P/ProtocolP2PPacket.java | 7 ++ src/protocolP2P/ProtocolP2PPacketTCP.java | 12 +++ src/protocolP2P/ProtocolP2PPacketUDP.java | 13 ++- src/protocolP2P/RequestResponseCode.java | 7 +- src/remoteException/NotATracker.java | 7 ++ src/serverP2P/ServerManagementTCP.java | 25 ++++- src/serverP2P/ServerManagementUDP.java | 17 ++++ src/tools/BytesArrayTools.java | 31 ++++++ src/tools/HostItem.java | 14 +++ 14 files changed, 334 insertions(+), 17 deletions(-) create mode 100644 src/protocolP2P/DiscoverRequest.java create mode 100644 src/protocolP2P/DiscoverResponse.java create mode 100644 src/remoteException/NotATracker.java diff --git a/src/protocolP2P/CodeType.java b/src/protocolP2P/CodeType.java index e38de49..87f3e49 100644 --- a/src/protocolP2P/CodeType.java +++ b/src/protocolP2P/CodeType.java @@ -8,6 +8,7 @@ package protocolP2P; */ public enum CodeType { REQUEST, + REQUEST_TRACKER, RESPONSE, ERROR } diff --git a/src/protocolP2P/DiscoverRequest.java b/src/protocolP2P/DiscoverRequest.java new file mode 100644 index 0000000..b3a83aa --- /dev/null +++ b/src/protocolP2P/DiscoverRequest.java @@ -0,0 +1,65 @@ +package protocolP2P; +import protocolP2P.Payload; +import tools.BytesArrayTools; +import localException.InternalError; +import localException.SizeError; +import localException.ProtocolError; +import localException.TransmissionError; + +public class DiscoverRequest extends Payload { + + private String filename; + + /** Constructor with filename (typically used by client). If filename is null, it is initialized with "". + * @param filename Name of the file you want a server list of. + * @throws InternalError + */ + public DiscoverRequest(String filename) throws InternalError { + super(RequestResponseCode.DISCOVER_REQUEST); + if (filename == null) { + this.filename = ""; + } else { + this.filename = filename; + } + } + + /** Constructor (typically used by server) with a byte[] parameter containing the Packet received. + * @param packet the full Packet received + * @throws SizeError + * @throws InternalError + * @throws ProtocolError + * @throws TransmissionError + */ + protected DiscoverRequest(byte[] packet) throws SizeError, ProtocolError, InternalError, TransmissionError { + super(packet); + int size = getPayloadSize(packet); + filename = BytesArrayTools.readString(packet, Payload.PAYLOAD_START_POSITION, size); + } + + /** Returns a byte[] containing Packet with padding. + * This Packet is still incomplete and should not be send directly. + * ProtocolP2PPacket will use this method to generate the complete Packet. + * @return Packet with padding + * @throws InternalError + */ + protected byte[] toPacket() throws InternalError { + // compute total size + int size = PAYLOAD_START_POSITION + filename.length(); + byte[] packet = new byte[size + 1]; // java initialize all to zero + // set request/response code + packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue; + // set Payload size + setPayloadSize(size - PAYLOAD_START_POSITION, packet); + // write filename to Packet + BytesArrayTools.write(packet, filename, PAYLOAD_START_POSITION); + return packet; + } + + /** Filename getter. + * @return filename + */ + public String getFilename() { + return filename; + } + +} diff --git a/src/protocolP2P/DiscoverResponse.java b/src/protocolP2P/DiscoverResponse.java new file mode 100644 index 0000000..b887dea --- /dev/null +++ b/src/protocolP2P/DiscoverResponse.java @@ -0,0 +1,111 @@ +package protocolP2P; +import protocolP2P.Payload; +import tools.HostItem; +import java.util.ArrayList; +import java.util.List; +import localException.InternalError; +import localException.SizeError; +import localException.ProtocolError; +import localException.TransmissionError; +import tools.BytesArrayTools; + +public class DiscoverResponse extends Payload { + + private List hostList; + private String filename; + private static final int FILENAME_SIZE_POSITION = PAYLOAD_START_POSITION; + private static final int FILENAME_POSITION = FILENAME_SIZE_POSITION + 4; + + /** Constructor with filename (typically used by tracker). If filename is null, it is initialized with "". + * @param filename Name of the file related to the server list. + * @param hostList List of servers + * @throws InternalError + */ + public DiscoverResponse(String filename, List hostList) throws InternalError { + super(RequestResponseCode.DISCOVER_RESPONSE); + this.filename = filename; + this.hostList = hostList; + } + + /** Constructor (typically used by server) with a byte[] parameter containing the Packet received. + * @param packet the full Packet received + * @throws SizeError + * @throws InternalError + * @throws ProtocolError + * @throws TransmissionError + */ + protected DiscoverResponse(byte[] packet) throws SizeError, ProtocolError, InternalError, TransmissionError { + super(packet); + int size = getPayloadSize(packet); + /* Read filename size */ + int filenameSize = BytesArrayTools.readInt(packet, FILENAME_SIZE_POSITION); + + /* Read filename */ + filename = BytesArrayTools.readString(packet, FILENAME_POSITION, filenameSize); + + // TODO + hostList = new ArrayList<>(); + int i = FILENAME_POSITION + filenameSize; + while(i getHostList() { + return hostList; + } + + /** Filename getter. + * @return filename + */ + public String getFilename() { + return filename; + } +} diff --git a/src/protocolP2P/FilePart.java b/src/protocolP2P/FilePart.java index 0863c0b..c394b0f 100644 --- a/src/protocolP2P/FilePart.java +++ b/src/protocolP2P/FilePart.java @@ -83,7 +83,7 @@ public class FilePart extends Payload { // set request/response code packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue; // set Payload size - setPayloadSize(size - OFFSET_POSITION, packet); + setPayloadSize(size - PAYLOAD_START_POSITION, packet); // write offset to Packet BytesArrayTools.write(packet, OFFSET_POSITION, offset); // write totalSize to Packet diff --git a/src/protocolP2P/Payload.java b/src/protocolP2P/Payload.java index f0dcb34..8a84384 100644 --- a/src/protocolP2P/Payload.java +++ b/src/protocolP2P/Payload.java @@ -5,6 +5,8 @@ import protocolP2P.FileList; import protocolP2P.LoadRequest; import protocolP2P.HashRequest; import protocolP2P.HashResponse; +import protocolP2P.DiscoverRequest; +import protocolP2P.DiscoverResponse; import localException.ProtocolError; import localException.InternalError; import localException.TransmissionError; @@ -27,11 +29,13 @@ public class Payload { */ public Payload(RequestResponseCode requestResponseCode) throws InternalError { /* asserts to help debugging */ - assert requestResponseCode != RequestResponseCode.LIST_RESPONSE || (this instanceof FileList) : "LIST_RESPONSE must use FilePart class"; - assert requestResponseCode != RequestResponseCode.LOAD_RESPONSE || (this instanceof FilePart) : "LOAD_RESPONSE must use FileList class"; - assert requestResponseCode != RequestResponseCode.LOAD_REQUEST || (this instanceof LoadRequest) : "LOAD_REQUEST must use LoadRequest class"; - assert requestResponseCode != RequestResponseCode.HASH_REQUEST || (this instanceof HashRequest) : "HASH_REQUEST must use HashRequest class"; - assert requestResponseCode != RequestResponseCode.HASH_RESPONSE || (this instanceof HashResponse) : "HASH_RESPONSE must use HashResponse class"; + assert requestResponseCode != RequestResponseCode.LIST_RESPONSE || (this instanceof FileList) : "LIST_RESPONSE must use FilePart class"; + assert requestResponseCode != RequestResponseCode.LOAD_RESPONSE || (this instanceof FilePart) : "LOAD_RESPONSE must use FileList class"; + assert requestResponseCode != RequestResponseCode.LOAD_REQUEST || (this instanceof LoadRequest) : "LOAD_REQUEST must use LoadRequest class"; + assert requestResponseCode != RequestResponseCode.HASH_REQUEST || (this instanceof HashRequest) : "HASH_REQUEST must use HashRequest class"; + assert requestResponseCode != RequestResponseCode.HASH_RESPONSE || (this instanceof HashResponse) : "HASH_RESPONSE must use HashResponse class"; + assert requestResponseCode != RequestResponseCode.DISCOVER_REQUEST || (this instanceof DiscoverRequest) : "DISCOVER_REQUEST must use DiscoverRequest class"; + assert requestResponseCode != RequestResponseCode.DISCOVER_RESPONSE || (this instanceof DiscoverResponse) : "DISCOVER_RESPONSE must use DiscoverResponse class"; this.requestResponseCode = requestResponseCode; checkRequestResponseCode(); // this can throw InternalError } @@ -46,13 +50,17 @@ public class Payload { */ protected Payload(byte[] packet) throws SizeError, ProtocolError, InternalError, TransmissionError { /* asserts to help debugging */ - assert getPayloadSize(packet) + 8 <= packet.length : "Payload is truncated"; - if (packet.length < getPayloadSize(packet) + 8) { + assert getPayloadSize(packet) + PAYLOAD_START_POSITION <= packet.length : "Payload is truncated"; + if (packet.length < getPayloadSize(packet) + PAYLOAD_START_POSITION) { throw new TransmissionError(); } - assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LIST_RESPONSE || (this instanceof FileList) : "LIST_RESPONSE must use FilePart class"; - assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LOAD_RESPONSE || (this instanceof FilePart) : "LOAD_RESPONSE must use FileList class"; - assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LOAD_REQUEST || (this instanceof LoadRequest) : "LOAD_REQUEST must use LoadRequest class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LIST_RESPONSE || (this instanceof FileList) : "LIST_RESPONSE must use FilePart class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LOAD_RESPONSE || (this instanceof FilePart) : "LOAD_RESPONSE must use FileList class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LOAD_REQUEST || (this instanceof LoadRequest) : "LOAD_REQUEST must use LoadRequest class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.HASH_REQUEST || (this instanceof HashRequest) : "HASH_REQUEST must use HashRequest class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.HASH_RESPONSE || (this instanceof HashResponse) : "HASH_RESPONSE must use HashResponse class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.DISCOVER_REQUEST || (this instanceof DiscoverRequest) : "DISCOVER_REQUEST must use DiscoverRequest class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.DISCOVER_RESPONSE || (this instanceof DiscoverResponse) : "DISCOVER_RESPONSE must use DiscoverResponse class"; requestResponseCode = RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]); checkRequestResponseCode(); // this can throw InternalError } @@ -62,9 +70,14 @@ public class Payload { */ private void checkRequestResponseCode() throws InternalError { /* Incorrect use cases (use subclasses instead) */ - if ((requestResponseCode == RequestResponseCode.LIST_RESPONSE && !(this instanceof FileList)) - || (requestResponseCode == RequestResponseCode.LOAD_RESPONSE && !(this instanceof FilePart)) - || (requestResponseCode == RequestResponseCode.LOAD_REQUEST && !(this instanceof LoadRequest))) { + if ((requestResponseCode == RequestResponseCode.LIST_RESPONSE && !(this instanceof FileList)) + || (requestResponseCode == RequestResponseCode.LOAD_RESPONSE && !(this instanceof FilePart)) + || (requestResponseCode == RequestResponseCode.LOAD_REQUEST && !(this instanceof LoadRequest)) + || (requestResponseCode == RequestResponseCode.HASH_REQUEST && !(this instanceof HashRequest)) + || (requestResponseCode == RequestResponseCode.HASH_RESPONSE && !(this instanceof HashResponse)) + || (requestResponseCode == RequestResponseCode.DISCOVER_REQUEST && !(this instanceof DiscoverRequest)) + || (requestResponseCode == RequestResponseCode.DISCOVER_RESPONSE && !(this instanceof DiscoverResponse)) + ) { throw new InternalError(); } } diff --git a/src/protocolP2P/ProtocolP2PPacket.java b/src/protocolP2P/ProtocolP2PPacket.java index be23aec..037da9b 100644 --- a/src/protocolP2P/ProtocolP2PPacket.java +++ b/src/protocolP2P/ProtocolP2PPacket.java @@ -13,6 +13,7 @@ import remoteException.VersionRemoteError; import remoteException.EmptyFile; import java.net.InetAddress; import java.io.IOException; +import tools.HostItem; /** Representation of packet. * @author Louis Royer @@ -50,6 +51,12 @@ public abstract class ProtocolP2PPacket { */ public abstract void sendResponse(ProtocolP2PPacket response) throws InternalError, IOException, SocketClosed; + /** Get hostItem of the sender + * @return hostItem of the sender + * @throws InternalError + */ + public abstract HostItem getHostItem() throws InternalError; + /** Receive a response * @throws EmptyFile * @throws NotFound diff --git a/src/protocolP2P/ProtocolP2PPacketTCP.java b/src/protocolP2P/ProtocolP2PPacketTCP.java index 7c80474..ddde5f3 100644 --- a/src/protocolP2P/ProtocolP2PPacketTCP.java +++ b/src/protocolP2P/ProtocolP2PPacketTCP.java @@ -12,6 +12,7 @@ import remoteException.ProtocolRemoteError; import remoteException.VersionRemoteError; import remoteException.EmptyFile; import tools.BytesArrayTools; +import tools.HostItem; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; import protocolP2P.LoadRequest; @@ -319,4 +320,15 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { return packet; } + /** Get hostItem of the sender + * @return hostItem of the sender + * @throws InternalError + */ + public HostItem getHostItem() throws InternalError { + if (responseSocket == null) { + throw new InternalError(); + } + return new HostItem(responseSocket.getInetAddress().getHostName(), responseSocket.getPort()); + } + } diff --git a/src/protocolP2P/ProtocolP2PPacketUDP.java b/src/protocolP2P/ProtocolP2PPacketUDP.java index aea6dcc..db92d2f 100644 --- a/src/protocolP2P/ProtocolP2PPacketUDP.java +++ b/src/protocolP2P/ProtocolP2PPacketUDP.java @@ -12,6 +12,7 @@ import remoteException.ProtocolRemoteError; import remoteException.VersionRemoteError; import remoteException.EmptyFile; import tools.BytesArrayTools; +import tools.HostItem; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; import protocolP2P.LoadRequest; @@ -353,7 +354,6 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { * @param packet full packet * @throws TransmissionError */ - private void checkCheckSum(byte [] packet) throws TransmissionError { try { int checksum = BytesArrayTools.readInt16Bits(packet, CHECKSUM_POSITION); @@ -365,4 +365,15 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { throw new TransmissionError(); } } + + /** Get hostItem of the sender + * @return hostItem of the sender + * @throws InternalError + */ + public HostItem getHostItem() throws InternalError { + if (responseSocket == null) { + throw new InternalError(); + } + return new HostItem(responseSocket.getInetAddress().getHostName(), responseSocket.getPort()); + } } diff --git a/src/protocolP2P/RequestResponseCode.java b/src/protocolP2P/RequestResponseCode.java index a6e68d3..f216d8c 100644 --- a/src/protocolP2P/RequestResponseCode.java +++ b/src/protocolP2P/RequestResponseCode.java @@ -15,15 +15,20 @@ public enum RequestResponseCode { LIST_REQUEST(CodeType.REQUEST, (byte)0x00), LOAD_REQUEST(CodeType.REQUEST, (byte)0x01), HASH_REQUEST(CodeType.REQUEST, (byte)0x02), + DISCOVER_REQUEST(CodeType.REQUEST_TRACKER, (byte)0x03), + REGISTER(CodeType.REQUEST_TRACKER, (byte)0x04), + UNREGISTER(CodeType.REQUEST_TRACKER, (byte)0x05), LIST_RESPONSE(CodeType.RESPONSE, (byte)0x80), LOAD_RESPONSE(CodeType.RESPONSE, (byte)0x81), HASH_RESPONSE(CodeType.RESPONSE, (byte)0x82), + DISCOVER_RESPONSE(CodeType.RESPONSE, (byte)0x83), VERSION_ERROR(CodeType.ERROR, (byte)0xC0), PROTOCOL_ERROR(CodeType.ERROR, (byte)0xC1), INTERNAL_ERROR(CodeType.ERROR, (byte)0xC2), EMPTY_DIRECTORY(CodeType.ERROR, (byte)0xC3), NOT_FOUND(CodeType.ERROR, (byte)0xC4), - EMPTY_FILE(CodeType.ERROR, (byte)0xC5); + EMPTY_FILE(CodeType.ERROR, (byte)0xC5), + NOT_A_TRACKER(CodeType.ERROR, (byte)0xC6); public final CodeType codeType; public final byte codeValue; diff --git a/src/remoteException/NotATracker.java b/src/remoteException/NotATracker.java new file mode 100644 index 0000000..dbccea2 --- /dev/null +++ b/src/remoteException/NotATracker.java @@ -0,0 +1,7 @@ +package remoteException; + +import exception.RemoteException; + +public class NotATracker extends exception.RemoteException { + private static final long serialVersionUID = 12L; +} diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index 257fe3d..316143e 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -136,6 +136,18 @@ public class ServerManagementTCP implements Runnable { logger.writeTCP(addr + "HASH_REQUEST", LogLevel.Action); sendHashResponse(pd); break; + case DISCOVER_REQUEST: + logger.writeTCP(addr + "DISCOVER_REQUEST", LogLevel.Action); + sendNotATracker(pd); + break; + case UNREGISTER: + logger.writeTCP(addr + "UNREGISTER", LogLevel.Action); + sendNotATracker(pd); + break; + case REGISTER: + logger.writeTCP(addr + "REGISTER", LogLevel.Action); + sendNotATracker(pd); + break; default: logger.writeTCP(addr + "Received grabbage", LogLevel.Action); sendInternalError(pd); @@ -198,7 +210,18 @@ public class ServerManagementTCP implements Runnable { logger.writeTCP(e, LogLevel.Error); } } - + + /** Send a NotATracker error message. + * @param pd ProtocolP2PPacketTCP to respond + */ + private void sendNotATracker(ProtocolP2PPacketTCP pd) { + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.NOT_A_TRACKER))); + } catch (Exception e) { + logger.writeTCP(e, LogLevel.Error); + } + } + /** Send response to list request * @param pd Request received */ diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index 986e8d0..3289796 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -89,6 +89,12 @@ public class ServerManagementUDP implements Runnable { logger.writeUDP("Received HASH_REQUEST", LogLevel.Action); sendHashResponse(pd); break; + case DISCOVER_REQUEST: + case UNREGISTER: + case REGISTER: + logger.writeUDP("Received Tracker request", LogLevel.Action); + sendNotATracker(pd); + break; default: sendInternalError(pd); } @@ -213,6 +219,17 @@ public class ServerManagementUDP implements Runnable { } } + /** Send a NotATracker error message. + * @param pd ProtocolP2PPacketUDP to respond + */ + private void sendNotATracker(ProtocolP2PPacketUDP pd) { + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.NOT_A_TRACKER))); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); + } + } + /** Send hash response to hash request * @param pd Request received */ diff --git a/src/tools/BytesArrayTools.java b/src/tools/BytesArrayTools.java index 8f80fcb..f1cbe85 100644 --- a/src/tools/BytesArrayTools.java +++ b/src/tools/BytesArrayTools.java @@ -219,6 +219,37 @@ public class BytesArrayTools { } } + /** Read string from byte array + * @param array Byte array to read + * @param start start position in byte array + * @param endStr End string delimiter + * @return String read + * @throws InternalError + */ + public static String readString(byte[] array, int start, String endStr) throws InternalError { + boolean failed = false; + try { + int i = start; + while(true) { + for(byte b: endStr.getBytes()) { + if (b != array[i]) { + failed = true; + break; + } + } + if (failed) { + i++; + failed = false; + } else { + break; + } + } + return readString(array, start, i -1 - start); + } catch(IndexOutOfBoundsException e) { + throw new InternalError(); + } + } + /** Write byte Array to byte Array. * @param dst Destination byte Array * @param src Source byte Array diff --git a/src/tools/HostItem.java b/src/tools/HostItem.java index ffe2f58..9bba17b 100644 --- a/src/tools/HostItem.java +++ b/src/tools/HostItem.java @@ -79,10 +79,24 @@ public class HostItem { } return udpSocket; } + + /** Closes udp socket + */ public void closeUDPSocket() { if (udpSocket != null) { udpSocket.close(); } udpSocket = null; } + + /** Getter for hostname */ + public String getHostname() { + return hostname; + } + + /** Getter for port */ + public int getPort() { + return port; + } + } -- 2.30.2 From 6d7fabaf1c811378747cb0f8154b159069623fb4 Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 19 Mar 2020 22:58:57 +0100 Subject: [PATCH 05/13] Add tracker --- src/tools/HostItem.java | 7 + src/tracker/Tracker.java | 47 +++++ src/tracker/TrackerManagementTCP.java | 270 ++++++++++++++++++++++++++ src/tracker/TrackerManagementUDP.java | 221 +++++++++++++++++++++ 4 files changed, 545 insertions(+) create mode 100644 src/tracker/Tracker.java create mode 100644 src/tracker/TrackerManagementTCP.java create mode 100644 src/tracker/TrackerManagementUDP.java diff --git a/src/tools/HostItem.java b/src/tools/HostItem.java index 9bba17b..f2bfbf3 100644 --- a/src/tools/HostItem.java +++ b/src/tools/HostItem.java @@ -98,5 +98,12 @@ public class HostItem { public int getPort() { return port; } + + /** To string + * @return String representation + */ + public String toString() { + return getHostname() + " (port " + getPort() + ")"; + } } diff --git a/src/tracker/Tracker.java b/src/tracker/Tracker.java new file mode 100644 index 0000000..bb82422 --- /dev/null +++ b/src/tracker/Tracker.java @@ -0,0 +1,47 @@ +package tracker; +import tracker.TrackerManagementTCP; +import tracker.TrackerManagementUDP; +import tools.Directories; +import tools.Logger; + +/** Tracker implementation + * First argument of main method is port listened by the tracker, and is mandatory. + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class Tracker { + private int port; + private Directories directories; + private Logger logger; + + /** Constructor with portStr containing a port number. + * @param portStr String containing port number of listening. + */ + public Tracker(String portStr) { + port = Integer.valueOf(Integer.parseInt(portStr)); + directories = new Directories("P2P_JAVA_PROJECT_TRACKER_" + port); + logger = new Logger(directories.getDataHomeDirectory() + "tracker.log"); + System.out.println("Tracker will listen on port " + port + " and write logs into " + directories.getDataHomeDirectory()); + directories.askOpenDataHomeDirectory(null); + } + + /** Main program entry point + * first parameter is port number and is mandatory + * to test, run with: java -ea serverP2P.ServerP2P -- + * @param args parameters + */ + public static void main(String [] args) { + Tracker t = new Tracker(args[1]); + TrackerManagementUDP tmudp = new TrackerManagementUDP(t.port, t.logger); + TrackerManagementTCP tmtcp = new TrackerManagementTCP(t.port, t.logger); + Thread tudp = new Thread(tmudp); + tudp.setName("Tracker UDP P2P-JAVA-PROJECT"); + tudp.start(); + Thread ttcp = new Thread(tmtcp); + ttcp.setName("Tracker TCP P2P-JAVA-PROJECT"); + ttcp.start(); + } + +} diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java new file mode 100644 index 0000000..91d7dab --- /dev/null +++ b/src/tracker/TrackerManagementTCP.java @@ -0,0 +1,270 @@ +package tracker; +import tools.Logger; +import tools.LogLevel; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import protocolP2P.ProtocolP2PPacketTCP; +import protocolP2P.ProtocolP2PPacket; +import protocolP2P.RequestResponseCode; +import protocolP2P.Payload; +import tools.HostItem; +import java.util.ArrayList; +import java.util.List; +import java.io.IOException; +import exception.LocalException; +import java.util.Map; +import java.util.HashMap; +import protocolP2P.DiscoverRequest; +import protocolP2P.DiscoverResponse; +import protocolP2P.FileList; +import protocolP2P.HashRequest; +import localException.InternalError; + + +/** Tracker management implementation with tcp + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class TrackerManagementTCP implements Runnable { + + private int port; + private Logger logger; + private ServerSocket socket; + private List hostList = new ArrayList<>(); + private Map> fileList = new HashMap<>(); + + /** Constructor with port and logger. + * @param port Port used to listen. + * @param logger Logger object + */ + public TrackerManagementTCP(int port, Logger logger) { + this.port = port; + this.logger = logger; + try { + socket = new ServerSocket(port); + } catch (SocketException e) { + logger.writeTCP("Error: cannot listen on port " + port, LogLevel.Error); + System.exit(-1); + } catch (IOException e) { + logger.writeTCP("Error: cannot openning socket", LogLevel.Error); + System.exit(-2); + } + } + + /** Implementation of runnable. This methods allows to run the server. + */ + public void run() { + logger.writeTCP("Tracker sucessfully started", LogLevel.Info); + do { + try { + Socket s = socket.accept(); + ClientHandler c = new ClientHandler(s); + (new Thread(c)).start(); + } catch (IOException e) { + logger.writeTCP("Error while accepting new connection", LogLevel.Warning); + } + } while(true); + } + + + /** Private runnable class allowing to serve one client. + */ + private class ClientHandler implements Runnable { + private Socket s; + private String addr; + /** Constructor with a socket. + * @param s Socket of this client + */ + public ClientHandler(Socket s) { + this.s = s; + this.addr = "[" +s.getInetAddress().getHostAddress() + "]:" + s.getPort() + " "; + } + + /** Implementation of runnable. This method allow to serve one client. + */ + public void run() { + + boolean end = false; + logger.writeTCP(addr + "New connection", LogLevel.Action); + do { + end = handleRequest(); + } while(!end); + logger.writeTCP(addr + "End of connection", LogLevel.Action); + } + + /** Respond to next request incomming on socket s. + * @param s Socket used to read request and send response + * @return true if cannot expect another request (ie, socket is closed) + */ + private boolean handleRequest() { + try { + ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)socket); + Payload p = pd.getPayload(); + switch (p.getRequestResponseCode()) { + case LOAD_REQUEST: + logger.writeTCP("Received LOAD_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); + sendNotFound(pd); + break; + case LIST_REQUEST: + logger.writeTCP("Received LIST_REQUEST from host " + pd.getHostItem() + ", sending EMPTY_DIRECTORY", LogLevel.Action); + sendEmptyDirectory(pd); + break; + case HASH_REQUEST: + logger.writeTCP("Received HASH_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); + sendNotFound(pd); + break; + case REGISTER: + handleRegister(pd); + break; + case UNREGISTER: + handleUnregister(pd); + break; + case DISCOVER_REQUEST: + handleDiscover(pd); + break; + case LIST_RESPONSE: + handleListResponse(pd); + break; + default: + logger.writeTCP("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); + sendInternalError(pd); + break; + } + } catch (IOException e) { + logger.writeTCP(e, LogLevel.Warning); + return true; + } catch (LocalException e) { + logger.writeTCP(e, LogLevel.Warning); + return true; + } + return false; + } + + /** Send a not found message. + * @param pd ProtocolP2PPacketTCP to respond + */ + private void sendNotFound(ProtocolP2PPacketTCP pd) { + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.NOT_FOUND))); + } catch (Exception e) { + logger.writeTCP(e, LogLevel.Error); + } + } + + /** Send an empty directory message. + * @param pd ProtocolP2PPacketTCP to respond + */ + private void sendEmptyDirectory(ProtocolP2PPacketTCP pd) { + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); + } catch (Exception e) { + logger.writeTCP(e, LogLevel.Error); + } + } + + /** Send an internal error message. + * @param pd ProtocolP2PPacketTCP to respond + */ + private void sendInternalError(ProtocolP2PPacketTCP pd) { + logger.writeTCP("Internal Error", LogLevel.Warning); + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.INTERNAL_ERROR))); + } catch (Exception e) { + logger.writeTCP(e, LogLevel.Error); + } + } + + /** Handle Registering + * @param pd ProtocolP2PPacketTCP to respond + * @throws InternalError + */ + private void handleRegister(ProtocolP2PPacketTCP pd) throws InternalError { + // add host to known host list + HostItem host = pd.getHostItem(); + if (!hostList.contains(host)) { + hostList.add(pd.getHostItem()); + } + // send a list request + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.LIST_REQUEST))); + logger.writeTCP("Received REGISTER. Adding host " + host + " to list. Sending List request", LogLevel.Action); + } catch (Exception e) { + // remove from list because list request could not be send + hostList.remove(host); + logger.writeTCP("Aborting the add of host " + host, LogLevel.Action); + logger.writeTCP(e, LogLevel.Error); + } + } + + /** Handle Unregistering + * @param pd ProtocolP2PPacketTCP to respond + * @throws InternalError + */ + private void handleUnregister(ProtocolP2PPacketTCP pd) throws InternalError { + HostItem host = pd.getHostItem(); + logger.writeTCP("Received UNREGISTER. Removing host " + host, LogLevel.Action); + hostList.remove(host); + for(String f: fileList.keySet()) { + fileList.get(f).remove(host); + if(fileList.get(f).isEmpty()) { + fileList.remove(f); + } + } + } + + /** Handle Discover request + * @param pd ProtocolP2PPacketTCP to respond + * @throws InternalError + */ + private void handleDiscover(ProtocolP2PPacketTCP pd) throws InternalError { + logger.writeTCP("Received DISCOVER REQUEST from host " + pd.getHostItem(), LogLevel.Action); + Payload p = pd.getPayload(); + assert p instanceof DiscoverRequest : "payload must be an instance of DiscoverRequest"; + if (!(p instanceof DiscoverRequest)) { + sendInternalError(pd); + } else { + String filename = ((HashRequest)p).getFilename(); + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); + } catch (Exception e) { + logger.writeTCP(e, LogLevel.Error); + } + } + } + + /** Handle List Responses + * @param pd ProtocolP2PPacketTCP response + * @throws InternalError + */ + private void handleListResponse(ProtocolP2PPacketTCP pd) throws InternalError { + HostItem host = pd.getHostItem(); + if (!hostList.contains(host)) { + logger.writeTCP("Received LIST RESPONSE from host " + host + " but it is not registered.", LogLevel.Action); + } else { + logger.writeTCP("Received LIST RESPONSE from host " + host + ": registered host.", LogLevel.Action); + Payload p = pd.getPayload(); + assert p instanceof FileList: "payload must be an instance of FileList"; + if (!(p instanceof FileList)) { + sendInternalError(pd); + } else { + String[] f = ((FileList)p).getFileList(); + for (String file: f) { + List h = fileList.get(file); + if (h != null) { + if (!h.contains(host)) { + h.add(host); + } + } else { + List emptyH = new ArrayList<>(); + emptyH.add(host); + fileList.put(file, emptyH); + } + } + } + } + } + } +} diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java new file mode 100644 index 0000000..f1448f8 --- /dev/null +++ b/src/tracker/TrackerManagementUDP.java @@ -0,0 +1,221 @@ +package tracker; +import tools.Logger; +import tools.LogLevel; +import java.net.DatagramSocket; +import protocolP2P.ProtocolP2PPacketUDP; +import protocolP2P.ProtocolP2PPacket; +import protocolP2P.RequestResponseCode; +import protocolP2P.Payload; +import tools.HostItem; +import java.util.ArrayList; +import java.util.List; +import java.io.IOException; +import java.net.SocketException; +import exception.LocalException; +import java.util.Map; +import java.util.HashMap; +import protocolP2P.DiscoverRequest; +import protocolP2P.DiscoverResponse; +import protocolP2P.FileList; +import protocolP2P.HashRequest; +import localException.InternalError; + +/** Tracker management implementation with udp + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class TrackerManagementUDP implements Runnable { + + private int port; + private Logger logger; + private DatagramSocket socket; + private List hostList = new ArrayList<>(); + private Map> fileList = new HashMap<>(); + + /** Constructor with port and logger. + * @param port Port used to listen. + * @param logger Logger object + */ + public TrackerManagementUDP(int port, Logger logger) { + this.port = port; + this.logger = logger; + try { + socket = new DatagramSocket(port); + } catch (SocketException e) { + logger.writeUDP("Error: cannot listen on port " + port, LogLevel.Error); + System.exit(-1); + } + } + + /** Implementation of runnable. This methods allows to run the tracker. + */ + public void run() { + logger.writeUDP("Tracker successfully started", LogLevel.Info); + while(true) { + try { + ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP((Object)socket); + Payload p = pd.getPayload(); + switch (p.getRequestResponseCode()) { + case LOAD_REQUEST: + logger.writeUDP("Received LOAD_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); + sendNotFound(pd); + break; + case LIST_REQUEST: + logger.writeUDP("Received LIST_REQUEST from host " + pd.getHostItem() + ", sending EMPTY_DIRECTORY", LogLevel.Action); + sendEmptyDirectory(pd); + break; + case HASH_REQUEST: + logger.writeUDP("Received HASH_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); + sendNotFound(pd); + break; + case REGISTER: + handleRegister(pd); + break; + case UNREGISTER: + handleUnregister(pd); + break; + case DISCOVER_REQUEST: + handleDiscover(pd); + break; + case LIST_RESPONSE: + handleListResponse(pd); + break; + default: + logger.writeUDP("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); + sendInternalError(pd); + break; + } + } catch (IOException e) { + logger.writeUDP(e, LogLevel.Warning); + } catch (LocalException e) { + logger.writeUDP(e, LogLevel.Warning); + } + } + } + + /** Send a not found message. + * @param pd ProtocolP2PPacketUDP to respond + */ + private void sendNotFound(ProtocolP2PPacketUDP pd) { + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.NOT_FOUND))); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); + } + } + + /** Send an empty directory message. + * @param pd ProtocolP2PPacketUDP to respond + */ + private void sendEmptyDirectory(ProtocolP2PPacketUDP pd) { + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); + } + } + + /** Send an internal error message. + * @param pd ProtocolP2PPacketUDP to respond + */ + private void sendInternalError(ProtocolP2PPacketUDP pd) { + logger.writeUDP("Internal Error", LogLevel.Warning); + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); + } + } + + /** Handle Registering + * @param pd ProtocolP2PPacketUDP to respond + * @throws InternalError + */ + private void handleRegister(ProtocolP2PPacketUDP pd) throws InternalError { + // add host to known host list + HostItem host = pd.getHostItem(); + if (!hostList.contains(host)) { + hostList.add(pd.getHostItem()); + } + // send a list request + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST))); + logger.writeUDP("Received REGISTER. Adding host " + host + " to list. Sending List request", LogLevel.Action); + } catch (Exception e) { + // remove from list because list request could not be send + hostList.remove(host); + logger.writeUDP("Aborting the add of host " + host, LogLevel.Action); + logger.writeUDP(e, LogLevel.Error); + } + } + + /** Handle Unregistering + * @param pd ProtocolP2PPacketUDP to respond + * @throws InternalError + */ + private void handleUnregister(ProtocolP2PPacketUDP pd) throws InternalError { + HostItem host = pd.getHostItem(); + logger.writeUDP("Received UNREGISTER. Removing host " + host, LogLevel.Action); + hostList.remove(host); + for(String f: fileList.keySet()) { + fileList.get(f).remove(host); + if(fileList.get(f).isEmpty()) { + fileList.remove(f); + } + } + } + + /** Handle Discover request + * @param pd ProtocolP2PPacketUDP to respond + * @throws InternalError + */ + private void handleDiscover(ProtocolP2PPacketUDP pd) throws InternalError { + logger.writeUDP("Received DISCOVER REQUEST from host " + pd.getHostItem(), LogLevel.Action); + Payload p = pd.getPayload(); + assert p instanceof DiscoverRequest : "payload must be an instance of DiscoverRequest"; + if (!(p instanceof DiscoverRequest)) { + sendInternalError(pd); + } else { + String filename = ((HashRequest)p).getFilename(); + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); + } + } + } + + /** Handle List Responses + * @param pd ProtocolP2PPacketUDP response + * @throws InternalError + */ + private void handleListResponse(ProtocolP2PPacketUDP pd) throws InternalError { + HostItem host = pd.getHostItem(); + if (!hostList.contains(host)) { + logger.writeUDP("Received LIST RESPONSE from host " + host + " but it is not registered.", LogLevel.Action); + } else { + logger.writeUDP("Received LIST RESPONSE from host " + host + ": registered host.", LogLevel.Action); + Payload p = pd.getPayload(); + assert p instanceof FileList: "payload must be an instance of FileList"; + if (!(p instanceof FileList)) { + sendInternalError(pd); + } else { + String[] f = ((FileList)p).getFileList(); + for (String file: f) { + List h = fileList.get(file); + if (h != null) { + if (!h.contains(host)) { + h.add(host); + } + } else { + List emptyH = new ArrayList<>(); + emptyH.add(host); + fileList.put(file, emptyH); + } + } + } + } + } +} -- 2.30.2 From 07d92762326fb3cb85dc8d57a8daa968da659a36 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 20 Mar 2020 00:11:13 +0100 Subject: [PATCH 06/13] Changes in protocol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit À implémenter: Register + Unregister dans protocolP2P. Encore des erreurs: - [UDP] ICMP Port unreachable, c’est parce qu’on essaie de se connecter à un port qui est fermé. c’est pour ça qu’il faut donner le port dans register et dans unregister (sinon on a le mauvais HostItem). - [TCP] une autre erreur que je corrigerai demain --- doc/protocol.md | 10 ++++++++ src/clientP2P/ClientP2P.java | 6 +++-- src/protocolP2P/ProtocolP2PPacketUDP.java | 6 +++-- src/serverP2P/ServerManagementTCP.java | 27 +++++++++++++++++++++- src/serverP2P/ServerManagementUDP.java | 28 +++++++++++++++++++++-- src/serverP2P/ServerP2P.java | 14 +++++++----- src/tools/HostItem.java | 21 ++++++++++++++++- src/tracker/TrackerManagementTCP.java | 10 ++++---- src/tracker/TrackerManagementUDP.java | 8 +++---- 9 files changed, 107 insertions(+), 23 deletions(-) diff --git a/doc/protocol.md b/doc/protocol.md index a01a6c9..352078f 100644 --- a/doc/protocol.md +++ b/doc/protocol.md @@ -106,11 +106,21 @@ A algo hash bloc contains: #### Register Used by a server to register itself on a tracker. Server may want to do a free `DISCOVER` to check if they have been registered. +Payload contains: + +``` +2 bytes: [] +``` #### Unregister Used by a server to unregister itself from a tracker. No error is raised if the server was not registered. Server may want to do a free `DISCOVER` to check if they have been unregistered. +Payload contains: + +``` +2 bytes: [] +``` #### Discover request If payload size is null, lists all servers registered. diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index 34a9519..e08c1fb 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -30,6 +30,7 @@ public class ClientP2P { private Directories directories; private List hostList; private static final int defaultPort = 20000; + private HostItem tracker; /** Initialize loggers if directories and logger are null, @@ -47,6 +48,7 @@ public class ClientP2P { * @param portStr String containing port for server listenning. */ public ClientP2P(String portStr) { + tracker = new HostItem("localhost", 30000); // TODO : make it configurable try{ port = Integer.valueOf(Integer.parseInt(portStr)); } catch (NumberFormatException e){ @@ -84,8 +86,8 @@ public class ClientP2P { } // Server threads - ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer); - ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer); + ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer, c.tracker); + ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer, c.tracker); Thread tudp = new Thread(smudp); tudp.setName("server UDP P2P-JAVA-PROJECT (port: " + c.port + ")"); tudp.start(); diff --git a/src/protocolP2P/ProtocolP2PPacketUDP.java b/src/protocolP2P/ProtocolP2PPacketUDP.java index db92d2f..500fa57 100644 --- a/src/protocolP2P/ProtocolP2PPacketUDP.java +++ b/src/protocolP2P/ProtocolP2PPacketUDP.java @@ -34,6 +34,7 @@ import java.io.IOException; public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { private final static int CHECKSUM_POSITION = 2; + private HostItem remoteHost; private SocketAddress responseSocketAddress; // socket address used when receptionning request and to sending response private DatagramSocket responseSocket; // socket used to recept request and send response private DatagramSocket requestSocket; // socket used to send request and to reception response @@ -113,6 +114,7 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { DatagramPacket reception = new DatagramPacket(packet, packet.length); ss.receive(reception); responseSocketAddress = reception.getSocketAddress(); + remoteHost = new HostItem(reception.getAddress().getHostName(), reception.getPort()); // contruction boolean protocolError = false; try { @@ -371,9 +373,9 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { * @throws InternalError */ public HostItem getHostItem() throws InternalError { - if (responseSocket == null) { + if (remoteHost == null) { throw new InternalError(); } - return new HostItem(responseSocket.getInetAddress().getHostName(), responseSocket.getPort()); + return remoteHost; } } diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index 316143e..6001cdf 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -32,6 +32,7 @@ import remoteException.EmptyFile; import java.util.Arrays; import tools.Logger; import tools.LogLevel; +import tools.HostItem; import java.util.HashMap; import java.util.Map; import protocolP2P.HashAlgorithm; @@ -53,12 +54,14 @@ public class ServerManagementTCP implements Runnable { private int TCPPort; private ServerSocket socket; private Logger logger; + private HostItem tracker; /** Constructor for TCP implementation, with baseDirectory and TCPPort parameters. * @param baseDirectory the root directory where files are stored * @param TCPPort the server will listen on this port */ - public ServerManagementTCP(String baseDirectory, int TCPPort, Logger logger) { + public ServerManagementTCP(String baseDirectory, int TCPPort, Logger logger, HostItem tracker) { + this.tracker = tracker; this.logger = logger; this.baseDirectory = baseDirectory; this.TCPPort = TCPPort; @@ -79,6 +82,12 @@ public class ServerManagementTCP implements Runnable { */ public void run() { logger.writeTCP("Server sucessfully started", LogLevel.Info); + try { + registerTracker(); + } catch (Exception e) { + logger.writeTCP(e, LogLevel.Error); + System.exit(-4); + } do { try { Socket s = socket.accept(); @@ -332,4 +341,20 @@ public class ServerManagementTCP implements Runnable { } } + /** Register server on tracker + * @throws InternalError + * @throws IOException + * @throws SocketClosed + */ + public void registerTracker() throws InternalError, IOException, SocketClosed { + logger.writeTCP("Unregistering from tracker", LogLevel.Info); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.UNREGISTER)); + p.sendRequest((Object)tracker.getTCPSocket()); + logger.writeTCP("Registering into tracker", LogLevel.Info); + p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.REGISTER)); + p.sendRequest((Object)tracker.getTCPSocket()); + logger.writeTCP("Registering completed", LogLevel.Debug); + tracker.closeTCPSocket(); + } + } diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index 3289796..0de0ef7 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -36,6 +36,7 @@ import java.util.Map; import protocolP2P.HashAlgorithm; import protocolP2P.HashRequest; import protocolP2P.HashResponse; +import tools.HostItem; /** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol for UDP. * @author Louis Royer @@ -51,15 +52,17 @@ public class ServerManagementUDP implements Runnable { private int UDPPort; private DatagramSocket socket; private Logger logger; + private HostItem tracker; /** Constructor for UDP implementation, with baseDirectory and UDPPort parameters. * @param baseDirectory the root directory where files are stored * @param UDPPort the server will listen on this port */ - public ServerManagementUDP(String baseDirectory, int UDPPort, Logger logger) { + public ServerManagementUDP(String baseDirectory, int UDPPort, Logger logger, HostItem tracker) { this.logger = logger; this.baseDirectory = baseDirectory; this.UDPPort = UDPPort; + this.tracker = tracker; initFileList(); initSha512(); try { @@ -74,6 +77,12 @@ public class ServerManagementUDP implements Runnable { */ public void run() { logger.writeUDP("Server sucessfully started", LogLevel.Info); + try { + registerTracker(); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); + System.exit(-4); + } while(true) { try { ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP((Object)socket); @@ -268,5 +277,20 @@ public class ServerManagementUDP implements Runnable { } } } - + + /** Register server on tracker + * @throws InternalError + * @throws IOException + * @throws SocketClosed + */ + public void registerTracker() throws InternalError, IOException, SocketClosed { + logger.writeUDP("Unregistering from tracker", LogLevel.Info); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.UNREGISTER)); + p.sendRequest((Object)tracker.getUDPSocket()); + logger.writeUDP("Registering into tracker", LogLevel.Info); + p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.REGISTER)); + p.sendRequest((Object)tracker.getUDPSocket()); + tracker.closeUDPSocket(); + logger.writeUDP("Registering completed", LogLevel.Debug); + } } diff --git a/src/serverP2P/ServerP2P.java b/src/serverP2P/ServerP2P.java index be8bfec..abfdb66 100644 --- a/src/serverP2P/ServerP2P.java +++ b/src/serverP2P/ServerP2P.java @@ -3,6 +3,7 @@ import serverP2P.ServerManagementUDP; import serverP2P.ServerManagementTCP; import tools.Directories; import tools.Logger; +import tools.HostItem; /** Server only implementation * First argument of main method is port listened by the server, and is mandatory. @@ -16,12 +17,14 @@ public class ServerP2P { private Directories directories; static private final String subdir = "seeded/"; private Logger logger; + private HostItem tracker; /** Constructor with portStr containing a port number. * @param portStr String containing port number of listening. */ - public ServerP2P(String portStr) { + public ServerP2P(String portStr, String trackerHostname, String trackerPortStr) { port = Integer.valueOf(Integer.parseInt(portStr)); + tracker = new HostItem(trackerHostname, Integer.valueOf(Integer.parseInt(trackerPortStr))); directories = new Directories("P2P_JAVA_PROJECT_SERVER_" + port); directories.createSubdir(subdir); logger = new Logger(directories.getDataHomeDirectory() + "server.log"); @@ -31,18 +34,17 @@ public class ServerP2P { /** Main program entry point * first parameter is port number and is mandatory - * to test, run with: java -ea serverP2P.ServerP2P -- + * to test, run with: java -ea serverP2P.ServerP2P -- * @param args parameters */ public static void main(String [] args) { - if (args[1].equals("help") || args[1].equals("-h") || args[1].equals("h")){ System.out.println("usage : java -ea serveurP2P.ServeurP2P -- "); } else{ - ServerP2P s = new ServerP2P(args[1]); - ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, s.port, s.logger); - ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, s.port, s.logger); + ServerP2P s = new ServerP2P(args[1], args[2], args[3]); + ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, s.port, s.logger, s.tracker); + ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, s.port, s.logger, s.tracker); Thread tudp = new Thread(smudp); tudp.setName("server UDP P2P-JAVA-PROJECT"); tudp.start(); diff --git a/src/tools/HostItem.java b/src/tools/HostItem.java index f2bfbf3..fe15007 100644 --- a/src/tools/HostItem.java +++ b/src/tools/HostItem.java @@ -105,5 +105,24 @@ public class HostItem { public String toString() { return getHostname() + " (port " + getPort() + ")"; } - + + /** Override of equals method + * @param other Object to test equality with + * @return true if equals + */ + public boolean equals(Object other) { + boolean result = false; + if (other instanceof HostItem) { + HostItem that = (HostItem) other; + result = this.getHostname() == that.getHostname() && this.getPort() == that.getPort(); + } + return result; + } + + /** Override of hashCode method + * @return a hash code for this object. + */ + public int hashCode() { + return hostname.hashCode() ^ port; + } } diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index 91d7dab..e8795d9 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -101,7 +101,7 @@ public class TrackerManagementTCP implements Runnable { */ private boolean handleRequest() { try { - ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)socket); + ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)s); Payload p = pd.getPayload(); switch (p.getRequestResponseCode()) { case LOAD_REQUEST: @@ -125,9 +125,6 @@ public class TrackerManagementTCP implements Runnable { case DISCOVER_REQUEST: handleDiscover(pd); break; - case LIST_RESPONSE: - handleListResponse(pd); - break; default: logger.writeTCP("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); sendInternalError(pd); @@ -189,8 +186,11 @@ public class TrackerManagementTCP implements Runnable { } // send a list request try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.LIST_REQUEST))); + ProtocolP2PPacket pLReq = (ProtocolP2PPacket) new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.LIST_REQUEST)); + pLReq.sendRequest((Object)host.getTCPSocket()); logger.writeTCP("Received REGISTER. Adding host " + host + " to list. Sending List request", LogLevel.Action); + handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse()); + host.closeTCPSocket(); } catch (Exception e) { // remove from list because list request could not be send hostList.remove(host); diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index f1448f8..c11c54c 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -79,9 +79,6 @@ public class TrackerManagementUDP implements Runnable { case DISCOVER_REQUEST: handleDiscover(pd); break; - case LIST_RESPONSE: - handleListResponse(pd); - break; default: logger.writeUDP("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); sendInternalError(pd); @@ -141,8 +138,11 @@ public class TrackerManagementUDP implements Runnable { } // send a list request try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST))); + ProtocolP2PPacket pLReq =(ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST)); + pLReq.sendRequest((Object)host.getUDPSocket()); logger.writeUDP("Received REGISTER. Adding host " + host + " to list. Sending List request", LogLevel.Action); + handleListResponse((ProtocolP2PPacketUDP)pLReq.receiveResponse()); + host.closeUDPSocket(); } catch (Exception e) { // remove from list because list request could not be send hostList.remove(host); -- 2.30.2 From a2f505c167df9807c80490922c9c4bcd088342a6 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 20 Mar 2020 10:21:28 +0100 Subject: [PATCH 07/13] Add Register/Unregister --- doc/protocol.md | 3 +- src/protocolP2P/DiscoverRequest.java | 6 ++ src/protocolP2P/DiscoverResponse.java | 6 ++ src/protocolP2P/Payload.java | 8 +++ src/protocolP2P/ProtocolP2PPacketTCP.java | 12 ++++ src/protocolP2P/ProtocolP2PPacketUDP.java | 12 ++++ src/protocolP2P/Register.java | 77 +++++++++++++++++++++++ src/protocolP2P/Unregister.java | 77 +++++++++++++++++++++++ src/serverP2P/ServerManagementTCP.java | 51 +++++++++------ src/serverP2P/ServerManagementUDP.java | 51 +++++++++------ src/tracker/TrackerManagementTCP.java | 64 ++++++++++--------- src/tracker/TrackerManagementUDP.java | 65 ++++++++++--------- 12 files changed, 335 insertions(+), 97 deletions(-) create mode 100644 src/protocolP2P/Register.java create mode 100644 src/protocolP2P/Unregister.java diff --git a/doc/protocol.md b/doc/protocol.md index 352078f..64dae57 100644 --- a/doc/protocol.md +++ b/doc/protocol.md @@ -120,6 +120,7 @@ Payload contains: ``` 2 bytes: [] +? bytes: [] ``` #### Discover request @@ -128,7 +129,7 @@ If payload contains a filename, list all servers having this file in their list. ``` ? bytes: [] - +? bytes: [] ``` #### Discover response diff --git a/src/protocolP2P/DiscoverRequest.java b/src/protocolP2P/DiscoverRequest.java index b3a83aa..7ef1751 100644 --- a/src/protocolP2P/DiscoverRequest.java +++ b/src/protocolP2P/DiscoverRequest.java @@ -6,6 +6,12 @@ import localException.SizeError; import localException.ProtocolError; import localException.TransmissionError; +/** Representation of payload for discover request. + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ public class DiscoverRequest extends Payload { private String filename; diff --git a/src/protocolP2P/DiscoverResponse.java b/src/protocolP2P/DiscoverResponse.java index b887dea..4c73e36 100644 --- a/src/protocolP2P/DiscoverResponse.java +++ b/src/protocolP2P/DiscoverResponse.java @@ -9,6 +9,12 @@ import localException.ProtocolError; import localException.TransmissionError; import tools.BytesArrayTools; +/** Representation of payload for discover response. + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ public class DiscoverResponse extends Payload { private List hostList; diff --git a/src/protocolP2P/Payload.java b/src/protocolP2P/Payload.java index 8a84384..990df6b 100644 --- a/src/protocolP2P/Payload.java +++ b/src/protocolP2P/Payload.java @@ -7,6 +7,8 @@ import protocolP2P.HashRequest; import protocolP2P.HashResponse; import protocolP2P.DiscoverRequest; import protocolP2P.DiscoverResponse; +import protocolP2P.Register; +import protocolP2P.Unregister; import localException.ProtocolError; import localException.InternalError; import localException.TransmissionError; @@ -36,6 +38,8 @@ public class Payload { assert requestResponseCode != RequestResponseCode.HASH_RESPONSE || (this instanceof HashResponse) : "HASH_RESPONSE must use HashResponse class"; assert requestResponseCode != RequestResponseCode.DISCOVER_REQUEST || (this instanceof DiscoverRequest) : "DISCOVER_REQUEST must use DiscoverRequest class"; assert requestResponseCode != RequestResponseCode.DISCOVER_RESPONSE || (this instanceof DiscoverResponse) : "DISCOVER_RESPONSE must use DiscoverResponse class"; + assert requestResponseCode != RequestResponseCode.REGISTER || (this instanceof Register) : "REGISTER must use Register class"; + assert requestResponseCode != RequestResponseCode.UNREGISTER || (this instanceof Unregister) : "UNREGISTER must use Unregister class"; this.requestResponseCode = requestResponseCode; checkRequestResponseCode(); // this can throw InternalError } @@ -61,6 +65,8 @@ public class Payload { assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.HASH_RESPONSE || (this instanceof HashResponse) : "HASH_RESPONSE must use HashResponse class"; assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.DISCOVER_REQUEST || (this instanceof DiscoverRequest) : "DISCOVER_REQUEST must use DiscoverRequest class"; assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.DISCOVER_RESPONSE || (this instanceof DiscoverResponse) : "DISCOVER_RESPONSE must use DiscoverResponse class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.REGISTER || (this instanceof Register) : "REGISTER must use Register class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.UNREGISTER || (this instanceof Unregister) : "UNREGISTER must use Unregister class"; requestResponseCode = RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]); checkRequestResponseCode(); // this can throw InternalError } @@ -77,6 +83,8 @@ public class Payload { || (requestResponseCode == RequestResponseCode.HASH_RESPONSE && !(this instanceof HashResponse)) || (requestResponseCode == RequestResponseCode.DISCOVER_REQUEST && !(this instanceof DiscoverRequest)) || (requestResponseCode == RequestResponseCode.DISCOVER_RESPONSE && !(this instanceof DiscoverResponse)) + || (requestResponseCode == RequestResponseCode.REGISTER && !(this instanceof Register)) + || (requestResponseCode == RequestResponseCode.UNREGISTER && !(this instanceof Unregister)) ) { throw new InternalError(); } diff --git a/src/protocolP2P/ProtocolP2PPacketTCP.java b/src/protocolP2P/ProtocolP2PPacketTCP.java index ddde5f3..f2254f8 100644 --- a/src/protocolP2P/ProtocolP2PPacketTCP.java +++ b/src/protocolP2P/ProtocolP2PPacketTCP.java @@ -289,6 +289,18 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { case HASH_RESPONSE: payload = (Payload) new HashResponse(packet); break; + case REGISTER: + payload = (Payload) new Register(packet); + break; + case UNREGISTER: + payload = (Payload) new Unregister(packet); + break; + case DISCOVER_REQUEST: + payload = (Payload) new DiscoverRequest(packet); + break; + case DISCOVER_RESPONSE: + payload = (Payload) new DiscoverResponse(packet); + break; default: payload = new Payload(packet); // this can throw TransmissionError break; diff --git a/src/protocolP2P/ProtocolP2PPacketUDP.java b/src/protocolP2P/ProtocolP2PPacketUDP.java index 500fa57..4bc98bb 100644 --- a/src/protocolP2P/ProtocolP2PPacketUDP.java +++ b/src/protocolP2P/ProtocolP2PPacketUDP.java @@ -287,6 +287,18 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { case HASH_RESPONSE: payload = (Payload) new HashResponse(packet); break; + case REGISTER: + payload = (Payload) new Register(packet); + break; + case UNREGISTER: + payload = (Payload) new Unregister(packet); + break; + case DISCOVER_REQUEST: + payload = (Payload) new DiscoverRequest(packet); + break; + case DISCOVER_RESPONSE: + payload = (Payload) new DiscoverResponse(packet); + break; default: payload = new Payload(packet); // this can throw TransmissionError break; diff --git a/src/protocolP2P/Register.java b/src/protocolP2P/Register.java new file mode 100644 index 0000000..790ac2b --- /dev/null +++ b/src/protocolP2P/Register.java @@ -0,0 +1,77 @@ +package protocolP2P; +import protocolP2P.Payload; +import tools.HostItem; +import tools.BytesArrayTools; +import localException.SizeError; +import localException.InternalError; +import localException.TransmissionError; +import localException.ProtocolError; + +/** Representation of payload for unregister. + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class Register extends Payload { + private HostItem hostItem; + private static final int HOSTNAME_START_POSITION = PAYLOAD_START_POSITION + 2; + + /** Constructor with hostItem (typically used by client) + * @param hostItem Host you want to register. + * @throws InternalError + */ + public Register(HostItem hostItem) throws InternalError { + super(RequestResponseCode.REGISTER); + this.hostItem = hostItem; + } + + /** Constructor (typically used by server) with a byte[] parameter containing the Packet received. + * @param packet the full Packet received + * @throws SizeError + * @throws InternalError + * @throws ProtocolError + * @throws TransmissionError + */ + protected Register(byte[] packet) throws SizeError, ProtocolError, InternalError, TransmissionError { + super(packet); + int size = getPayloadSize(packet); + int port = BytesArrayTools.readInt16Bits(packet, PAYLOAD_START_POSITION); + String hostname = BytesArrayTools.readString(packet, HOSTNAME_START_POSITION, size - HOSTNAME_START_POSITION + PAYLOAD_START_POSITION); + hostItem = new HostItem(hostname, port); + } + + /** Returns a byte[] containing Packet with padding. + * This Packet is still incomplete and should not be send directly. + * ProtocolP2PPacket will use this method to generate the complete Packet. + * @return Packet with padding + * @throws InternalError + */ + protected byte[] toPacket() throws InternalError { + String hostname = hostItem.getHostname(); + // compute total size + int size = HOSTNAME_START_POSITION + hostname.length(); + byte[] packet = new byte[size + 1]; // java initialize all to zero + // set request/response code + packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue; + // set Payload size + setPayloadSize(size - PAYLOAD_START_POSITION, packet); + // write port to Packet + try { + BytesArrayTools.write16Bits(packet, PAYLOAD_START_POSITION, hostItem.getPort()); + } catch (SizeError e) { + throw new InternalError(); + } + // write hostname to Packet + BytesArrayTools.write(packet, hostname, HOSTNAME_START_POSITION); + return packet; + } + + /** HostItem getter. + * @return hostItem + */ + public HostItem getHostItem() { + return hostItem; + } + +} diff --git a/src/protocolP2P/Unregister.java b/src/protocolP2P/Unregister.java new file mode 100644 index 0000000..8307a5b --- /dev/null +++ b/src/protocolP2P/Unregister.java @@ -0,0 +1,77 @@ +package protocolP2P; +import protocolP2P.Payload; +import tools.HostItem; +import tools.BytesArrayTools; +import localException.SizeError; +import localException.InternalError; +import localException.TransmissionError; +import localException.ProtocolError; + +/** Representation of payload for unregister. + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class Unregister extends Payload { + private HostItem hostItem; + private static final int HOSTNAME_START_POSITION = PAYLOAD_START_POSITION + 2; + + /** Constructor with hostItem (typically used by client) + * @param hostItem Host you want to register. + * @throws InternalError + */ + public Unregister(HostItem hostItem) throws InternalError { + super(RequestResponseCode.UNREGISTER); + this.hostItem = hostItem; + } + + /** Constructor (typically used by server) with a byte[] parameter containing the Packet received. + * @param packet the full Packet received + * @throws SizeError + * @throws InternalError + * @throws ProtocolError + * @throws TransmissionError + */ + protected Unregister(byte[] packet) throws SizeError, ProtocolError, InternalError, TransmissionError { + super(packet); + int size = getPayloadSize(packet); + int port = BytesArrayTools.readInt16Bits(packet, PAYLOAD_START_POSITION); + String hostname = BytesArrayTools.readString(packet, HOSTNAME_START_POSITION, size - HOSTNAME_START_POSITION + PAYLOAD_START_POSITION); + hostItem = new HostItem(hostname, port); + } + + /** Returns a byte[] containing Packet with padding. + * This Packet is still incomplete and should not be send directly. + * ProtocolP2PPacket will use this method to generate the complete Packet. + * @return Packet with padding + * @throws InternalError + */ + protected byte[] toPacket() throws InternalError { + String hostname = hostItem.getHostname(); + // compute total size + int size = HOSTNAME_START_POSITION + hostname.length(); + byte[] packet = new byte[size + 1]; // java initialize all to zero + // set request/response code + packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue; + // set Payload size + setPayloadSize(size - PAYLOAD_START_POSITION, packet); + // write port to Packet + try { + BytesArrayTools.write16Bits(packet, PAYLOAD_START_POSITION, hostItem.getPort()); + } catch (SizeError e) { + throw new InternalError(); + } + // write hostname to Packet + BytesArrayTools.write(packet, hostname, HOSTNAME_START_POSITION); + return packet; + } + + /** HostItem getter. + * @return hostItem + */ + public HostItem getHostItem() { + return hostItem; + } + +} diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index 6001cdf..a136574 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -38,6 +38,8 @@ import java.util.Map; import protocolP2P.HashAlgorithm; import protocolP2P.HashRequest; import protocolP2P.HashResponse; +import protocolP2P.Register; +import protocolP2P.Unregister; /** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol for TCP. @@ -82,12 +84,7 @@ public class ServerManagementTCP implements Runnable { */ public void run() { logger.writeTCP("Server sucessfully started", LogLevel.Info); - try { - registerTracker(); - } catch (Exception e) { - logger.writeTCP(e, LogLevel.Error); - System.exit(-4); - } + (new Thread(new TrackerRegisterer())).start(); do { try { Socket s = socket.accept(); @@ -341,20 +338,34 @@ public class ServerManagementTCP implements Runnable { } } - /** Register server on tracker - * @throws InternalError - * @throws IOException - * @throws SocketClosed - */ - public void registerTracker() throws InternalError, IOException, SocketClosed { - logger.writeTCP("Unregistering from tracker", LogLevel.Info); - ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.UNREGISTER)); - p.sendRequest((Object)tracker.getTCPSocket()); - logger.writeTCP("Registering into tracker", LogLevel.Info); - p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.REGISTER)); - p.sendRequest((Object)tracker.getTCPSocket()); - logger.writeTCP("Registering completed", LogLevel.Debug); - tracker.closeTCPSocket(); + /** Private runnable class allowing to initialize tracker while initializing server. */ + private class TrackerRegisterer implements Runnable { + + /** Runnable implementation */ + public void run() { + try { + registerTracker(); + } catch (Exception e) { + logger.writeTCP(e, LogLevel.Error); + System.exit(-4); + } + } + /** Register server on tracker + * @throws InternalError + * @throws IOException + * @throws SocketClosed + */ + private void registerTracker() throws InternalError, IOException, SocketClosed { + HostItem host = new HostItem(InetAddress.getLocalHost().getCanonicalHostName(), TCPPort); + logger.writeTCP("Unregistering from tracker", LogLevel.Info); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Unregister(host)); + p.sendRequest((Object)tracker.getTCPSocket()); + logger.writeTCP("Registering into tracker", LogLevel.Info); + p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(host)); + p.sendRequest((Object)tracker.getTCPSocket()); + logger.writeTCP("Registering completed", LogLevel.Debug); + tracker.closeTCPSocket(); + } } } diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index 0de0ef7..c082825 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -37,6 +37,8 @@ import protocolP2P.HashAlgorithm; import protocolP2P.HashRequest; import protocolP2P.HashResponse; import tools.HostItem; +import protocolP2P.Register; +import protocolP2P.Unregister; /** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol for UDP. * @author Louis Royer @@ -77,12 +79,7 @@ public class ServerManagementUDP implements Runnable { */ public void run() { logger.writeUDP("Server sucessfully started", LogLevel.Info); - try { - registerTracker(); - } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - System.exit(-4); - } + (new Thread(new TrackerRegisterer())).start(); while(true) { try { ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP((Object)socket); @@ -278,19 +275,33 @@ public class ServerManagementUDP implements Runnable { } } - /** Register server on tracker - * @throws InternalError - * @throws IOException - * @throws SocketClosed - */ - public void registerTracker() throws InternalError, IOException, SocketClosed { - logger.writeUDP("Unregistering from tracker", LogLevel.Info); - ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.UNREGISTER)); - p.sendRequest((Object)tracker.getUDPSocket()); - logger.writeUDP("Registering into tracker", LogLevel.Info); - p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.REGISTER)); - p.sendRequest((Object)tracker.getUDPSocket()); - tracker.closeUDPSocket(); - logger.writeUDP("Registering completed", LogLevel.Debug); +/** Private runnable class allowing to initialize tracker while initializing server. */ + private class TrackerRegisterer implements Runnable { + + /** Runnable implementation */ + public void run() { + try { + registerTracker(); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); + System.exit(-4); + } + } + /** Register server on tracker + * @throws InternalError + * @throws IOException + * @throws SocketClosed + */ + private void registerTracker() throws InternalError, IOException, SocketClosed { + HostItem host = new HostItem(InetAddress.getLocalHost().getCanonicalHostName(), UDPPort); + logger.writeUDP("Unregistering from tracker", LogLevel.Info); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Unregister(host)); + p.sendRequest((Object)tracker.getUDPSocket()); + logger.writeUDP("Registering into tracker", LogLevel.Info); + p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Register(host)); + p.sendRequest((Object)tracker.getUDPSocket()); + logger.writeUDP("Registering completed", LogLevel.Debug); + tracker.closeUDPSocket(); + } } } diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index e8795d9..33f8ad2 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -8,6 +8,8 @@ import protocolP2P.ProtocolP2PPacketTCP; import protocolP2P.ProtocolP2PPacket; import protocolP2P.RequestResponseCode; import protocolP2P.Payload; +import protocolP2P.Register; +import protocolP2P.Unregister; import tools.HostItem; import java.util.ArrayList; import java.util.List; @@ -179,8 +181,13 @@ public class TrackerManagementTCP implements Runnable { * @throws InternalError */ private void handleRegister(ProtocolP2PPacketTCP pd) throws InternalError { + Payload p = pd.getPayload(); + assert p instanceof Register : "payload must be an instance of Register"; + if (!(p instanceof Register)) { + throw new InternalError(); + } // add host to known host list - HostItem host = pd.getHostItem(); + HostItem host = ((Register)p).getHostItem(); if (!hostList.contains(host)) { hostList.add(pd.getHostItem()); } @@ -188,8 +195,8 @@ public class TrackerManagementTCP implements Runnable { try { ProtocolP2PPacket pLReq = (ProtocolP2PPacket) new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.LIST_REQUEST)); pLReq.sendRequest((Object)host.getTCPSocket()); - logger.writeTCP("Received REGISTER. Adding host " + host + " to list. Sending List request", LogLevel.Action); - handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse()); + logger.writeTCP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); + handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse(), host); host.closeTCPSocket(); } catch (Exception e) { // remove from list because list request could not be send @@ -204,8 +211,14 @@ public class TrackerManagementTCP implements Runnable { * @throws InternalError */ private void handleUnregister(ProtocolP2PPacketTCP pd) throws InternalError { - HostItem host = pd.getHostItem(); - logger.writeTCP("Received UNREGISTER. Removing host " + host, LogLevel.Action); + Payload p = pd.getPayload(); + assert p instanceof Unregister : "payload must be an instance of Unregister"; + if (!(p instanceof Unregister)) { + sendInternalError(pd); + throw new InternalError(); + } + HostItem host = ((Unregister)p).getHostItem(); + logger.writeTCP("Received UNREGISTER from host " + pd.getHostItem() + ". Removing host " + host, LogLevel.Action); hostList.remove(host); for(String f: fileList.keySet()) { fileList.get(f).remove(host); @@ -239,30 +252,25 @@ public class TrackerManagementTCP implements Runnable { * @param pd ProtocolP2PPacketTCP response * @throws InternalError */ - private void handleListResponse(ProtocolP2PPacketTCP pd) throws InternalError { - HostItem host = pd.getHostItem(); - if (!hostList.contains(host)) { - logger.writeTCP("Received LIST RESPONSE from host " + host + " but it is not registered.", LogLevel.Action); + private void handleListResponse(ProtocolP2PPacketTCP pd, HostItem host) throws InternalError { + logger.writeTCP("Received LIST RESPONSE from host " + host + ": registered host.", LogLevel.Action); + Payload p = pd.getPayload(); + assert p instanceof FileList: "payload must be an instance of FileList"; + if (!(p instanceof FileList)) { + throw new InternalError(); } else { - logger.writeTCP("Received LIST RESPONSE from host " + host + ": registered host.", LogLevel.Action); - Payload p = pd.getPayload(); - assert p instanceof FileList: "payload must be an instance of FileList"; - if (!(p instanceof FileList)) { - sendInternalError(pd); - } else { - String[] f = ((FileList)p).getFileList(); - for (String file: f) { - List h = fileList.get(file); - if (h != null) { - if (!h.contains(host)) { - h.add(host); - } - } else { - List emptyH = new ArrayList<>(); - emptyH.add(host); - fileList.put(file, emptyH); - } - } + String[] f = ((FileList)p).getFileList(); + for (String file: f) { + List h = fileList.get(file); + if (h != null) { + if (!h.contains(host)) { + h.add(host); + } + } else { + List emptyH = new ArrayList<>(); + emptyH.add(host); + fileList.put(file, emptyH); + } } } } diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index c11c54c..3a93fe6 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -6,6 +6,8 @@ import protocolP2P.ProtocolP2PPacketUDP; import protocolP2P.ProtocolP2PPacket; import protocolP2P.RequestResponseCode; import protocolP2P.Payload; +import protocolP2P.Register; +import protocolP2P.Unregister; import tools.HostItem; import java.util.ArrayList; import java.util.List; @@ -131,8 +133,14 @@ public class TrackerManagementUDP implements Runnable { * @throws InternalError */ private void handleRegister(ProtocolP2PPacketUDP pd) throws InternalError { + Payload p = pd.getPayload(); + assert p instanceof Register : "payload must be an instance of Register"; + if (!(p instanceof Register)) { + sendInternalError(pd); + throw new InternalError(); + } // add host to known host list - HostItem host = pd.getHostItem(); + HostItem host = ((Register)p).getHostItem(); if (!hostList.contains(host)) { hostList.add(pd.getHostItem()); } @@ -140,8 +148,8 @@ public class TrackerManagementUDP implements Runnable { try { ProtocolP2PPacket pLReq =(ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST)); pLReq.sendRequest((Object)host.getUDPSocket()); - logger.writeUDP("Received REGISTER. Adding host " + host + " to list. Sending List request", LogLevel.Action); - handleListResponse((ProtocolP2PPacketUDP)pLReq.receiveResponse()); + logger.writeUDP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); + handleListResponse((ProtocolP2PPacketUDP)pLReq.receiveResponse(), host); host.closeUDPSocket(); } catch (Exception e) { // remove from list because list request could not be send @@ -156,8 +164,14 @@ public class TrackerManagementUDP implements Runnable { * @throws InternalError */ private void handleUnregister(ProtocolP2PPacketUDP pd) throws InternalError { - HostItem host = pd.getHostItem(); - logger.writeUDP("Received UNREGISTER. Removing host " + host, LogLevel.Action); + Payload p = pd.getPayload(); + assert p instanceof Unregister : "payload must be an instance of Unregister"; + if (!(p instanceof Unregister)) { + sendInternalError(pd); + throw new InternalError(); + } + HostItem host = ((Unregister)p).getHostItem(); + logger.writeUDP("Received UNREGISTER from host " + pd.getHostItem() + ". Removing host " + host, LogLevel.Action); hostList.remove(host); for(String f: fileList.keySet()) { fileList.get(f).remove(host); @@ -191,30 +205,25 @@ public class TrackerManagementUDP implements Runnable { * @param pd ProtocolP2PPacketUDP response * @throws InternalError */ - private void handleListResponse(ProtocolP2PPacketUDP pd) throws InternalError { - HostItem host = pd.getHostItem(); - if (!hostList.contains(host)) { - logger.writeUDP("Received LIST RESPONSE from host " + host + " but it is not registered.", LogLevel.Action); + private void handleListResponse(ProtocolP2PPacketUDP pd, HostItem host) throws InternalError { + logger.writeUDP("Received LIST RESPONSE from host " + host, LogLevel.Action); + Payload p = pd.getPayload(); + assert p instanceof FileList: "payload must be an instance of FileList"; + if (!(p instanceof FileList)) { + throw new InternalError(); } else { - logger.writeUDP("Received LIST RESPONSE from host " + host + ": registered host.", LogLevel.Action); - Payload p = pd.getPayload(); - assert p instanceof FileList: "payload must be an instance of FileList"; - if (!(p instanceof FileList)) { - sendInternalError(pd); - } else { - String[] f = ((FileList)p).getFileList(); - for (String file: f) { - List h = fileList.get(file); - if (h != null) { - if (!h.contains(host)) { - h.add(host); - } - } else { - List emptyH = new ArrayList<>(); - emptyH.add(host); - fileList.put(file, emptyH); - } - } + String[] f = ((FileList)p).getFileList(); + for (String file: f) { + List h = fileList.get(file); + if (h != null) { + if (!h.contains(host)) { + h.add(host); + } + } else { + List emptyH = new ArrayList<>(); + emptyH.add(host); + fileList.put(file, emptyH); + } } } } -- 2.30.2 From 9b6258afd382c1ad17a2cb3f351ad4c03b939b38 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 20 Mar 2020 11:27:57 +0100 Subject: [PATCH 08/13] Fix warnings / close scanners --- src/clientP2P/ClientDownloadPartTCP.java | 6 +++++- src/clientP2P/ClientDownloadPartUDP.java | 6 +++++- src/clientP2P/ClientDownloadTCP.java | 8 +++++++- src/clientP2P/ClientDownloadUDP.java | 8 +++++++- src/clientP2P/ClientManagementTCP.java | 11 +++++------ src/clientP2P/ClientManagementUDP.java | 12 +++++------- src/clientP2P/ClientP2P.java | 11 +++++------ src/localException/InternalError.java | 2 +- src/localException/ProtocolError.java | 2 +- src/localException/SizeError.java | 2 +- src/localException/SocketClosed.java | 2 +- src/localException/TransmissionError.java | 2 +- src/localException/VersionError.java | 2 +- src/protocolP2P/FileList.java | 2 -- src/protocolP2P/FilePart.java | 2 -- src/protocolP2P/HashRequest.java | 1 - src/protocolP2P/HashResponse.java | 1 - src/protocolP2P/LoadRequest.java | 1 - src/protocolP2P/ProtocolP2PPacket.java | 6 ++++-- src/protocolP2P/ProtocolP2PPacketTCP.java | 14 ++++++++------ src/protocolP2P/ProtocolP2PPacketUDP.java | 11 ++++++++--- src/remoteException/EmptyDirectory.java | 2 +- src/remoteException/EmptyFile.java | 2 +- src/remoteException/InternalRemoteError.java | 2 +- src/remoteException/NotATracker.java | 2 +- src/remoteException/NotFound.java | 2 +- src/remoteException/ProtocolRemoteError.java | 2 +- src/remoteException/VersionRemoteError.java | 2 +- src/serverP2P/ServerManagementTCP.java | 9 ++------- src/serverP2P/ServerManagementUDP.java | 18 ++++++------------ src/tools/Directories.java | 1 + src/tools/HostList.java | 1 + src/tracker/TrackerManagementTCP.java | 6 +++--- src/tracker/TrackerManagementUDP.java | 13 ++++++++++--- 34 files changed, 95 insertions(+), 79 deletions(-) diff --git a/src/clientP2P/ClientDownloadPartTCP.java b/src/clientP2P/ClientDownloadPartTCP.java index e6635cd..e4db082 100644 --- a/src/clientP2P/ClientDownloadPartTCP.java +++ b/src/clientP2P/ClientDownloadPartTCP.java @@ -5,7 +5,6 @@ import java.net.Socket; import java.io.File; import java.io.IOException; import java.nio.file.Files; -import java.nio.file.Paths; import protocolP2P.ProtocolP2PPacketTCP; import protocolP2P.Payload; import protocolP2P.LoadRequest; @@ -22,6 +21,7 @@ import remoteException.InternalRemoteError; import remoteException.VersionRemoteError; import remoteException.ProtocolRemoteError; import remoteException.NotFound; +import remoteException.NotATracker; import tools.Logger; import tools.LogLevel; @@ -351,6 +351,10 @@ public class ClientDownloadPartTCP implements Runnable { System.err.println("Error: downloadPart SocketClosed"); logger.writeTCP("downloadPart SocketClosed", LogLevel.Error); return true; + } catch (NotATracker e) { + System.err.println("Error: downloadPart notATracker"); + logger.writeTCP("downloadPart notATracker", LogLevel.Error); + return true; } return false; } diff --git a/src/clientP2P/ClientDownloadPartUDP.java b/src/clientP2P/ClientDownloadPartUDP.java index b818553..84ef0f8 100644 --- a/src/clientP2P/ClientDownloadPartUDP.java +++ b/src/clientP2P/ClientDownloadPartUDP.java @@ -17,9 +17,9 @@ import remoteException.ProtocolRemoteError; import localException.VersionError; import localException.SizeError; import remoteException.NotFound; +import remoteException.NotATracker; import java.nio.file.Files; import java.io.File; -import java.nio.file.Paths; import java.io.IOException; import tools.Logger; import tools.LogLevel; @@ -336,6 +336,10 @@ public class ClientDownloadPartUDP implements Runnable { System.err.println("Error: downloadPart internalError"); logger.writeUDP("downloadPart internalError", LogLevel.Error); return true; + } catch (NotATracker e) { + System.err.println("Error: downloadPart notATracker"); + logger.writeUDP("downloadPart notATracker", LogLevel.Error); + return true; } return false; } diff --git a/src/clientP2P/ClientDownloadTCP.java b/src/clientP2P/ClientDownloadTCP.java index 92bbc43..bb8e932 100644 --- a/src/clientP2P/ClientDownloadTCP.java +++ b/src/clientP2P/ClientDownloadTCP.java @@ -7,7 +7,6 @@ import java.util.Random; import java.io.IOException; import java.io.File; import java.nio.file.Files; -import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.nio.file.StandardCopyOption; import remoteException.EmptyDirectory; @@ -16,6 +15,7 @@ import remoteException.VersionRemoteError; import remoteException.ProtocolRemoteError; import remoteException.NotFound; import remoteException.InternalRemoteError; +import remoteException.NotATracker; import localException.ProtocolError; import localException.InternalError; import localException.TransmissionError; @@ -239,6 +239,9 @@ public class ClientDownloadTCP implements Runnable { } catch (SizeError e) { logger.writeTCP(e, LogLevel.Error); throw new InternalError(); + } catch (NotATracker e) { + logger.writeTCP(e, LogLevel.Error); + throw new InternalError(); } return hash; } catch (IOException e) { @@ -382,6 +385,9 @@ public class ClientDownloadTCP implements Runnable { } catch (NotFound e) { logger.writeTCP(e, LogLevel.Error); throw new InternalError(); + } catch (NotATracker e) { + logger.writeTCP(e, LogLevel.Error); + throw new InternalError(); } } catch (IOException e) { logger.writeTCP(e, LogLevel.Error); diff --git a/src/clientP2P/ClientDownloadUDP.java b/src/clientP2P/ClientDownloadUDP.java index 87d6bab..932019b 100644 --- a/src/clientP2P/ClientDownloadUDP.java +++ b/src/clientP2P/ClientDownloadUDP.java @@ -7,7 +7,6 @@ import java.util.Random; import java.io.IOException; import java.io.File; import java.nio.file.Files; -import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.nio.file.StandardCopyOption; import localException.ProtocolError; @@ -21,6 +20,7 @@ import remoteException.VersionRemoteError; import remoteException.ProtocolRemoteError; import remoteException.NotFound; import remoteException.InternalRemoteError; +import remoteException.NotATracker; import protocolP2P.HashAlgorithm; import protocolP2P.HashResponse; import protocolP2P.HashRequest; @@ -239,6 +239,9 @@ public class ClientDownloadUDP implements Runnable { } catch (SizeError e) { logger.writeUDP(e, LogLevel.Error); throw new InternalError(); + } catch (NotATracker e) { + logger.writeUDP(e, LogLevel.Error); + throw new InternalError(); } return hash; } catch (IOException e) { @@ -378,6 +381,9 @@ public class ClientDownloadUDP implements Runnable { } catch (NotFound e) { logger.writeUDP(e, LogLevel.Error); throw new InternalError(); + } catch (NotATracker e) { + logger.writeUDP(e, LogLevel.Error); + throw new InternalError(); } } catch (IOException e) { logger.writeUDP(e, LogLevel.Error); diff --git a/src/clientP2P/ClientManagementTCP.java b/src/clientP2P/ClientManagementTCP.java index f479df0..28fe131 100644 --- a/src/clientP2P/ClientManagementTCP.java +++ b/src/clientP2P/ClientManagementTCP.java @@ -4,9 +4,7 @@ import java.net.UnknownHostException; import java.util.Scanner; import java.io.IOException; import java.nio.file.Files; -import java.io.File; import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; import java.util.Arrays; import java.util.List; import java.security.MessageDigest; @@ -23,15 +21,12 @@ import remoteException.InternalRemoteError; import remoteException.NotFound; import remoteException.ProtocolRemoteError; import remoteException.VersionRemoteError; +import remoteException.NotATracker; import protocolP2P.ProtocolP2PPacketTCP; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; import protocolP2P.FileList; -import protocolP2P.FilePart; -import protocolP2P.LoadRequest; import protocolP2P.HashAlgorithm; -import protocolP2P.HashRequest; -import protocolP2P.HashResponse; import clientP2P.ClientDownloadTCP; import tools.HostItem; import tools.Logger; @@ -74,6 +69,7 @@ public class ClientManagementTCP implements Runnable { } System.out.println("Name of the file to download:"); String f = scanner.nextLine(); + scanner.close(); download(f); System.out.println("File " + f + " sucessfully downloaded"); logger.writeTCP("File " + f + " sucessfully downloaded", LogLevel.Info); @@ -203,6 +199,9 @@ public class ClientManagementTCP implements Runnable { System.err.println("listDirectory : SocketClosed"); logger.writeTCP("listDirectory : SocketClosed", LogLevel.Error); throw new ProtocolError(); + } catch (NotATracker e) { + logger.writeTCP(e, LogLevel.Error); + throw new ProtocolError(); } } diff --git a/src/clientP2P/ClientManagementUDP.java b/src/clientP2P/ClientManagementUDP.java index 914dc44..aa1da60 100644 --- a/src/clientP2P/ClientManagementUDP.java +++ b/src/clientP2P/ClientManagementUDP.java @@ -4,12 +4,9 @@ import java.util.Scanner; import java.util.Arrays; import java.util.List; import java.io.IOException; -import java.io.File; -import java.net.DatagramSocket; import java.net.UnknownHostException; import java.nio.file.Files; import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import localException.InternalError; @@ -23,15 +20,12 @@ import remoteException.InternalRemoteError; import remoteException.NotFound; import remoteException.ProtocolRemoteError; import remoteException.VersionRemoteError; +import remoteException.NotATracker; import protocolP2P.ProtocolP2PPacketUDP; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; import protocolP2P.FileList; -import protocolP2P.FilePart; -import protocolP2P.LoadRequest; import protocolP2P.HashAlgorithm; -import protocolP2P.HashRequest; -import protocolP2P.HashResponse; import tools.HostItem; import tools.Logger; import tools.LogLevel; @@ -74,6 +68,7 @@ public class ClientManagementUDP implements Runnable { } System.out.println("Name of the file to download:"); String f = scanner.nextLine(); + scanner.close(); download(f); System.out.println("File " + f + " sucessfully downloaded"); logger.writeUDP("File " + f + " sucessfully downloaded", LogLevel.Info); @@ -199,6 +194,9 @@ public class ClientManagementUDP implements Runnable { } catch (EmptyFile e) { logger.writeUDP(e, LogLevel.Error); throw new ProtocolError(); + } catch (NotATracker e) { + logger.writeUDP(e, LogLevel.Error); + throw new ProtocolError(); } } diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index e08c1fb..139701f 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -6,7 +6,6 @@ import clientP2P.ClientManagementUDP; import clientP2P.ClientManagementTCP; import serverP2P.ServerManagementUDP; import serverP2P.ServerManagementTCP; -import tools.Directories; import tools.Logger; import tools.LogLevel; import tools.Directories; @@ -21,8 +20,8 @@ import tools.HostList; */ public class ClientP2P { - static private final String subdir = "seeded/"; - static private String parts = ".parts"; + private String subdir = "seeded/"; + private String parts = ".parts"; private Logger loggerServer; private Logger loggerClient; private String host; @@ -86,8 +85,8 @@ public class ClientP2P { } // Server threads - ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer, c.tracker); - ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer, c.tracker); + ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + c.subdir, c.port, c.loggerServer, c.tracker); + ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + c.subdir, c.port, c.loggerServer, c.tracker); Thread tudp = new Thread(smudp); tudp.setName("server UDP P2P-JAVA-PROJECT (port: " + c.port + ")"); tudp.start(); @@ -108,6 +107,7 @@ public class ClientP2P { System.out.println("Client : Which transport protocol do you want to use? [TCP/udp]"); Scanner sc = new Scanner(System.in); String transportchoosen = sc.nextLine(); + sc.close(); Thread t; switch(transportchoosen){ case "UDP": @@ -127,7 +127,6 @@ public class ClientP2P { t = new Thread(cmtcp); break; } - t.setName("client P2P-JAVA-PROJECT"); t.start(); } diff --git a/src/localException/InternalError.java b/src/localException/InternalError.java index 08326f9..42794a5 100644 --- a/src/localException/InternalError.java +++ b/src/localException/InternalError.java @@ -2,6 +2,6 @@ package localException; import exception.LocalException; -public class InternalError extends exception.LocalException { +public class InternalError extends LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/ProtocolError.java b/src/localException/ProtocolError.java index 8a8be52..14aeca8 100644 --- a/src/localException/ProtocolError.java +++ b/src/localException/ProtocolError.java @@ -2,6 +2,6 @@ package localException; import exception.LocalException; -public class ProtocolError extends exception.LocalException { +public class ProtocolError extends LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/SizeError.java b/src/localException/SizeError.java index cb927bc..bb13830 100644 --- a/src/localException/SizeError.java +++ b/src/localException/SizeError.java @@ -4,6 +4,6 @@ import exception.LocalException; /** Used on reception side when size as set in Packet is too big, and we cant store this in a int/long as usual. */ -public class SizeError extends exception.LocalException { +public class SizeError extends LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/SocketClosed.java b/src/localException/SocketClosed.java index ceaac40..d3e68c5 100644 --- a/src/localException/SocketClosed.java +++ b/src/localException/SocketClosed.java @@ -2,6 +2,6 @@ package localException; import exception.LocalException; -public class SocketClosed extends exception.LocalException { +public class SocketClosed extends LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/TransmissionError.java b/src/localException/TransmissionError.java index 38fca4f..d5a539b 100644 --- a/src/localException/TransmissionError.java +++ b/src/localException/TransmissionError.java @@ -2,6 +2,6 @@ package localException; import exception.LocalException; -public class TransmissionError extends exception.LocalException { +public class TransmissionError extends LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/VersionError.java b/src/localException/VersionError.java index c0cb7d4..a793e27 100644 --- a/src/localException/VersionError.java +++ b/src/localException/VersionError.java @@ -2,6 +2,6 @@ package localException; import exception.LocalException; -public class VersionError extends exception.LocalException { +public class VersionError extends LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/protocolP2P/FileList.java b/src/protocolP2P/FileList.java index da31f08..b013bea 100644 --- a/src/protocolP2P/FileList.java +++ b/src/protocolP2P/FileList.java @@ -1,12 +1,10 @@ package protocolP2P; -import java.util.Arrays; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; import localException.TransmissionError; import localException.ProtocolError; import localException.InternalError; import localException.SizeError; -import java.io.UnsupportedEncodingException; import tools.BytesArrayTools; /** Representation of payload for list response. diff --git a/src/protocolP2P/FilePart.java b/src/protocolP2P/FilePart.java index c394b0f..d168a05 100644 --- a/src/protocolP2P/FilePart.java +++ b/src/protocolP2P/FilePart.java @@ -6,8 +6,6 @@ import localException.InternalError; import localException.SizeError; import localException.TransmissionError; import tools.BytesArrayTools; -import java.util.Arrays; -import java.io.UnsupportedEncodingException; /** Representation of payload for load response. * @author Louis Royer diff --git a/src/protocolP2P/HashRequest.java b/src/protocolP2P/HashRequest.java index 452fd32..1eec671 100644 --- a/src/protocolP2P/HashRequest.java +++ b/src/protocolP2P/HashRequest.java @@ -1,7 +1,6 @@ package protocolP2P; import protocolP2P.Payload; import protocolP2P.HashAlgorithm; -import java.io.UnsupportedEncodingException; import localException.TransmissionError; import localException.SizeError; import localException.ProtocolError; diff --git a/src/protocolP2P/HashResponse.java b/src/protocolP2P/HashResponse.java index 769fbd7..52df91e 100644 --- a/src/protocolP2P/HashResponse.java +++ b/src/protocolP2P/HashResponse.java @@ -2,7 +2,6 @@ package protocolP2P; import protocolP2P.Payload; import java.util.HashMap; import java.util.Map; -import java.io.UnsupportedEncodingException; import localException.TransmissionError; import localException.SizeError; import localException.ProtocolError; diff --git a/src/protocolP2P/LoadRequest.java b/src/protocolP2P/LoadRequest.java index 251981d..1fa0aeb 100644 --- a/src/protocolP2P/LoadRequest.java +++ b/src/protocolP2P/LoadRequest.java @@ -6,7 +6,6 @@ import localException.ProtocolError; import localException.InternalError; import localException.SizeError; import tools.BytesArrayTools; -import java.io.UnsupportedEncodingException; /** Representation of payload for load request. * @author Louis Royer diff --git a/src/protocolP2P/ProtocolP2PPacket.java b/src/protocolP2P/ProtocolP2PPacket.java index 037da9b..74a1dcd 100644 --- a/src/protocolP2P/ProtocolP2PPacket.java +++ b/src/protocolP2P/ProtocolP2PPacket.java @@ -11,7 +11,7 @@ import remoteException.NotFound; import remoteException.ProtocolRemoteError; import remoteException.VersionRemoteError; import remoteException.EmptyFile; -import java.net.InetAddress; +import remoteException.NotATracker; import java.io.IOException; import tools.HostItem; @@ -60,6 +60,7 @@ public abstract class ProtocolP2PPacket { /** Receive a response * @throws EmptyFile * @throws NotFound + * @throws NotATracker * @throws EmptyDirectory * @throws InternalRemoteError * @throws VersionRemoteError @@ -72,7 +73,7 @@ public abstract class ProtocolP2PPacket { * @throws IOException * @throws SocketClosed */ - public abstract ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed; + public abstract ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed; /** Receive a request, subclasses must overwrite this constructor. * @param socket socket used to get the request @@ -108,6 +109,7 @@ public abstract class ProtocolP2PPacket { */ protected void checkProtocolVersion() throws VersionError { if (PROTOCOL_VERSION != version) { + System.err.println("Error: wrong version in packet:" + version); throw new VersionError(); } } diff --git a/src/protocolP2P/ProtocolP2PPacketTCP.java b/src/protocolP2P/ProtocolP2PPacketTCP.java index f2254f8..9272ea6 100644 --- a/src/protocolP2P/ProtocolP2PPacketTCP.java +++ b/src/protocolP2P/ProtocolP2PPacketTCP.java @@ -5,21 +5,19 @@ import localException.SizeError; import localException.TransmissionError; import localException.VersionError; import localException.SocketClosed; +import remoteException.NotATracker; import remoteException.EmptyDirectory; import remoteException.InternalRemoteError; import remoteException.NotFound; import remoteException.ProtocolRemoteError; import remoteException.VersionRemoteError; import remoteException.EmptyFile; -import tools.BytesArrayTools; import tools.HostItem; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; import protocolP2P.LoadRequest; import protocolP2P.FileList; import protocolP2P.FilePart; -import java.util.ArrayList; -import java.lang.Byte; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; @@ -68,9 +66,9 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { socket.close(); } catch (IOException e2) { System.err.println("Cannot close socket"); - } finally { throw new SocketClosed(); } + } } @@ -117,7 +115,6 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { ss.close(); } catch (IOException e2) { System.err.println("Cannot close socket"); - } finally { throw new SocketClosed(); } } @@ -139,6 +136,8 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { case LOAD_RESPONSE: case LIST_RESPONSE: case HASH_RESPONSE: + case DISCOVER_RESPONSE: + case NOT_A_TRACKER: // we were expecting a request, but we are receiving a response throw new ProtocolError(); default : @@ -189,6 +188,7 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { * @return ProtocolP2PPacket received * @throws EmptyFile * @throws NotFound + * @throws NotATracker * @throws EmptyDirectory * @throws InternalRemoteError * @throws VersionRemoteError @@ -201,7 +201,7 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { * @throws IOException * @throws SocketClosed */ - public ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed { + public ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed { assert requestSocket != null : "Cannot receive response because request packet not sent."; if (requestSocket == null) { throw new InternalError(); @@ -226,6 +226,8 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { throw new NotFound(); case EMPTY_FILE: throw new EmptyFile(); + case NOT_A_TRACKER: + throw new NotATracker(); default : return (ProtocolP2PPacket)p; } diff --git a/src/protocolP2P/ProtocolP2PPacketUDP.java b/src/protocolP2P/ProtocolP2PPacketUDP.java index 4bc98bb..03ffd64 100644 --- a/src/protocolP2P/ProtocolP2PPacketUDP.java +++ b/src/protocolP2P/ProtocolP2PPacketUDP.java @@ -5,6 +5,7 @@ import localException.SizeError; import localException.TransmissionError; import localException.VersionError; import localException.SocketClosed; +import remoteException.NotATracker; import remoteException.EmptyDirectory; import remoteException.InternalRemoteError; import remoteException.NotFound; @@ -18,8 +19,6 @@ import protocolP2P.RequestResponseCode; import protocolP2P.LoadRequest; import protocolP2P.FileList; import protocolP2P.FilePart; -import java.util.ArrayList; -import java.lang.Byte; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketAddress; @@ -133,6 +132,8 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { case LOAD_RESPONSE: case LIST_RESPONSE: case HASH_RESPONSE: + case DISCOVER_RESPONSE: + case NOT_A_TRACKER: // we were expecting a request, but we are receiving a response throw new ProtocolError(); default : @@ -186,6 +187,7 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { * @return ProtocolP2PPacket received * @throws EmptyFile * @throws NotFound + * @throws NotATracker * @throws EmptyDirectory * @throws InternalRemoteError * @throws VersionRemoteError @@ -197,7 +199,7 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { * @throws SizeError * @throws IOException */ - public ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException { + public ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException { assert requestSocket != null : "Cannot receive response because request packet not sent."; if (requestSocket == null) { throw new InternalError(); @@ -206,6 +208,7 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { byte[] packet = new byte[8192]; DatagramPacket reception = new DatagramPacket(packet, packet.length); requestSocket.receive(reception); + // contruction try { ProtocolP2PPacketUDP p = new ProtocolP2PPacketUDP(packet); @@ -223,6 +226,8 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { throw new NotFound(); case EMPTY_FILE: throw new EmptyFile(); + case NOT_A_TRACKER: + throw new NotATracker(); default : return (ProtocolP2PPacket)p; } diff --git a/src/remoteException/EmptyDirectory.java b/src/remoteException/EmptyDirectory.java index 12fce76..45e477a 100644 --- a/src/remoteException/EmptyDirectory.java +++ b/src/remoteException/EmptyDirectory.java @@ -2,6 +2,6 @@ package remoteException; import exception.RemoteException; -public class EmptyDirectory extends exception.RemoteException { +public class EmptyDirectory extends RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/EmptyFile.java b/src/remoteException/EmptyFile.java index cbc580f..e5911d9 100644 --- a/src/remoteException/EmptyFile.java +++ b/src/remoteException/EmptyFile.java @@ -2,6 +2,6 @@ package remoteException; import exception.RemoteException; -public class EmptyFile extends exception.RemoteException { +public class EmptyFile extends RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/InternalRemoteError.java b/src/remoteException/InternalRemoteError.java index 802ee05..1d2e92f 100644 --- a/src/remoteException/InternalRemoteError.java +++ b/src/remoteException/InternalRemoteError.java @@ -2,6 +2,6 @@ package remoteException; import exception.RemoteException; -public class InternalRemoteError extends exception.RemoteException { +public class InternalRemoteError extends RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/NotATracker.java b/src/remoteException/NotATracker.java index dbccea2..1f22ce0 100644 --- a/src/remoteException/NotATracker.java +++ b/src/remoteException/NotATracker.java @@ -2,6 +2,6 @@ package remoteException; import exception.RemoteException; -public class NotATracker extends exception.RemoteException { +public class NotATracker extends RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/NotFound.java b/src/remoteException/NotFound.java index f8002bc..c0e61d9 100644 --- a/src/remoteException/NotFound.java +++ b/src/remoteException/NotFound.java @@ -2,6 +2,6 @@ package remoteException; import exception.RemoteException; -public class NotFound extends exception.RemoteException { +public class NotFound extends RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/ProtocolRemoteError.java b/src/remoteException/ProtocolRemoteError.java index c0c6161..1560083 100644 --- a/src/remoteException/ProtocolRemoteError.java +++ b/src/remoteException/ProtocolRemoteError.java @@ -2,6 +2,6 @@ package remoteException; import exception.RemoteException; -public class ProtocolRemoteError extends exception.RemoteException { +public class ProtocolRemoteError extends RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/VersionRemoteError.java b/src/remoteException/VersionRemoteError.java index 775d9cb..4e7a1d5 100644 --- a/src/remoteException/VersionRemoteError.java +++ b/src/remoteException/VersionRemoteError.java @@ -2,6 +2,6 @@ package remoteException; import exception.RemoteException; -public class VersionRemoteError extends exception.RemoteException { +public class VersionRemoteError extends RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index a136574..98ce3cd 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -23,12 +23,6 @@ import localException.SizeError; import localException.TransmissionError; import localException.VersionError; import localException.SocketClosed; -import remoteException.EmptyDirectory; -import remoteException.InternalRemoteError; -import remoteException.NotFound; -import remoteException.ProtocolRemoteError; -import remoteException.VersionRemoteError; -import remoteException.EmptyFile; import java.util.Arrays; import tools.Logger; import tools.LogLevel; @@ -360,11 +354,12 @@ public class ServerManagementTCP implements Runnable { logger.writeTCP("Unregistering from tracker", LogLevel.Info); ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Unregister(host)); p.sendRequest((Object)tracker.getTCPSocket()); + //tracker.closeTCPSocket(); logger.writeTCP("Registering into tracker", LogLevel.Info); p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(host)); p.sendRequest((Object)tracker.getTCPSocket()); logger.writeTCP("Registering completed", LogLevel.Debug); - tracker.closeTCPSocket(); + //tracker.closeTCPSocket(); } } diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index c082825..7573bda 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -22,12 +22,6 @@ import localException.SizeError; import localException.TransmissionError; import localException.VersionError; import localException.SocketClosed; -import remoteException.EmptyDirectory; -import remoteException.InternalRemoteError; -import remoteException.NotFound; -import remoteException.ProtocolRemoteError; -import remoteException.VersionRemoteError; -import remoteException.EmptyFile; import java.util.Arrays; import tools.Logger; import tools.LogLevel; @@ -86,10 +80,10 @@ public class ServerManagementUDP implements Runnable { Payload p = pd.getPayload(); switch (p.getRequestResponseCode()) { case LOAD_REQUEST: - LoadRequestManagement(logger, p, pd); + loadRequestManagement(p, pd); break; case LIST_REQUEST: - ListRequestManagement(logger, pd); + listRequestManagement(pd); break; case HASH_REQUEST: logger.writeUDP("Received HASH_REQUEST", LogLevel.Action); @@ -160,7 +154,7 @@ public class ServerManagementUDP implements Runnable { } } - public void LoadRequestManagement(Logger logger, Payload p, ProtocolP2PPacketUDP pd){ + public void loadRequestManagement(Payload p, ProtocolP2PPacketUDP pd){ logger.writeUDP("Received LOAD_REQUEST", LogLevel.Action); assert p instanceof LoadRequest : "payload must be an instance of LoadRequest"; if (!(p instanceof LoadRequest)) { @@ -210,14 +204,14 @@ public class ServerManagementUDP implements Runnable { } } - public void ListRequestManagement(Logger logger, ProtocolP2PPacketUDP pd){ + public void listRequestManagement(ProtocolP2PPacketUDP pd) { logger.writeUDP("Received LIST_REQUEST", LogLevel.Action); try { if (fileList.length == 0) { - logger.writeUDP("Sending EMPTY_DIRECTORY", LogLevel.Action); + logger.writeUDP("Sending EMPTY_DIRECTORY to host " + pd.getHostItem(), LogLevel.Action); pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); } else { - logger.writeUDP("Sending LIST_RESPONSE", LogLevel.Action); + logger.writeUDP("Sending LIST_RESPONSE to host " + pd.getHostItem(), LogLevel.Action); pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)(new FileList(fileList)))); } } catch (Exception e2) { diff --git a/src/tools/Directories.java b/src/tools/Directories.java index 97ec091..8c9a86e 100644 --- a/src/tools/Directories.java +++ b/src/tools/Directories.java @@ -99,6 +99,7 @@ public class Directories { System.out.println("Do you want to open this directory? (y/N)"); Scanner scanner = new Scanner(System.in); String resp = scanner.nextLine(); + scanner.close(); if (resp.equals("y") || resp.equals("Y")) { System.out.println("Openning"); openDataHomeDirectory(subdir); diff --git a/src/tools/HostList.java b/src/tools/HostList.java index 510e3ba..eae5e4e 100644 --- a/src/tools/HostList.java +++ b/src/tools/HostList.java @@ -50,6 +50,7 @@ public class HostList { } } while (!servName.equals("stop")); + scanner.close(); return serverList; } } diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index 33f8ad2..32f5394 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -189,7 +189,7 @@ public class TrackerManagementTCP implements Runnable { // add host to known host list HostItem host = ((Register)p).getHostItem(); if (!hostList.contains(host)) { - hostList.add(pd.getHostItem()); + hostList.add(host); } // send a list request try { @@ -197,7 +197,7 @@ public class TrackerManagementTCP implements Runnable { pLReq.sendRequest((Object)host.getTCPSocket()); logger.writeTCP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse(), host); - host.closeTCPSocket(); + //host.closeTCPSocket(); } catch (Exception e) { // remove from list because list request could not be send hostList.remove(host); @@ -253,7 +253,7 @@ public class TrackerManagementTCP implements Runnable { * @throws InternalError */ private void handleListResponse(ProtocolP2PPacketTCP pd, HostItem host) throws InternalError { - logger.writeTCP("Received LIST RESPONSE from host " + host + ": registered host.", LogLevel.Action); + logger.writeTCP("Received LIST RESPONSE from host " + host, LogLevel.Action); Payload p = pd.getPayload(); assert p instanceof FileList: "payload must be an instance of FileList"; if (!(p instanceof FileList)) { diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index 3a93fe6..ee604c4 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -21,6 +21,7 @@ import protocolP2P.DiscoverResponse; import protocolP2P.FileList; import protocolP2P.HashRequest; import localException.InternalError; +import remoteException.EmptyDirectory; /** Tracker management implementation with udp * @author Louis Royer @@ -142,15 +143,21 @@ public class TrackerManagementUDP implements Runnable { // add host to known host list HostItem host = ((Register)p).getHostItem(); if (!hostList.contains(host)) { - hostList.add(pd.getHostItem()); + hostList.add(host); } // send a list request try { - ProtocolP2PPacket pLReq =(ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST)); + ProtocolP2PPacket pLReq = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST)); pLReq.sendRequest((Object)host.getUDPSocket()); logger.writeUDP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); - handleListResponse((ProtocolP2PPacketUDP)pLReq.receiveResponse(), host); + ProtocolP2PPacket resp = pLReq.receiveResponse(); + handleListResponse((ProtocolP2PPacketUDP)resp, host); + logger.writeUDP("Received LIST RESPONSE from host " + pd.getHostItem(), LogLevel.Action); host.closeUDPSocket(); + } catch (EmptyDirectory e) { + logger.writeUDP("Empty Directory", LogLevel.Debug); + hostList.remove(host); + logger.writeUDP("Received EMPTY DIRECTORY from host " + pd.getHostItem() + ". Aborting.", LogLevel.Action); } catch (Exception e) { // remove from list because list request could not be send hostList.remove(host); -- 2.30.2 From cc06ccc3349ff82f6c50c9e272ab0aedc39853ed Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 20 Mar 2020 14:50:01 +0100 Subject: [PATCH 09/13] Bind sur localhost --- src/serverP2P/ServerManagementTCP.java | 2 +- src/serverP2P/ServerManagementUDP.java | 6 +++++- src/tools/HostItem.java | 22 ++++++++++++++++++++++ src/tools/Logger.java | 1 + src/tracker/TrackerManagementTCP.java | 23 ++++++++++++----------- src/tracker/TrackerManagementUDP.java | 8 +++++--- 6 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index 98ce3cd..69ce5d6 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -64,7 +64,7 @@ public class ServerManagementTCP implements Runnable { initFileList(); initSha512(); try { - socket = new ServerSocket(TCPPort); + socket = new ServerSocket(TCPPort, 10, InetAddress.getLocalHost()); } catch (SocketException e) { logger.writeTCP("Error: cannot listen on port " + TCPPort, LogLevel.Error); System.exit(-1); diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index 7573bda..2050916 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -33,6 +33,7 @@ import protocolP2P.HashResponse; import tools.HostItem; import protocolP2P.Register; import protocolP2P.Unregister; +import java.net.UnknownHostException; /** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol for UDP. * @author Louis Royer @@ -62,10 +63,13 @@ public class ServerManagementUDP implements Runnable { initFileList(); initSha512(); try { - socket = new DatagramSocket(UDPPort); + socket = new DatagramSocket(UDPPort, InetAddress.getLocalHost()); } catch (SocketException e) { logger.writeUDP("Error: cannot listen on port " + UDPPort, LogLevel.Error); System.exit(-1); + } catch (UnknownHostException e) { + logger.writeUDP(e, LogLevel.Error); + System.exit(-2); } } diff --git a/src/tools/HostItem.java b/src/tools/HostItem.java index fe15007..76dcb2d 100644 --- a/src/tools/HostItem.java +++ b/src/tools/HostItem.java @@ -17,6 +17,7 @@ public class HostItem { private int port; private Socket tcpSocket; private DatagramSocket udpSocket; + private InetAddress inetAddress; /** Constructor with hostname and port * @param hostname Hostname @@ -125,4 +126,25 @@ public class HostItem { public int hashCode() { return hostname.hashCode() ^ port; } + + public InetAddress getInetAddress() { + if (inetAddress == null) { + try { + inetAddress = InetAddress.getByName(getHostname()); + } catch (UnknownHostException e) { + System.err.println("Error: Unknown host."); + System.exit(-1); + } + } + return inetAddress; + } + + public HostItem(Socket s) { + tcpSocket = s; + inetAddress = s.getInetAddress(); + hostname = inetAddress.getCanonicalHostName(); + port = s.getPort(); + } + + } diff --git a/src/tools/Logger.java b/src/tools/Logger.java index 63c2107..4da4848 100644 --- a/src/tools/Logger.java +++ b/src/tools/Logger.java @@ -120,4 +120,5 @@ public class Logger { e.printStackTrace(); } + } diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index 32f5394..8ab4724 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -22,6 +22,8 @@ import protocolP2P.DiscoverResponse; import protocolP2P.FileList; import protocolP2P.HashRequest; import localException.InternalError; +import java.net.UnknownHostException; +import java.net.InetAddress; /** Tracker management implementation with tcp @@ -32,7 +34,7 @@ import localException.InternalError; */ public class TrackerManagementTCP implements Runnable { - private int port; + private HostItem tracker; private Logger logger; private ServerSocket socket; private List hostList = new ArrayList<>(); @@ -43,15 +45,15 @@ public class TrackerManagementTCP implements Runnable { * @param logger Logger object */ public TrackerManagementTCP(int port, Logger logger) { - this.port = port; + tracker = new HostItem("localhost", port); this.logger = logger; try { - socket = new ServerSocket(port); + socket = new ServerSocket(tracker.getPort(), 10, tracker.getInetAddress()); } catch (SocketException e) { - logger.writeTCP("Error: cannot listen on port " + port, LogLevel.Error); + logger.writeTCP("Error: cannot listen on" + tracker, LogLevel.Error); System.exit(-1); } catch (IOException e) { - logger.writeTCP("Error: cannot openning socket", LogLevel.Error); + logger.writeTCP("Error: cannot open socket", LogLevel.Error); System.exit(-2); } } @@ -76,13 +78,12 @@ public class TrackerManagementTCP implements Runnable { */ private class ClientHandler implements Runnable { private Socket s; - private String addr; + private HostItem addr; /** Constructor with a socket. * @param s Socket of this client */ public ClientHandler(Socket s) { - this.s = s; - this.addr = "[" +s.getInetAddress().getHostAddress() + "]:" + s.getPort() + " "; + this.addr = new HostItem(s); } /** Implementation of runnable. This method allow to serve one client. @@ -90,11 +91,11 @@ public class TrackerManagementTCP implements Runnable { public void run() { boolean end = false; - logger.writeTCP(addr + "New connection", LogLevel.Action); + logger.writeTCP("[ " + addr + "] New connection", LogLevel.Action); do { end = handleRequest(); } while(!end); - logger.writeTCP(addr + "End of connection", LogLevel.Action); + logger.writeTCP("[ " + addr + "] End of connection", LogLevel.Action); } /** Respond to next request incomming on socket s. @@ -103,7 +104,7 @@ public class TrackerManagementTCP implements Runnable { */ private boolean handleRequest() { try { - ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)s); + ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)addr.getTCPSocket()); Payload p = pd.getPayload(); switch (p.getRequestResponseCode()) { case LOAD_REQUEST: diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index ee604c4..41ff8d8 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -22,6 +22,8 @@ import protocolP2P.FileList; import protocolP2P.HashRequest; import localException.InternalError; import remoteException.EmptyDirectory; +import java.net.InetAddress; +import java.net.UnknownHostException; /** Tracker management implementation with udp * @author Louis Royer @@ -31,7 +33,7 @@ import remoteException.EmptyDirectory; */ public class TrackerManagementUDP implements Runnable { - private int port; + private HostItem tracker; private Logger logger; private DatagramSocket socket; private List hostList = new ArrayList<>(); @@ -42,10 +44,10 @@ public class TrackerManagementUDP implements Runnable { * @param logger Logger object */ public TrackerManagementUDP(int port, Logger logger) { - this.port = port; + tracker = new HostItem("localhost", port); this.logger = logger; try { - socket = new DatagramSocket(port); + socket = new DatagramSocket(tracker.getPort(), tracker.getInetAddress()); } catch (SocketException e) { logger.writeUDP("Error: cannot listen on port " + port, LogLevel.Error); System.exit(-1); -- 2.30.2 From 3387b90b14434d78ba95993032cfe643e6735680 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 20 Mar 2020 16:30:42 +0100 Subject: [PATCH 10/13] HostItems dans le server --- src/clientP2P/ClientP2P.java | 5 ++--- src/serverP2P/ServerManagementTCP.java | 30 +++++++++++++------------- src/serverP2P/ServerManagementUDP.java | 23 ++++++++++---------- src/serverP2P/ServerP2P.java | 5 ++--- src/tracker/TrackerManagementTCP.java | 5 ++--- src/tracker/TrackerManagementUDP.java | 1 - 6 files changed, 32 insertions(+), 37 deletions(-) diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index 139701f..a1700b9 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -72,7 +72,6 @@ public class ClientP2P { * @param args server listenning port */ public static void main(String [] args) { - if (args[1].equals("help") || args[1].equals("-h") || args[1].equals("h")){ System.out.println("usage : java -ea clientP2P.ClientP2P -- "); } @@ -85,8 +84,8 @@ public class ClientP2P { } // Server threads - ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + c.subdir, c.port, c.loggerServer, c.tracker); - ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + c.subdir, c.port, c.loggerServer, c.tracker); + ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + c.subdir, "localhost", c.port, c.loggerServer, c.tracker); + ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + c.subdir, "localhost", c.port, c.loggerServer, c.tracker); Thread tudp = new Thread(smudp); tudp.setName("server UDP P2P-JAVA-PROJECT (port: " + c.port + ")"); tudp.start(); diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index 69ce5d6..d04b544 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -47,26 +47,29 @@ public class ServerManagementTCP implements Runnable { private String[] fileList; private Map sha512 = new HashMap<>(); private String baseDirectory; - private int TCPPort; private ServerSocket socket; private Logger logger; private HostItem tracker; + private HostItem server; /** Constructor for TCP implementation, with baseDirectory and TCPPort parameters. * @param baseDirectory the root directory where files are stored + * @param hostName the server will bind on this address * @param TCPPort the server will listen on this port + * @param logger Logger item + * @param tracker Tracker */ - public ServerManagementTCP(String baseDirectory, int TCPPort, Logger logger, HostItem tracker) { + public ServerManagementTCP(String baseDirectory, String hostName, int port, Logger logger, HostItem tracker) { + server = new HostItem(hostName, port); this.tracker = tracker; this.logger = logger; this.baseDirectory = baseDirectory; - this.TCPPort = TCPPort; initFileList(); initSha512(); try { - socket = new ServerSocket(TCPPort, 10, InetAddress.getLocalHost()); + socket = new ServerSocket(server.getPort(), 10, server.getInetAddress()); } catch (SocketException e) { - logger.writeTCP("Error: cannot listen on port " + TCPPort, LogLevel.Error); + logger.writeTCP("Error: cannot listen on " + server, LogLevel.Error); System.exit(-1); } catch (IOException e) { logger.writeTCP("Error: cannot openning socket", LogLevel.Error); @@ -93,14 +96,12 @@ public class ServerManagementTCP implements Runnable { /** Private runnable class allowing to serve one client. */ private class ClientHandler implements Runnable { - private Socket s; - private String addr; + private HostItem addr; /** Constructor with a socket. * @param s Socket of this client */ public ClientHandler(Socket s) { - this.s = s; - this.addr = "[" +s.getInetAddress().getHostAddress() + "]:" + s.getPort() + " "; + addr = new HostItem(s); } /** Implementation of runnable. This method allow to serve one client. @@ -108,11 +109,11 @@ public class ServerManagementTCP implements Runnable { public void run() { boolean end = false; - logger.writeTCP(addr + "New connection", LogLevel.Action); + logger.writeTCP("[ " + addr + "] New connection", LogLevel.Action); do { end = handleRequest(); } while(!end); - logger.writeTCP(addr + "End of connection", LogLevel.Action); + logger.writeTCP("[ " + addr + "] End of connection", LogLevel.Action); } /** Respond to next request incomming on socket s. @@ -121,7 +122,7 @@ public class ServerManagementTCP implements Runnable { */ private boolean handleRequest() { try { - ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)s); + ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)addr.getTCPSocket()); Payload p = pd.getPayload(); switch (p.getRequestResponseCode()) { case LOAD_REQUEST: @@ -350,13 +351,12 @@ public class ServerManagementTCP implements Runnable { * @throws SocketClosed */ private void registerTracker() throws InternalError, IOException, SocketClosed { - HostItem host = new HostItem(InetAddress.getLocalHost().getCanonicalHostName(), TCPPort); logger.writeTCP("Unregistering from tracker", LogLevel.Info); - ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Unregister(host)); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Unregister(server)); p.sendRequest((Object)tracker.getTCPSocket()); //tracker.closeTCPSocket(); logger.writeTCP("Registering into tracker", LogLevel.Info); - p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(host)); + p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(server)); p.sendRequest((Object)tracker.getTCPSocket()); logger.writeTCP("Registering completed", LogLevel.Debug); //tracker.closeTCPSocket(); diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index 2050916..e5f81db 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -46,30 +46,30 @@ public class ServerManagementUDP implements Runnable { private String[] fileList; private Map sha512 = new HashMap<>(); private String baseDirectory; - private int UDPPort; private DatagramSocket socket; private Logger logger; private HostItem tracker; + private HostItem server; /** Constructor for UDP implementation, with baseDirectory and UDPPort parameters. * @param baseDirectory the root directory where files are stored - * @param UDPPort the server will listen on this port + * @param hostName the server will bind on this address + * @param port the server will listen on this port + * @param logger Logger item + * @param tracker Tracker */ - public ServerManagementUDP(String baseDirectory, int UDPPort, Logger logger, HostItem tracker) { + public ServerManagementUDP(String baseDirectory, String hostName, int port, Logger logger, HostItem tracker) { + server = new HostItem(hostName, port); this.logger = logger; this.baseDirectory = baseDirectory; - this.UDPPort = UDPPort; this.tracker = tracker; initFileList(); initSha512(); try { - socket = new DatagramSocket(UDPPort, InetAddress.getLocalHost()); + socket = new DatagramSocket(server.getPort(), server.getInetAddress()); } catch (SocketException e) { - logger.writeUDP("Error: cannot listen on port " + UDPPort, LogLevel.Error); + logger.writeUDP("Error: cannot listen on " + server, LogLevel.Error); System.exit(-1); - } catch (UnknownHostException e) { - logger.writeUDP(e, LogLevel.Error); - System.exit(-2); } } @@ -291,12 +291,11 @@ public class ServerManagementUDP implements Runnable { * @throws SocketClosed */ private void registerTracker() throws InternalError, IOException, SocketClosed { - HostItem host = new HostItem(InetAddress.getLocalHost().getCanonicalHostName(), UDPPort); logger.writeUDP("Unregistering from tracker", LogLevel.Info); - ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Unregister(host)); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Unregister(server)); p.sendRequest((Object)tracker.getUDPSocket()); logger.writeUDP("Registering into tracker", LogLevel.Info); - p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Register(host)); + p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Register(server)); p.sendRequest((Object)tracker.getUDPSocket()); logger.writeUDP("Registering completed", LogLevel.Debug); tracker.closeUDPSocket(); diff --git a/src/serverP2P/ServerP2P.java b/src/serverP2P/ServerP2P.java index abfdb66..1b57958 100644 --- a/src/serverP2P/ServerP2P.java +++ b/src/serverP2P/ServerP2P.java @@ -43,8 +43,8 @@ public class ServerP2P { } else{ ServerP2P s = new ServerP2P(args[1], args[2], args[3]); - ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, s.port, s.logger, s.tracker); - ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, s.port, s.logger, s.tracker); + ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, "localhost", s.port, s.logger, s.tracker); + ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, "localhost", s.port, s.logger, s.tracker); Thread tudp = new Thread(smudp); tudp.setName("server UDP P2P-JAVA-PROJECT"); tudp.start(); @@ -53,5 +53,4 @@ public class ServerP2P { ttcp.start(); } } - } diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index 8ab4724..491b883 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -77,7 +77,6 @@ public class TrackerManagementTCP implements Runnable { /** Private runnable class allowing to serve one client. */ private class ClientHandler implements Runnable { - private Socket s; private HostItem addr; /** Constructor with a socket. * @param s Socket of this client @@ -198,7 +197,8 @@ public class TrackerManagementTCP implements Runnable { pLReq.sendRequest((Object)host.getTCPSocket()); logger.writeTCP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse(), host); - //host.closeTCPSocket(); + logger.writeTCP("Received LIST RESPONSE from host " + pd.getHostItem(), LogLevel.Action); + host.closeTCPSocket(); } catch (Exception e) { // remove from list because list request could not be send hostList.remove(host); @@ -254,7 +254,6 @@ public class TrackerManagementTCP implements Runnable { * @throws InternalError */ private void handleListResponse(ProtocolP2PPacketTCP pd, HostItem host) throws InternalError { - logger.writeTCP("Received LIST RESPONSE from host " + host, LogLevel.Action); Payload p = pd.getPayload(); assert p instanceof FileList: "payload must be an instance of FileList"; if (!(p instanceof FileList)) { diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index 41ff8d8..3a3cbc2 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -215,7 +215,6 @@ public class TrackerManagementUDP implements Runnable { * @throws InternalError */ private void handleListResponse(ProtocolP2PPacketUDP pd, HostItem host) throws InternalError { - logger.writeUDP("Received LIST RESPONSE from host " + host, LogLevel.Action); Payload p = pd.getPayload(); assert p instanceof FileList: "payload must be an instance of FileList"; if (!(p instanceof FileList)) { -- 2.30.2 From ad2b79607130e1cf2c1d2c069b08505ed77af194 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 20 Mar 2020 17:41:24 +0100 Subject: [PATCH 11/13] Fix tcp --- src/protocolP2P/ProtocolP2PPacketTCP.java | 20 ++++++++++++++++++-- src/serverP2P/ServerManagementTCP.java | 14 ++++++++++---- src/tracker/TrackerManagementTCP.java | 5 +++++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/protocolP2P/ProtocolP2PPacketTCP.java b/src/protocolP2P/ProtocolP2PPacketTCP.java index 9272ea6..b99e83f 100644 --- a/src/protocolP2P/ProtocolP2PPacketTCP.java +++ b/src/protocolP2P/ProtocolP2PPacketTCP.java @@ -108,11 +108,14 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { Socket ss = (Socket)socket; byte[] packet = new byte[1024]; try { - System.err.println("Reading " + ss.getInputStream().read(packet) + " bytes"); + if (-1 == ss.getInputStream().read(packet)) { + throw new IOException(); + } } catch (IOException e) { // Error: cannot read request, closing socket try { ss.close(); + throw new SocketClosed(); } catch (IOException e2) { System.err.println("Cannot close socket"); throw new SocketClosed(); @@ -208,7 +211,20 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { } // reception byte[] packet = new byte[8192]; - requestSocket.getInputStream().read(packet); + try { + if (-1== requestSocket.getInputStream().read(packet)) { + throw new IOException(); + } + } catch (IOException e) { + // Error: cannot read request, closing socket + try { + requestSocket.close(); + throw new SocketClosed(); + } catch (IOException e2) { + System.err.println("Cannot close socket"); + throw new SocketClosed(); + } + } // contruction try { ProtocolP2PPacketTCP p = new ProtocolP2PPacketTCP(packet); diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index d04b544..359d616 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -109,11 +109,11 @@ public class ServerManagementTCP implements Runnable { public void run() { boolean end = false; - logger.writeTCP("[ " + addr + "] New connection", LogLevel.Action); + logger.writeTCP("[" + addr + "] New connection", LogLevel.Action); do { end = handleRequest(); } while(!end); - logger.writeTCP("[ " + addr + "] End of connection", LogLevel.Action); + logger.writeTCP("[" + addr + "] End of connection", LogLevel.Action); } /** Respond to next request incomming on socket s. @@ -354,12 +354,18 @@ public class ServerManagementTCP implements Runnable { logger.writeTCP("Unregistering from tracker", LogLevel.Info); ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Unregister(server)); p.sendRequest((Object)tracker.getTCPSocket()); - //tracker.closeTCPSocket(); + // FIXME: this is a hack + // ProtocolP2PPacketTCP reads 1024 bytes but if 2 request comes at the same time InputStream is cleared fully + // and we keep waiting forever on the other side + // a fix could be to read only the header first, and read the required size after + try { + Thread.sleep(100); + } catch (InterruptedException e) {} logger.writeTCP("Registering into tracker", LogLevel.Info); p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(server)); p.sendRequest((Object)tracker.getTCPSocket()); logger.writeTCP("Registering completed", LogLevel.Debug); - //tracker.closeTCPSocket(); + tracker.closeTCPSocket(); } } diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index 491b883..5f75aa2 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -24,6 +24,7 @@ import protocolP2P.HashRequest; import localException.InternalError; import java.net.UnknownHostException; import java.net.InetAddress; +import localException.SocketClosed; /** Tracker management implementation with tcp @@ -119,9 +120,11 @@ public class TrackerManagementTCP implements Runnable { sendNotFound(pd); break; case REGISTER: + logger.writeTCP("Received REGISTER from host " + pd.getHostItem(), LogLevel.Debug); handleRegister(pd); break; case UNREGISTER: + logger.writeTCP("Received UNREGISTER from host " + pd.getHostItem(), LogLevel.Debug); handleUnregister(pd); break; case DISCOVER_REQUEST: @@ -135,6 +138,8 @@ public class TrackerManagementTCP implements Runnable { } catch (IOException e) { logger.writeTCP(e, LogLevel.Warning); return true; + } catch (SocketClosed e) { + return true; } catch (LocalException e) { logger.writeTCP(e, LogLevel.Warning); return true; -- 2.30.2 From 683529b21c3e72ea92d1a56e85c35c759b4ac071 Mon Sep 17 00:00:00 2001 From: Louis Date: Sat, 21 Mar 2020 14:29:29 +0100 Subject: [PATCH 12/13] Add javadoc on some methods --- src/serverP2P/ServerManagementUDP.java | 11 +++++++++-- src/tools/HostItem.java | 6 ++++++ src/tools/Logger.java | 3 +++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index e5f81db..fbc0795 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -84,7 +84,7 @@ public class ServerManagementUDP implements Runnable { Payload p = pd.getPayload(); switch (p.getRequestResponseCode()) { case LOAD_REQUEST: - loadRequestManagement(p, pd); + loadRequestManagement(pd); break; case LIST_REQUEST: listRequestManagement(pd); @@ -158,7 +158,11 @@ public class ServerManagementUDP implements Runnable { } } - public void loadRequestManagement(Payload p, ProtocolP2PPacketUDP pd){ + /** Respond to LOAD requests + * @param pd ProtocolP2PPacketUDP + */ + public void loadRequestManagement(ProtocolP2PPacketUDP pd){ + Payload p = pd.getPayload(); logger.writeUDP("Received LOAD_REQUEST", LogLevel.Action); assert p instanceof LoadRequest : "payload must be an instance of LoadRequest"; if (!(p instanceof LoadRequest)) { @@ -208,6 +212,9 @@ public class ServerManagementUDP implements Runnable { } } + /** Respond to LIST requests + * @param pd ProtocolP2PPacketUDP + */ public void listRequestManagement(ProtocolP2PPacketUDP pd) { logger.writeUDP("Received LIST_REQUEST", LogLevel.Action); try { diff --git a/src/tools/HostItem.java b/src/tools/HostItem.java index 76dcb2d..80b4f13 100644 --- a/src/tools/HostItem.java +++ b/src/tools/HostItem.java @@ -127,6 +127,9 @@ public class HostItem { return hostname.hashCode() ^ port; } + /** Get InetAddress associated to this HostItem. + * @return InetAddress + */ public InetAddress getInetAddress() { if (inetAddress == null) { try { @@ -139,6 +142,9 @@ public class HostItem { return inetAddress; } + /** Constructor from Socket. + * @param s socket + */ public HostItem(Socket s) { tcpSocket = s; inetAddress = s.getInetAddress(); diff --git a/src/tools/Logger.java b/src/tools/Logger.java index 4da4848..1fdb4ad 100644 --- a/src/tools/Logger.java +++ b/src/tools/Logger.java @@ -17,6 +17,9 @@ import java.sql.Timestamp; public class Logger { private Path logFile; + /** Constructor with logFile. + * @param logFile name of the file to store logs. + */ public Logger(String logFile) { assert logFile != null : "Logfile name is null"; this.logFile = Paths.get(logFile); -- 2.30.2 From 3f21797b09c6e71b6f510c5fc19b0713ddc63cbe Mon Sep 17 00:00:00 2001 From: Louis Date: Sat, 21 Mar 2020 15:48:18 +0100 Subject: [PATCH 13/13] Client now asks servers to tracker ! --- src/clientP2P/ClientManagementTCP.java | 117 ++++++++++++++----------- src/clientP2P/ClientManagementUDP.java | 51 +++++++++-- src/clientP2P/ClientP2P.java | 20 +++-- src/serverP2P/ServerP2P.java | 5 +- src/tools/BytesArrayTools.java | 6 +- src/tools/Directories.java | 7 +- src/tools/HostItem.java | 12 +-- src/tools/HostList.java | 56 ------------ src/tracker/Tracker.java | 5 +- src/tracker/TrackerManagementTCP.java | 8 +- src/tracker/TrackerManagementUDP.java | 3 +- 11 files changed, 151 insertions(+), 139 deletions(-) delete mode 100644 src/tools/HostList.java diff --git a/src/clientP2P/ClientManagementTCP.java b/src/clientP2P/ClientManagementTCP.java index 28fe131..b52899c 100644 --- a/src/clientP2P/ClientManagementTCP.java +++ b/src/clientP2P/ClientManagementTCP.java @@ -31,6 +31,8 @@ import clientP2P.ClientDownloadTCP; import tools.HostItem; import tools.Logger; import tools.LogLevel; +import protocolP2P.DiscoverRequest; +import protocolP2P.DiscoverResponse; /** Implementation of P2P-JAVA-PROJECT CLIENT * @author Louis Royer @@ -42,26 +44,36 @@ public class ClientManagementTCP implements Runnable { private String baseDirectory; private String partsSubdir; private List hostList; + private HostItem tracker; private Logger logger; + private Scanner scanner; - /** Constructor for TCP implementation, with baseDirectory and TCPPort parameters. + /** Constructor for TCP implementation, with baseDirectory, tracker, partsSubdir, logger, and scanner parameters. * @param baseDirectory the root directory where files are stored - * @param host hostname of the server - * @param TCPPort the server will listen on this port + * @param tracker Tracker hostItem + * @param partsSubdir subdirectory to store file parts + * @param logger Loggger + * @param scanner Scanner used to read input */ - public ClientManagementTCP(String baseDirectory, List hostList, String partsSubdir, Logger logger) { + public ClientManagementTCP(String baseDirectory, HostItem tracker, String partsSubdir, Logger logger, Scanner scanner) { + this.scanner = scanner; this.baseDirectory = baseDirectory; - this.hostList = hostList; + this.tracker = tracker; this.partsSubdir = partsSubdir; this.logger = logger; + try { + initHostList(); + } catch (InternalError e) { + System.exit(-1); + } catch (ProtocolError e) { + System.exit(-2); + } } /** Implementation of Runnable */ public void run() { try { - System.out.println("Enter all servers: type \"stop\" when finished"); - Scanner scanner = new Scanner(System.in); String[] list = listDirectory(); System.out.println("Files present on the server:"); for(String listItem: list) { @@ -69,49 +81,35 @@ public class ClientManagementTCP implements Runnable { } System.out.println("Name of the file to download:"); String f = scanner.nextLine(); - scanner.close(); download(f); System.out.println("File " + f + " sucessfully downloaded"); logger.writeTCP("File " + f + " sucessfully downloaded", LogLevel.Info); } catch (EmptyDirectory e) { - System.err.println("Error: Server has no file in directory"); - logger.writeTCP("Error: Server has no file in directory", LogLevel.Error); + logger.writeTCP("Server has no file in directory", LogLevel.Error); } catch (InternalError e) { - System.err.println("Error: Client internal error"); - logger.writeTCP("Error: Client internal error", LogLevel.Error); + logger.writeTCP("Client internal error", LogLevel.Error); } catch (UnknownHostException e) { - System.err.println("Error: Server host is unknown"); - logger.writeTCP("Error: Server host is unknown", LogLevel.Error); + logger.writeTCP("Server host is unknown", LogLevel.Error); } catch (IOException e) { - System.err.println("Error: Request cannot be send or response cannot be received"); - logger.writeTCP("Error: Request cannot be send or response cannot be received", LogLevel.Error); + logger.writeTCP("Request cannot be send or response cannot be received", LogLevel.Error); } catch (TransmissionError e) { - System.err.println("Error: Message received is too big"); - logger.writeTCP("Error: Message received is too big", LogLevel.Error); + logger.writeTCP("Message received is too big", LogLevel.Error); } catch (ProtocolError e) { - System.err.println("Error: Cannot decode server’s response"); - logger.writeTCP("Error: Cannot decode server’s response", LogLevel.Error); + logger.writeTCP("Cannot decode server’s response", LogLevel.Error); } catch (VersionError e) { - System.err.println("Error: Server’s response use bad version of the protocol"); - logger.writeTCP("Error: Server’s response use bad version of the protocol", LogLevel.Error); + logger.writeTCP("Server’s response use bad version of the protocol", LogLevel.Error); } catch (SizeError e) { - System.err.println("Error: Cannot handle this packets because of internal representation limitations of numbers on the client"); - logger.writeTCP("Error: Cannot handle this packets because of internal representation limitations of numbers on the client", LogLevel.Error); + logger.writeTCP("Cannot handle this packets because of internal representation limitations of numbers on the client", LogLevel.Error); } catch (InternalRemoteError e) { - System.err.println("Error: Server internal error"); - logger.writeTCP("Error: Server internal error", LogLevel.Error); + logger.writeTCP("Server internal error", LogLevel.Error); } catch (ProtocolRemoteError e) { - System.err.println("Error: Server cannot decode client’s request"); - logger.writeTCP("Error: Server cannot decode client’s request", LogLevel.Error); + logger.writeTCP("Server cannot decode client’s request", LogLevel.Error); } catch (VersionRemoteError e) { - System.err.println("Error: Server cannot decode this version of the protocol"); - logger.writeTCP("Error: Server cannot decode this version of the protocol", LogLevel.Error); + logger.writeTCP("Server cannot decode this version of the protocol", LogLevel.Error); } catch (NotFound e) { - System.err.println("Error: Server has not this file in directory"); - logger.writeTCP("Error: Server has not this file in directory", LogLevel.Error); + logger.writeTCP("Server has not this file in directory", LogLevel.Error); } catch (EmptyFile e) { - System.err.println("Error: File is empty"); - logger.writeTCP("Error: File is empty", LogLevel.Error); + logger.writeTCP("File is empty", LogLevel.Error); } } @@ -139,21 +137,18 @@ public class ClientManagementTCP implements Runnable { if (downLoader.getSuccess()) { byte[] hash512 = downLoader.getHashSum512(); if (!Arrays.equals(hash512, computeHashsum(filename, HashAlgorithm.SHA512))) { - System.err.println("Error: Hashsum does not match"); - logger.writeTCP("Error: Hashsum does not match", LogLevel.Error); - System.err.println("Computed checksum:"); + logger.writeTCP("Hashsum does not match", LogLevel.Error); + String line = "Computed checksum:\n"; byte[] c = computeHashsum(filename, HashAlgorithm.SHA512); for (byte b: c) { - System.err.print(String.format("%02X", b)); - logger.writeTCP("Computed checksum:" + String.format("%02X", b), LogLevel.Info); + line += String.format("%02X", b); } - System.err.println(""); - System.err.println("Received checksum:"); + line += "\nReceived checksum:\n"; for (byte b: hash512) { - System.err.print(String.format("%02X", b)); - logger.writeTCP("Received checksum:" + String.format("%02X", b), LogLevel.Info); + line += String.format("%02X", b); } - System.err.println(""); + line += "\n"; + logger.writeTCP(line, LogLevel.Info); throw new InternalError(); } } else { @@ -196,7 +191,6 @@ public class ClientManagementTCP implements Runnable { logger.writeTCP(e, LogLevel.Error); throw new ProtocolError(); } catch (SocketClosed e){ - System.err.println("listDirectory : SocketClosed"); logger.writeTCP("listDirectory : SocketClosed", LogLevel.Error); throw new ProtocolError(); } catch (NotATracker e) { @@ -214,12 +208,37 @@ public class ClientManagementTCP implements Runnable { MessageDigest md = MessageDigest.getInstance(HashAlgorithm.SHA512.getName()); return md.digest(Files.readAllBytes(Paths.get(baseDirectory + filename))); } catch (NoSuchAlgorithmException e) { - System.out.println("Error: " + h.getName() + " not supported"); - logger.writeTCP("Error: " + h.getName() + " not supported", LogLevel.Error); + logger.writeTCP(h.getName() + " not supported", LogLevel.Error); } catch (IOException e) { - System.out.println("Error: cannot read " + filename); - logger.writeTCP("Error: cannot read " + filename, LogLevel.Error); + logger.writeTCP("cannot read " + filename, LogLevel.Error); } return new byte[0]; } + + /** Initialize hostList from tracker + * @throws ProtocolError + * @throws InternalError + */ + private void initHostList() throws ProtocolError, InternalError { + ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP((Payload) new DiscoverRequest(null)); + try { + d.sendRequest((Object)tracker.getTCPSocket()); + Payload p = d.receiveResponse().getPayload(); + assert p instanceof DiscoverResponse : "This payload must be instance of Filelist"; + if (!(p instanceof DiscoverResponse)) { + throw new InternalError(); + } else { + hostList = ((DiscoverResponse)p).getHostList(); + } + } catch (SocketClosed e){ + logger.writeTCP("listDirectory : SocketClosed", LogLevel.Error); + throw new ProtocolError(); + } catch (NotATracker e) { + logger.writeTCP(e, LogLevel.Error); + throw new ProtocolError(); + } catch (Exception e) { + logger.writeTCP(e, LogLevel.Error); + throw new ProtocolError(); + } + } } diff --git a/src/clientP2P/ClientManagementUDP.java b/src/clientP2P/ClientManagementUDP.java index aa1da60..b298fc7 100644 --- a/src/clientP2P/ClientManagementUDP.java +++ b/src/clientP2P/ClientManagementUDP.java @@ -26,6 +26,8 @@ import protocolP2P.Payload; import protocolP2P.RequestResponseCode; import protocolP2P.FileList; import protocolP2P.HashAlgorithm; +import protocolP2P.DiscoverRequest; +import protocolP2P.DiscoverResponse; import tools.HostItem; import tools.Logger; import tools.LogLevel; @@ -41,26 +43,36 @@ public class ClientManagementUDP implements Runnable { private String baseDirectory; private String partsSubdir; private List hostList; + private HostItem tracker; private Logger logger; + private Scanner scanner; - /** Constructor for UDP implementation, with baseDirectory and UDPPort parameters. + /** Constructor for UDP implementation, with baseDirectory, tracker, partsSubdir, logger and scanner parameters. * @param baseDirectory the root directory where files are stored - * @param host hostname of the server - * @param UDPPort the server will listen on this port + * @param tracker tracker HostItem + * @param partsSubdir subdirectory to store file parts + * @param logger Loggger + * @param scanner Scanner used to read input */ - public ClientManagementUDP(String baseDirectory, List hostList, String partsSubdir, Logger logger) { + public ClientManagementUDP(String baseDirectory, HostItem tracker, String partsSubdir, Logger logger, Scanner scanner) { + this.scanner = scanner; this.baseDirectory = baseDirectory; - this.hostList = hostList; + this.tracker = tracker; this.partsSubdir = partsSubdir; this.logger = logger; + try { + initHostList(); + } catch (InternalError e) { + System.exit(-1); + } catch (ProtocolError e) { + System.exit(-2); + } } /** Implementation of Runnable */ public void run() { try { - System.out.println("Enter all servers: type \"stop\" when finished"); - Scanner scanner = new Scanner(System.in); String[] list = listDirectory(); System.out.println("Files present on the server:"); for(String listItem: list) { @@ -68,7 +80,6 @@ public class ClientManagementUDP implements Runnable { } System.out.println("Name of the file to download:"); String f = scanner.nextLine(); - scanner.close(); download(f); System.out.println("File " + f + " sucessfully downloaded"); logger.writeUDP("File " + f + " sucessfully downloaded", LogLevel.Info); @@ -217,4 +228,28 @@ public class ClientManagementUDP implements Runnable { } return new byte[0]; } + + /** Initialize hostList from tracker + * @throws ProtocolError + * @throws InternalError + */ + private void initHostList() throws ProtocolError, InternalError { + ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP((Payload) new DiscoverRequest(null)); + try { + d.sendRequest((Object)tracker.getUDPSocket()); + Payload p = d.receiveResponse().getPayload(); + assert p instanceof DiscoverResponse : "This payload must be instance of Filelist"; + if (!(p instanceof DiscoverResponse)) { + throw new InternalError(); + } else { + hostList = ((DiscoverResponse)p).getHostList(); + } + } catch (NotATracker e) { + logger.writeUDP(e, LogLevel.Error); + throw new ProtocolError(); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); + throw new ProtocolError(); + } + } } diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index a1700b9..1d1b224 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -10,7 +10,6 @@ import tools.Logger; import tools.LogLevel; import tools.Directories; import tools.HostItem; -import tools.HostList; /** Client + Server implementation. * @author Louis Royer @@ -27,9 +26,9 @@ public class ClientP2P { private String host; private int port; private Directories directories; - private List hostList; private static final int defaultPort = 20000; private HostItem tracker; + private Scanner scanner; /** Initialize loggers if directories and logger are null, @@ -47,6 +46,7 @@ public class ClientP2P { * @param portStr String containing port for server listenning. */ public ClientP2P(String portStr) { + scanner = new Scanner(System.in); tracker = new HostItem("localhost", 30000); // TODO : make it configurable try{ port = Integer.valueOf(Integer.parseInt(portStr)); @@ -62,7 +62,7 @@ public class ClientP2P { directories.createSubdir(parts); host = "localhost"; System.out.println("Server will listen on port " + port + " and serve files from " + directories.getDataHomeDirectory() + subdir); - directories.askOpenDataHomeDirectory(subdir); + directories.askOpenDataHomeDirectory(subdir, scanner); System.out.println("Please enter list of servers to use; first one will be used to ask list of files"); } @@ -102,11 +102,9 @@ public class ClientP2P { } // initialize Host lists - c.hostList = HostList.getServList(); System.out.println("Client : Which transport protocol do you want to use? [TCP/udp]"); - Scanner sc = new Scanner(System.in); - String transportchoosen = sc.nextLine(); - sc.close(); + c.scanner.hasNextLine(); + String transportchoosen = c.scanner.nextLine(); Thread t; switch(transportchoosen){ case "UDP": @@ -114,7 +112,7 @@ public class ClientP2P { case "upd": // alias typo case "2" : System.out.println("Starting with UDP"); - ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.hostList, c.directories.getDataHomeDirectory() + c.parts + "/", c.loggerClient); + ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.tracker, c.directories.getDataHomeDirectory() + c.parts + "/", c.loggerClient, c.scanner); t = new Thread(cmudp); break; case "TCP": @@ -122,12 +120,16 @@ public class ClientP2P { case "1": default: System.out.println("Starting with TCP"); - ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.hostList, c.directories.getDataHomeDirectory() + c.parts + "/", c.loggerClient); + ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.tracker, c.directories.getDataHomeDirectory() + c.parts + "/", c.loggerClient, c.scanner); t = new Thread(cmtcp); break; } t.setName("client P2P-JAVA-PROJECT"); t.start(); + try { + t.join(); + } catch (InterruptedException e) {} + c.scanner.close(); } } } diff --git a/src/serverP2P/ServerP2P.java b/src/serverP2P/ServerP2P.java index 1b57958..df0a3f1 100644 --- a/src/serverP2P/ServerP2P.java +++ b/src/serverP2P/ServerP2P.java @@ -4,6 +4,7 @@ import serverP2P.ServerManagementTCP; import tools.Directories; import tools.Logger; import tools.HostItem; +import java.util.Scanner; /** Server only implementation * First argument of main method is port listened by the server, and is mandatory. @@ -29,7 +30,9 @@ public class ServerP2P { directories.createSubdir(subdir); logger = new Logger(directories.getDataHomeDirectory() + "server.log"); System.out.println("Server will listen on port " + port + " and serve files from " + directories.getDataHomeDirectory() + subdir); - directories.askOpenDataHomeDirectory(subdir); + Scanner scanner = new Scanner(System.in); + directories.askOpenDataHomeDirectory(subdir, scanner); + scanner.close(); } /** Main program entry point diff --git a/src/tools/BytesArrayTools.java b/src/tools/BytesArrayTools.java index f1cbe85..554bc3a 100644 --- a/src/tools/BytesArrayTools.java +++ b/src/tools/BytesArrayTools.java @@ -231,11 +231,13 @@ public class BytesArrayTools { try { int i = start; while(true) { + int j = i; for(byte b: endStr.getBytes()) { - if (b != array[i]) { + if (b != array[j]) { failed = true; break; } + j++; } if (failed) { i++; @@ -244,7 +246,7 @@ public class BytesArrayTools { break; } } - return readString(array, start, i -1 - start); + return readString(array, start, i - start); } catch(IndexOutOfBoundsException e) { throw new InternalError(); } diff --git a/src/tools/Directories.java b/src/tools/Directories.java index 8c9a86e..0ee49c6 100644 --- a/src/tools/Directories.java +++ b/src/tools/Directories.java @@ -70,6 +70,7 @@ public class Directories { } /** Opens dataHomeDirectory if supported. + * @param subdir Subdir to open (optional) */ private void openDataHomeDirectory(String subdir) { String d = dataHomeDirectory; @@ -93,13 +94,13 @@ public class Directories { } /** Asks the user to choose opening dataHomeDirectory or not. + * @param subdir subdirectory to open (optional) + * @param scanner Scanner to use for reading input */ - public void askOpenDataHomeDirectory(String subdir) { + public void askOpenDataHomeDirectory(String subdir, Scanner scanner) { if (os.equals("Linux") || os.equals("Mac") || os.equals("Mac OS X")) { System.out.println("Do you want to open this directory? (y/N)"); - Scanner scanner = new Scanner(System.in); String resp = scanner.nextLine(); - scanner.close(); if (resp.equals("y") || resp.equals("Y")) { System.out.println("Openning"); openDataHomeDirectory(subdir); diff --git a/src/tools/HostItem.java b/src/tools/HostItem.java index 80b4f13..231e6b7 100644 --- a/src/tools/HostItem.java +++ b/src/tools/HostItem.java @@ -36,13 +36,13 @@ public class HostItem { try { tcpSocket = new Socket(InetAddress.getByName(hostname), port); } catch (SocketException e) { - System.err.println("Error: No TCP socket available."); + System.err.println("getTCPSocket error: No TCP socket available."); System.exit(-1); } catch (UnknownHostException e) { - System.err.println("Error: Unknown host."); + System.err.println("getTCPSocket error: Unknown host (" + this + ")."); System.exit(-1); } catch (IOException e) { - System.err.println("Error: Cannot create TCP socket"); + System.err.println("getTCPSocket error: Cannot create TCP socket (" + this + ")."); System.exit(-1); } } @@ -71,10 +71,10 @@ public class HostItem { udpSocket = new DatagramSocket(); udpSocket.connect(InetAddress.getByName(hostname), port); } catch (SocketException e) { - System.err.println("Error: No UDP socket available."); + System.err.println("getUDPSocket error: No UDP socket available." ); System.exit(-1); } catch (UnknownHostException e) { - System.err.println("Error: Unknown host."); + System.err.println("getUDPSocket error: Unknown host (" + this + ")."); System.exit(-1); } } @@ -135,7 +135,7 @@ public class HostItem { try { inetAddress = InetAddress.getByName(getHostname()); } catch (UnknownHostException e) { - System.err.println("Error: Unknown host."); + System.err.println("getInetAddress error: Unknown host (" + this + ")."); System.exit(-1); } } diff --git a/src/tools/HostList.java b/src/tools/HostList.java deleted file mode 100644 index eae5e4e..0000000 --- a/src/tools/HostList.java +++ /dev/null @@ -1,56 +0,0 @@ -package tools; - -import java.util.Scanner; -import java.util.ArrayList; -import java.util.List; -import java.util.InputMismatchException; -import tools.HostItem; - -/** Helper to get the server list from the user -* @author Louis Royer -* @author Flavien Haas -* @author JS Auge -* @version 1.0 -*/ -public class HostList { - /** - * Let the user enter all server and puts it in a list - * @return list of servers - */ - public static List getServList() { - List serverList = new ArrayList(); - Scanner scanner = new Scanner(System.in); - String servName; - int port = 0; - do { - System.out.println("Enter hostname of next server: (or \"stop\" when finished, default: localhost)."); - servName = scanner.nextLine(); - if (servName.equals("")) { - servName = "localhost"; - } - if (!servName.equals("stop")) { - boolean err = false; - do { - System.out.println("Enter port for this server"); - try { - port = scanner.nextInt(); - scanner.nextLine(); - if (port > 65535 || port <= 0) { - err = true; - System.out.println("Port number must be in 1-65535 range. Try again."); - } else { - err = false; - } - } catch (InputMismatchException e) { - System.out.println("Invalid number. Try again."); - err = true; - } - } while (err); - serverList.add(new HostItem(servName, port)); - } - - } while (!servName.equals("stop")); - scanner.close(); - return serverList; - } -} diff --git a/src/tracker/Tracker.java b/src/tracker/Tracker.java index bb82422..8607610 100644 --- a/src/tracker/Tracker.java +++ b/src/tracker/Tracker.java @@ -3,6 +3,7 @@ import tracker.TrackerManagementTCP; import tracker.TrackerManagementUDP; import tools.Directories; import tools.Logger; +import java.util.Scanner; /** Tracker implementation * First argument of main method is port listened by the tracker, and is mandatory. @@ -24,7 +25,9 @@ public class Tracker { directories = new Directories("P2P_JAVA_PROJECT_TRACKER_" + port); logger = new Logger(directories.getDataHomeDirectory() + "tracker.log"); System.out.println("Tracker will listen on port " + port + " and write logs into " + directories.getDataHomeDirectory()); - directories.askOpenDataHomeDirectory(null); + Scanner scanner = new Scanner(System.in); + directories.askOpenDataHomeDirectory(null, scanner); + scanner.close(); } /** Main program entry point diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index 5f75aa2..c26c9c9 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -20,8 +20,8 @@ import java.util.HashMap; import protocolP2P.DiscoverRequest; import protocolP2P.DiscoverResponse; import protocolP2P.FileList; -import protocolP2P.HashRequest; import localException.InternalError; +import remoteException.EmptyDirectory; import java.net.UnknownHostException; import java.net.InetAddress; import localException.SocketClosed; @@ -204,6 +204,10 @@ public class TrackerManagementTCP implements Runnable { handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse(), host); logger.writeTCP("Received LIST RESPONSE from host " + pd.getHostItem(), LogLevel.Action); host.closeTCPSocket(); + } catch (EmptyDirectory e) { + logger.writeTCP("Empty Directory", LogLevel.Debug); + hostList.remove(host); + logger.writeTCP("Received EMPTY DIRECTORY from host " + pd.getHostItem() + ". Aborting.", LogLevel.Action); } catch (Exception e) { // remove from list because list request could not be send hostList.remove(host); @@ -245,7 +249,7 @@ public class TrackerManagementTCP implements Runnable { if (!(p instanceof DiscoverRequest)) { sendInternalError(pd); } else { - String filename = ((HashRequest)p).getFilename(); + String filename = ((DiscoverRequest)p).getFilename(); try { pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); } catch (Exception e) { diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index 3a3cbc2..4d31c2f 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -19,7 +19,6 @@ import java.util.HashMap; import protocolP2P.DiscoverRequest; import protocolP2P.DiscoverResponse; import protocolP2P.FileList; -import protocolP2P.HashRequest; import localException.InternalError; import remoteException.EmptyDirectory; import java.net.InetAddress; @@ -201,7 +200,7 @@ public class TrackerManagementUDP implements Runnable { if (!(p instanceof DiscoverRequest)) { sendInternalError(pd); } else { - String filename = ((HashRequest)p).getFilename(); + String filename = ((DiscoverRequest)p).getFilename(); try { pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); } catch (Exception e) { -- 2.30.2