GiveFile.vala 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. using LibPeer.Networks.Simulation;
  2. using LibPeer.Protocols.Mx2;
  3. using LibPeer.Protocols.Stp;
  4. using LibPeer.Protocols.Stp.Streams;
  5. using LibPeer.Networks;
  6. using Gee;
  7. namespace GiveFile {
  8. class FileGiver : Object {
  9. private Muxer muxer;
  10. private Network network;
  11. private Instance instance;
  12. private StreamTransmissionProtocol transport;
  13. private string path;
  14. private HashSet<InstanceReference> peers = new HashSet<InstanceReference>(r => r.hash(), (a, b) => a.compare(b) == 0);
  15. private MainLoop loop;
  16. public FileGiver(Conduit conduit, string file_path) {
  17. loop = new MainLoop();
  18. muxer = new Muxer ();
  19. network = conduit.get_interface (0, 0, 0.2f);
  20. network.bring_up ();
  21. muxer.register_network (network);
  22. instance = muxer.create_instance ("GiveFile");
  23. transport = new StreamTransmissionProtocol (muxer, instance);
  24. path = file_path;
  25. instance.incoming_greeting.connect((origin) => rx_greeting(origin));
  26. network.incoming_advertisment.connect(rx_advertisement);
  27. transport.incoming_stream.connect(incoming);
  28. network.advertise(instance.reference);
  29. print(@"File giver created for '$path'\n");
  30. }
  31. void rx_advertisement(Advertisement adv) {
  32. print("rx_advertisement\n");
  33. if(!peers.contains(adv.instance_reference)) {
  34. muxer.inquire(instance, adv.instance_reference, new PeerInfo[] {adv.peer_info});
  35. }
  36. }
  37. void rx_greeting(InstanceReference origin) {
  38. print("rx_greeting\n");
  39. peers.add(origin);
  40. transport.initialise_stream(origin).established.connect(make_request);
  41. }
  42. void make_request(StpOutputStream stream) {
  43. print("make_request\n");
  44. stream.reply.connect(reply);
  45. print("Asking peer to gib file\n");
  46. stream.write({'G', 'i', 'b', ' ', 'f', 'i', 'l', 'e'});
  47. }
  48. void reply(StpInputStream stream) {
  49. print("reply\n");
  50. print("Peer gibs file...\n");
  51. var reader = new DataInputStream(stream);
  52. var size = reader.read_uint32();
  53. var file = File.new_for_path(Uuid.string_random());
  54. var file_stream = file.create(FileCreateFlags.PRIVATE);
  55. uint8[] hunk = new uint8[size/100];
  56. int hunks_received = 0;
  57. while(hunks_received < size/100) {
  58. reader.read(hunk);
  59. file_stream.write(hunk);
  60. hunks_received++;
  61. print(@"rx file $(hunks_received)% complete\n");
  62. }
  63. if(size%100 != 0) {
  64. hunk = new uint8[size%100];
  65. reader.read(hunk);
  66. file_stream.write(hunk);
  67. }
  68. file_stream.flush();
  69. file_stream.close();
  70. print("Done\n");
  71. }
  72. void incoming(StpInputStream stream) {
  73. print("incoming\n");
  74. print("I have a new stream\n");
  75. var magic = new uint8[8];
  76. uint8[] expected_magic = {'G', 'i', 'b', ' ', 'f', 'i', 'l', 'e'};
  77. stream.read(magic);
  78. for(var i = 0; i < 8; i++) {
  79. if(expected_magic[i] != magic[i]) {
  80. print("Peer did not ask me to gib file\n");
  81. return;
  82. }
  83. }
  84. print("Peer asked to gib file\n");
  85. transport.initialise_stream(stream.origin, stream.session_id).established.connect(send_file);
  86. }
  87. void send_file(StpOutputStream stream) {
  88. print("send_file\n");
  89. print("Sending my file\n");
  90. var file = File.new_for_path(path);
  91. var file_stream = file.read();
  92. file_stream.seek(0, SeekType.END);
  93. var size = file_stream.tell();
  94. file_stream.seek(0, SeekType.SET);
  95. var writer = new DataOutputStream(stream);
  96. writer.put_uint32((uint32)size);
  97. var buffer = new uint8[size];
  98. file_stream.read(buffer);
  99. stream.write(buffer);
  100. file_stream.close();
  101. print("My purpose is complete!\n");
  102. }
  103. }
  104. }