Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

This will do the right thing, way way messy in the end.

  • Loading branch information...
commit 3242da87adb1ce609578161e9ae8f349683c8882 1 parent 6c65456
☁ daicoden daicoden authored

Showing 2 changed files with 204 additions and 25 deletions. Show diff stats Hide diff stats

  1. +191 19 assets/javascripts/vendor/peer.js
  2. +13 6 views/test.jade
210 assets/javascripts/vendor/peer.js
@@ -729,7 +729,7 @@ function Reliable(dc, debug) {
729 729 if (!(this instanceof Reliable)) return new Reliable(dc);
730 730 this._dc = dc;
731 731
732   - util.debug = true;
  732 + util.debug = false;
733 733
734 734 this.DATA = 1;
735 735 this.ACK = 2;
@@ -741,52 +741,136 @@ function Reliable(dc, debug) {
741 741 this.PACKET_COUNT_IN_MESSAGE_FIELD = 4;
742 742 this.PACKET_DATA_FIELD = 5;
743 743
  744 + this.PACKETS_TO_RESEND_FIELD = 3;
  745 +
744 746 // Messages sent/received so far.
745 747 // DATA
746   - // packetId: { 1, <messageId>, <messagePacketStart>, <messagePacketEnd>, <packetId>, <data> }
  748 + // packetId: { 1, <messageId>, <packetId>, <firstPacket>, <totalPacketsInMessage>, <data> }
747 749 // ACK
748   - // packetId: { 2, <packetId> }
  750 + // packetId: { 2, <messageId>, <packetId>, <numberToResend> }
749 751 this._outgoing = {};
  752 + this._ackOutgoing = {};
750 753 this._incoming = {};
751 754 // Window size.
752 755 this._window = 40;
753 756 // MTU.
754 757 this._mtu = 256;
755 758 // Max Chunk Size Without Yielding
756   - this._maxChunkSize = 10
  759 + //this._maxChunkSize = 10
757 760 // Interval for setInterval. In ms.
758 761 this._interval = 0;
  762 + this._ackInterval = 2;
  763 +
  764 + // We could be a lot smarter and calculate it but this is here for now
  765 + this._packetCountToResend = 5;
759 766
760 767 this._nextPacketId = 0;
761 768 this._nextMessageId = 0;
762 769
  770 + this._ackedPacketId = -1;
  771 + this._ackedMessageId = -1;
  772 +
  773 + this._receivedPacketId = -1;
  774 + this._receivedPacketCache = {}
  775 + this._receivedMessageId = -1;
  776 + this._resendTimeout = null;
  777 + this._resendInterval = 100;
  778 +
  779 + this._ackQueue = []
  780 + this._ackTimeout = null;
  781 +
  782 +
  783 + //hacking now
  784 + this._stuckCount = 0;
  785 +
763 786 // Outgoing message queue.
764 787 this._sendQueue = [];
765 788
766 789 this._setupDC();
767 790
768   - this._orderedDeliveryMessageId = 0;
  791 + this._active = false;
  792 +
769 793
770 794 util.log('These settings mean the client can lag behind by ' + (60*500)/(Math.pow(2,10)) + "Kb")
771 795 };
772 796
  797 +Reliable.prototype._deactivate = function() {
  798 + this._active = false;
  799 + if (this._resendTimeout) {
  800 + clearTimeout(this._resendTimeout);
  801 + this._resendTimeout = false
  802 + }
  803 +}
  804 +
  805 +Reliable.prototype._activate = function() {
  806 + this._active = true;
  807 + var self = this;
  808 + //this._resendTimeout = setTimeout(function() { self._resend() }, this._resendInterval);
  809 +}
  810 +
  811 +Reliable.prototype._resend = function() {
  812 + var queue = []
  813 + var self = this;
  814 + var message = this._outgoing[this._ackedMessageId];
  815 + var testPacket = message.packets[0];
  816 + var wantedPacketNumber = this._ackedPacketId - testPacket[this.FIRST_PACKET_ID_IN_MESSAGE_FIELD];
  817 + var totalPacketsInMessage = testPacket[this.PACKET_COUNT_IN_MESSAGE_FIELD] - wantedPacketNumber;
  818 +
  819 + var toTake = 10;
  820 + if(totalPacketsInMessage >= 0) {
  821 + var subset = message.packets.slice(wantedPacketNumber, toTake + wantedPacketNumber)
  822 + for(i in subset) {
  823 + queue.push(subset[i])
  824 + }
  825 + }
  826 +
  827 + var messageId = this._ackedMessageId;
  828 + while(queue.length < 10) {
  829 + messageId += 1
  830 +
  831 + message = this._outgoing[messageId]
  832 + if(!message) { break }
  833 +
  834 + var subset = message.packets.slice(0, 10 - queue.length)
  835 + for(i in subset) {
  836 + queue.push(subset[i])
  837 + }
  838 + }
  839 +
  840 + console.log('WeStuck?, message: ' + this._ackedMessageId + ' packet: ' + this._ackedPacketId + ' resending')
  841 + this._enqueueForDelivery(queue);
  842 +
  843 +}
  844 +
  845 +Reliable.prototype._rescheduleResend = function() {
  846 + if(this._resendTimeout) {
  847 + clearTimeout(this._resendInterval)
  848 + }
  849 +
  850 + var self = this;
  851 + //this._resendTimeout = setTimeout(function() { self._resend() }, this._resendInterval);
  852 +}
  853 +
773 854 ////////////////////////////////////////////////////////////////////////////////
774 855 // Application Synchronous Sending
775 856
776 857 // Send a message reliably.
777 858 Reliable.prototype.send = function(msg) {
  859 + if(!this._active) {
  860 + this._activate();
  861 + }
778 862 // Determine if chunking is necessary.
779 863 var payload = util.pack(msg);
780 864 var self = this;
781 865
782 866 var messageId = this._queuePackets({expectAck: true}, function(messageId, firstPacketId) {
  867 + if (util.debug) {
  868 + console.time('SendMessage:' + messageId);
  869 + }
  870 +
783 871 return self._buildPackets(payload, messageId, firstPacketId);
784 872 });
785 873
786   - if (util.debug) {
787   - console.time('SendMessage:' + messageId);
788   - }
789   -
790 874 // Send prelim window.
791 875 this._sendMessage(messageId);
792 876
@@ -799,10 +883,11 @@ Reliable.prototype.send = function(msg) {
799 883 // outgoing after delivery. This is used for resending missed packets
800 884 Reliable.prototype._queuePackets = function(opts, packetProvider) {
801 885 var messageId = this._nextMessageId;
802   - packets = packetProvider(messageId, this._nextPacketId);
  886 + var packets = packetProvider(messageId, this._nextPacketId);
803 887 this._outgoing[messageId] = {packets: packets, expectAck: (opts.expectAck || true)};
804 888 this._nextMessageId += 1;
805   - this._nextPacketId += packets[this.PACKET_COUNT_IN_MESSAGE_FIELD];
  889 + // Just use first packet for this
  890 + this._nextPacketId += packets[0][this.PACKET_COUNT_IN_MESSAGE_FIELD];
806 891
807 892 return messageId;
808 893 }
@@ -918,8 +1003,8 @@ Reliable.prototype._handleMessage = function(msg) {
918 1003 switch (msg[this.MESSAGE_TYPE_FIELD]) {
919 1004 case this.DATA:
920 1005 var messageId = msg[this.MESSAGE_ID_FIELD];
921   - var messagePacketNumber = msg[this.PACKET_ID_FIELD] -
922   - msg[this.FIRST_PACKET_ID_IN_MESSAGE_FIELD];
  1006 + var packetId = msg[this.PACKET_ID_FIELD];
  1007 + var messagePacketNumber = packetId - msg[this.FIRST_PACKET_ID_IN_MESSAGE_FIELD];
923 1008 var toReceive = this._incoming[messageId];
924 1009
925 1010 if (!toReceive) {
@@ -931,18 +1016,72 @@ Reliable.prototype._handleMessage = function(msg) {
931 1016 toReceive.packets[messagePacketNumber] = msg;
932 1017 } else{
933 1018 // Duplicate
934   - // TODO figure out what to do about this
  1019 + return;
935 1020 }
936 1021
937 1022 if (toReceive.isReceived) {
  1023 + if (util.debug) {
  1024 + console.time('ReceivedMessage:' + packetId);
  1025 + }
  1026 + console.log('received ' + packetId + ' need ' + (this._receivedPacketId + 1))
  1027 +
938 1028 this._collectDeliverableIds(messageId, function(deliveryId) {
939 1029 self._assembleAndNotify(deliveryId);
940 1030 delete self._incoming[deliveryId];
  1031 +
  1032 + if (util.debug) {
  1033 + console.timeEnd('ReceivedMessage:' + messageId);
  1034 + }
941 1035 })
942 1036 }
  1037 +
  1038 + if (this._receivedPacketId == packetId - 1 || this._receivedPacketCache[this._receivedPacketId]) {
  1039 + this._receivedPacketId += 1;
  1040 +
  1041 + while(this._receivedPacketCache[this._receivedPacketId]) {
  1042 + delete this._receivedPacketCache[this._receivedPacketId];
  1043 + this._receivedPacketId += 1;
  1044 + }
  1045 +
  1046 + this._scheduleAck(true, messageId, packetId);
  1047 + } else {
  1048 + this._receivedPacketCache[packetId] = true
  1049 + this._scheduleAck(false, messageId, packetId);
  1050 + }
  1051 +
943 1052 break;
944 1053 case this.ACK:
945   - TODO
  1054 + var receivedMsg = msg[this.MESSAGE_ID_FIELD];
  1055 + var receivedPacket = msg[this.PACKET_ID_FIELD];
  1056 + var packetsToResend = msg[this.PACKETS_TO_RESEND_FIELD];
  1057 +
  1058 + if (receivedPacket < this._ackedPacketId) {
  1059 + return; //Old Ack
  1060 + } else if (this._ackedPacketId == receivedPacket) {
  1061 + // Might indicate the client missed a packet, scheduleResend
  1062 + this._stuckCount += 1;
  1063 + //TODO: Make this on a timeout when early errors break
  1064 + if(this._stuckCount >= 20) {
  1065 + this._resend()
  1066 + this._stuckCount = 0
  1067 + }
  1068 + } else {
  1069 + this._stuckCount = 0;
  1070 + }
  1071 + this._ackedPacketId = receivedPacket;
  1072 +
  1073 + // There's a bug here - if we stop sending data we will never delete it from _outgoing...
  1074 + // should fix this by adding totalPacketCount to the ack
  1075 + while(this._ackedMessageId < receivedMsg - 1) {
  1076 + delete this._outgoing[this._ackedMessageId];
  1077 + this._ackedMessageId += 1;
  1078 + }
  1079 +
  1080 + if (this.receivedPacket == this.nextPacketId) {
  1081 + // We have caught up
  1082 + this._deactivate();
  1083 + }
  1084 +
946 1085 break;
947 1086 default:
948 1087 throw "Unknown Message Type: ", msg[this.MESSAGE_TYPE_FIELD]
@@ -960,15 +1099,48 @@ Reliable.prototype._newReceivable = function(packet) {
960 1099 }
961 1100 }
962 1101
  1102 +//TODO: these +1 are here to keeep symetry with the receivedPacketId for acks.
  1103 +// We can definitly do this better
963 1104 Reliable.prototype._collectDeliverableIds = function(receivedMessageId, deliverer) {
964   - while (this._incoming[this._orderedDeliveryMessageId] &&
965   - this._incoming[this._orderedDeliveryMessageId].isReceived()) {
  1105 + while (this._incoming[this._receivedMessageId + 1] &&
  1106 + this._incoming[this._receivedMessageId + 1].isReceived()) {
966 1107 //TODO: Check the ordered preference from options
967   - deliverer(this._orderedDeliveryMessageId);
968   - this._orderedDeliveryMessageId += 1;
  1108 + deliverer(this._receivedMessageId + 1);
  1109 + this._receivedMessageId += 1;
  1110 + console.log("Processing message " + (this._receivedMessageId) + ' need packet ' + (this._receivedPacketId + 1))
969 1111 }
970 1112 }
971 1113
  1114 +Reliable.prototype._scheduleAck = function(success, messageId, packetId) {
  1115 + var self = this;
  1116 +// if (success) {
  1117 + // If are always wanting the next packet, but have the message we need
  1118 + this._ackQueue.push([this.ACK, this._receivedMessageId, this._receivedPacketId + 1, 0]);
  1119 +// } else {
  1120 +// this._ackQueue.push([this.ACK, messageId, packetId, this._packetCountToResend]);
  1121 +// }
  1122 +
  1123 + if (!this._ackTimeout) {
  1124 + this._ackTimeout = setTimeout(function() {
  1125 + var newQueue = [];
  1126 + for (i in self._ackQueue) {
  1127 + if (self._ackQueue[i][self.PACKET_ID_FIELD] < self.receivedPacketId) {
  1128 + newQueue.push(self._ackQueue[i]);
  1129 + } else {
  1130 + newQueue.push([self.ACK, self._receivedMessageId, self._receivedPacketId, 0]);
  1131 + }
  1132 + }
  1133 +
  1134 + for(var i = 0; i < newQueue.length; i += self._window) {
  1135 + self._enqueueForDelivery(newQueue.slice(i, i + self._window));
  1136 + }
  1137 +
  1138 + delete self._ackQueue;
  1139 + self._ackQueue = [];
  1140 + self._ackTimeout = null;
  1141 + }, this._ackInterval)
  1142 + }
  1143 +}
972 1144
973 1145 // Sends ACK N, expecting Nth blob chunk for message ID.
974 1146 Reliable.prototype._ack = function(id) {
19 views/test.jade
@@ -4,14 +4,21 @@ block script
4 4 script
5 5 S.pair(1, function(socket, master) {
6 6 conn = socket.conn
7   - conn.on('data', function(data) { console.log(data) });
  7 + count = 0
  8 + conn.on('data', function(data) {
  9 + if(data.n != count) { throw "Holy SHit" }
  10 + count += 1
  11 + console.log(data)
  12 + });
8 13 if (master) {
9   - for (var i = 0; i < 100; i++)
  14 + //for (var i = 0; i < 1; i++)
  15 + // conn.send({ n: i, payload: Array(250000) });
  16 + // for (var i = 0; i < 2; i++)
  17 + // conn.send({ n: i, payload: Array(250000) });
  18 + console.time("Here we go")
  19 + for (var i = 0; i < 1000; i++)
10 20 conn.send({ n: i, payload: Array(1) });
11   - for (var i = 0; i < 2; i++)
12   - conn.send({ n: i, payload: Array(250000) });
13   - for (var i = 0; i < 100; i++)
14   - conn.send({ n: i, payload: Array(2) });
  21 + console.timeEnd("Here we go")
15 22 }
16 23 });
17 24

0 comments on commit 3242da8

Please sign in to comment.
Something went wrong with that request. Please try again.