On Sat, Dec 6, 2008 at 4:14 AM,  <toad at freenetproject.org> wrote:
> Author: toad
> Date: 2008-12-05 20:14:58 +0000 (Fri, 05 Dec 2008)
> New Revision: 24070
>
> Modified:
>   trunk/freenet/src/freenet/node/FNPPacketMangler.java
>   trunk/freenet/src/freenet/node/PacketTracker.java
>   trunk/freenet/src/freenet/node/PeerNode.java
>   trunk/freenet/src/freenet/support/Fields.java
> Log:
> Neg type 4: negotiate during JFK(3) and JFK(4) whether to reuse the old 
> PacketTracker.

Can we remove type 3 now? All nodes support type 2.

> Modified: trunk/freenet/src/freenet/node/FNPPacketMangler.java
> ===================================================================
> --- trunk/freenet/src/freenet/node/FNPPacketMangler.java        2008-12-05 
> 16:50:17 UTC (rev 24069)
> +++ trunk/freenet/src/freenet/node/FNPPacketMangler.java        2008-12-05 
> 20:14:58 UTC (rev 24070)
> @@ -598,7 +598,7 @@
>                        Logger.error(this, "Decrypted auth packet but invalid 
> version: "+version);
>                        return;
>                }
> -               if(!(negType == 2 || negType == 3)) {
> +               if(!(negType == 2 || negType == 3 || negType == 4)) {
>                        Logger.error(this, "Unknown neg type: "+negType);
>                        return;
>                }
> @@ -663,7 +663,9 @@
>                } else if (negType == 1) {
>                        Logger.error(this, "Old StationToStation (negType 1) 
> not supported.");
>                        return;
> -               } else if (negType==2 || negType == 3){ // negType == 3 => no 
> new PacketTracker when rekeying
> +               } else if (negType==2 || negType == 3 || negType == 4){
> +                       // negType == 3 => no new PacketTracker when rekeying
> +                       // negType == 4 => negotiate whether to use a new 
> PacketTracker when rekeying
>                        /*
>                         * We implement Just Fast Keying key management 
> protocol with active identity protection
>                         * for the initiator and no identity protection for 
> the responder
> @@ -1045,6 +1047,7 @@
>                        (c.getBlockSize() >> 3) + // IV
>                        HASH_LENGTH + // it's at least a signature
>                        8 +           // a bootid
> +                       (negType >= 4 ? 8 : 0) + // packet tracker ID
>                        1;            // znoderefI* is at least 1 byte long
>
>                if(payload.length < expectedLength + 3) {
> @@ -1148,9 +1151,20 @@
>                decypheredPayloadOffset += Node.SIGNATURE_PARAMETER_LENGTH;
>                byte[] data = new byte[decypheredPayload.length - 
> decypheredPayloadOffset];
>                System.arraycopy(decypheredPayload, decypheredPayloadOffset, 
> data, 0, decypheredPayload.length - decypheredPayloadOffset);
> -               long bootID = Fields.bytesToLong(data);
> -               byte[] hisRef = new byte[data.length - 8];
> -               System.arraycopy(data, 8, hisRef, 0, hisRef.length);
> +               int ptr = 0;
> +               long trackerID;
> +               if(negType >= 4) {
> +                       trackerID = Fields.bytesToLong(data, ptr);
> +                       if(trackerID < 0) trackerID = -1;
> +                       ptr += 8;
> +               } else {
> +                       if(negType == 3) trackerID = -2; // emulate negtype = 
> 3 behaviour
> +                       else trackerID = -1;
> +               }
> +               long bootID = Fields.bytesToLong(data, ptr);
> +               ptr += 8;
> +               byte[] hisRef = new byte[data.length - ptr];
> +               System.arraycopy(data, ptr, hisRef, 0, hisRef.length);
>
>                // construct the peernode
>                if(unknownInitiator) {
> @@ -1175,12 +1189,10 @@
>                // At this point we know it's from the peer, so we can report 
> a packet received.
>                pn.receivedPacket(true, false);
>
> -               // Send reply
> -               sendJFKMessage4(1, negType, 3, nonceInitiator, 
> nonceResponder,initiatorExponential, responderExponential,
> -                               c, Ke, Ka, authenticator, hisRef, pn, 
> replyTo, unknownInitiator, setupType);
> +               BlockCipher cs = null;
> +               try { cs = new Rijndael(256, 256); } catch 
> (UnsupportedCipherException e) {}
> +               cs.initialize(Ks);
>
> -               c.initialize(Ks);
> -
>                // Promote if necessary
>                boolean dontWant = false;
>                if(oldOpennetPeer) {
> @@ -1196,13 +1208,21 @@
>                        // wantPeer will call node.peers.addPeer(), we don't 
> have to.
>                }
>
> -               if(pn.completedHandshake(bootID, hisRef, 0, hisRef.length, c, 
> Ks, replyTo, true, negType)) {
> +               long newTrackerID = pn.completedHandshake(bootID, hisRef, 0, 
> hisRef.length, cs, Ks, replyTo, true, negType, trackerID, false, false);
> +
> +               if(newTrackerID > 0) {
> +
> +                       // Send reply
> +                       sendJFKMessage4(1, negType, 3, nonceInitiator, 
> nonceResponder,initiatorExponential, responderExponential,
> +                                       c, Ke, Ka, authenticator, hisRef, pn, 
> replyTo, unknownInitiator, setupType, newTrackerID, newTrackerID == 
> trackerID);
> +
>                        if(dontWant)
> -                               node.peers.disconnect(pn, true, false);
> +                               node.peers.disconnect(pn, true, false); // 
> Let it connect then tell it to remove it.
>                        else
>                                pn.maybeSendInitialMessages();
>                } else {
>                        Logger.error(this, "Handshake failure! with 
> "+pn.getPeer());
> +                       // Don't send the JFK(4). We have not successfully 
> connected.
>                }
>
>                final long t2=System.currentTimeMillis();
> @@ -1279,6 +1299,7 @@
>                        HASH_LENGTH + // HMAC of the cyphertext
>                        (c.getBlockSize() >> 3) + // IV
>                        Node.SIGNATURE_PARAMETER_LENGTH * 2 + // the signature
> +                       (negType >= 4 ? 9 : 0) + // ID of packet tracker, 
> plus boolean byte
>                        8+ // bootID
>                        1; // znoderefR
>
> @@ -1344,25 +1365,39 @@
>                decypheredPayloadOffset += Node.SIGNATURE_PARAMETER_LENGTH;
>                byte[] data = new byte[decypheredPayload.length - 
> decypheredPayloadOffset];
>                System.arraycopy(decypheredPayload, decypheredPayloadOffset, 
> data, 0, decypheredPayload.length - decypheredPayloadOffset);
> -               long bootID = Fields.bytesToLong(data);
> -               if(data.length - 8 < 0) {
> +               int ptr = 0;
> +               long trackerID;
> +               boolean reusedTracker;
> +               if(negType >= 4) {
> +                       trackerID = Fields.bytesToLong(data, ptr);
> +                       ptr += 8;
> +                       reusedTracker = data[ptr++] != 0;
> +               } else {
> +                       if(negType == 3) trackerID = -2;
> +                       else trackerID = -1;
> +                       reusedTracker = false;
> +               }
> +               long bootID = Fields.bytesToLong(data, ptr);
> +               ptr += 8;
> +               if(data.length - ptr < 0) {
>                        Logger.error(this, "No space for hisRef: 
> data.length="+data.length+" 
> myRef.length="+(pn.jfkMyRef==null?0:pn.jfkMyRef.length)+" orig data length 
> "+(payload.length-inputOffset));
>                        return true;
>                }
> -               byte[] hisRef = new byte[data.length - 8];
> -               System.arraycopy(data, 8, hisRef, 0, hisRef.length);
> +               byte[] hisRef = new byte[data.length - ptr];
> +               System.arraycopy(data, ptr, hisRef, 0, hisRef.length);
>
>                // verify the signature
>                DSASignature remoteSignature = new DSASignature(new 
> NativeBigInteger(1,r), new NativeBigInteger(1,s));
> -               byte[] locallyGeneratedText = new byte[NONCE_SIZE * 2 + 
> DiffieHellman.modulusLengthInBytes() * 2 + crypto.myIdentity.length + 8 
> /*bootID*/ + hisRef.length + pn.jfkMyRef.length];
> +               int dataLen = hisRef.length + 8 + (negType >= 4 ? 9 : 0);
> +               byte[] locallyGeneratedText = new byte[NONCE_SIZE * 2 + 
> DiffieHellman.modulusLengthInBytes() * 2 + crypto.myIdentity.length + dataLen 
> + pn.jfkMyRef.length];
>                int bufferOffset = NONCE_SIZE * 2 + 
> DiffieHellman.modulusLengthInBytes()*2;
>                System.arraycopy(jfkBuffer, 0, locallyGeneratedText, 0, 
> bufferOffset);
>                byte[] identity = crypto.getIdentity(unknownInitiator);
>                System.arraycopy(identity, 0, locallyGeneratedText, 
> bufferOffset, identity.length);
>                bufferOffset += identity.length;
>                // bootID
> -               System.arraycopy(data, 0, locallyGeneratedText, bufferOffset, 
> hisRef.length + 8);
> -               bufferOffset += hisRef.length + 8;
> +               System.arraycopy(data, 0, locallyGeneratedText, bufferOffset, 
> dataLen);
> +               bufferOffset += dataLen;
>                System.arraycopy(pn.jfkMyRef, 0, locallyGeneratedText, 
> bufferOffset, pn.jfkMyRef.length);
>                byte[] messageHash = SHA256.digest(locallyGeneratedText);
>                if(!DSA.verify(pn.peerPubKey, remoteSignature, new 
> NativeBigInteger(1, messageHash), false)) {
> @@ -1391,7 +1426,7 @@
>
>                // We change the key
>                c.initialize(pn.jfkKs);
> -               if(pn.completedHandshake(bootID, data, 8, data.length - 8, c, 
> pn.jfkKs, replyTo, false, negType)) {
> +               if(pn.completedHandshake(bootID, hisRef, 0, hisRef.length, c, 
> pn.jfkKs, replyTo, false, negType, trackerID, true, reusedTracker) >= 0) {
>                        if(dontWant)
>                                node.peers.disconnect(pn, true, false);
>                        else
> @@ -1442,9 +1477,19 @@
>                if(ctx == null) return;
>                byte[] ourExponential = 
> stripBigIntegerToNetworkFormat(ctx.myExponential);
>                pn.jfkMyRef = unknownInitiator ? 
> crypto.myCompressedHeavySetupRef() : crypto.myCompressedSetupRef();
> -               byte[] data = new byte[8 + pn.jfkMyRef.length];
> -               System.arraycopy(Fields.longToBytes(node.bootID), 0, data, 0, 
> 8);
> -               System.arraycopy(pn.jfkMyRef, 0, data, 8, pn.jfkMyRef.length);
> +               byte[] data = new byte[(negType >= 4 ? 8 : 0) + 8 + 
> pn.jfkMyRef.length];
> +               int ptr = 0;
> +               if(negType >= 4) {
> +                       long trackerID;
> +                       if(pn == null)
> +                               trackerID = -1;
> +                       else trackerID = pn.getReusableTrackerID();
> +                       System.arraycopy(Fields.longToBytes(trackerID), 0, 
> data, ptr, 8);
> +                       ptr += 8;
> +               }
> +               System.arraycopy(Fields.longToBytes(node.bootID), 0, data, 
> ptr, 8);
> +               ptr += 8;
> +               System.arraycopy(pn.jfkMyRef, 0, data, ptr, 
> pn.jfkMyRef.length);
>                final byte[] message3 = new byte[NONCE_SIZE*2 + // nI, nR
>                                           
> DiffieHellman.modulusLengthInBytes()*2 + // g^i, g^r
>                                           HASH_LENGTH + // authenticator
> @@ -1554,7 +1599,7 @@
>         * @param pn The PeerNode to encrypt the auth packet to. Cannot be 
> null, because even in anonymous initiator,
>         * we will have created one before calling this method.
>         */
> -       private void sendJFKMessage4(int version,int negType,int phase,byte[] 
> nonceInitiator,byte[] nonceResponder,byte[] initiatorExponential,byte[] 
> responderExponential, BlockCipher c, byte[] Ke, byte[] Ka, byte[] 
> authenticator, byte[] hisRef, PeerNode pn, Peer replyTo, boolean 
> unknownInitiator, int setupType)
> +       private void sendJFKMessage4(int version,int negType,int phase,byte[] 
> nonceInitiator,byte[] nonceResponder,byte[] initiatorExponential,byte[] 
> responderExponential, BlockCipher c, byte[] Ke, byte[] Ka, byte[] 
> authenticator, byte[] hisRef, PeerNode pn, Peer replyTo, boolean 
> unknownInitiator, int setupType, long newTrackerID, boolean 
> sameAsOldTrackerID)
>        {
>                if(logMINOR)
>                        Logger.minor(this, "Sending a JFK(4) message to 
> "+pn.getPeer());
> @@ -1563,11 +1608,20 @@
>                NativeBigInteger _initiatorExponential = new 
> NativeBigInteger(1,initiatorExponential);
>
>                byte[] myRef = crypto.myCompressedSetupRef();
> -               byte[] data = new byte[8 + myRef.length + hisRef.length];
> -               System.arraycopy(Fields.longToBytes(node.bootID), 0, data, 0, 
> 8);
> -               System.arraycopy(myRef, 0, data, 8, myRef.length);
> -               System.arraycopy(hisRef, 0, data, 8 + myRef.length, 
> hisRef.length);
> +               byte[] data = new byte[(negType >= 4 ? 9 : 0) + 8 + 
> myRef.length + hisRef.length];
> +               int ptr = 0;
> +               if(negType >= 4) {
> +                       System.arraycopy(Fields.longToBytes(newTrackerID), 0, 
> data, ptr, 8);
> +                       ptr += 8;
> +                       data[ptr++] = (byte) (sameAsOldTrackerID ? 1 : 0);
> +               }
>
> +               System.arraycopy(Fields.longToBytes(node.bootID), 0, data, 
> ptr, 8);
> +               ptr += 8;
> +               System.arraycopy(myRef, 0, data, ptr, myRef.length);
> +               ptr += myRef.length;
> +               System.arraycopy(hisRef, 0, data, ptr, hisRef.length);
> +
>                byte[] params = assembleDHParams(nonceInitiator, 
> nonceResponder, _initiatorExponential, _responderExponential, pn.identity, 
> data);
>                byte[] messageHash = SHA256.digest(params);
>                if(logMINOR)
> @@ -2816,7 +2870,7 @@
>        }
>
>        public int[] supportedNegTypes() {
> -               return new int[] { 2, 3 };
> +               return new int[] { 2, 3, 4 };
>        }
>
>        public int fullHeadersLengthOneMessage() {
>
> Modified: trunk/freenet/src/freenet/node/PacketTracker.java
> ===================================================================
> --- trunk/freenet/src/freenet/node/PacketTracker.java   2008-12-05 16:50:17 
> UTC (rev 24069)
> +++ trunk/freenet/src/freenet/node/PacketTracker.java   2008-12-05 20:14:58 
> UTC (rev 24070)
> @@ -78,9 +78,16 @@
>        final long createdTime;
>        /** The time at which we last successfully decoded a packet. */
>        private long timeLastDecodedPacket;
> +       /** Tracker ID. Must be positive. */
> +       final long trackerID;
>
>        /** Everything is clear to start with */
>        PacketTracker(PeerNode pn) {
> +               this(pn, pn.node.random.nextLong() & Long.MAX_VALUE);
> +       }
> +
> +       PacketTracker(PeerNode pn, long tid) {
> +               trackerID = tid;
>                this.pn = pn;
>                ackQueue = new LinkedList<QueuedAck>();
>                forgottenQueue = new LinkedList<QueuedForgotten>();
>
> Modified: trunk/freenet/src/freenet/node/PeerNode.java
> ===================================================================
> --- trunk/freenet/src/freenet/node/PeerNode.java        2008-12-05 16:50:17 
> UTC (rev 24069)
> +++ trunk/freenet/src/freenet/node/PeerNode.java        2008-12-05 20:14:58 
> UTC (rev 24070)
> @@ -1812,11 +1812,21 @@
>        * @param length Number of bytes to read.
>        * @param encKey The new session key.
>        * @param replyTo The IP the handshake came in on.
> -       * @return True unless we rejected the handshake, or it failed to 
> parse.
> +       * @param trackerID The tracker ID proposed by the other side. If -1, 
> create a new tracker. If -2,
> +       * reuse the old tracker if possible. If any other value, check 
> whether we have it, and if we do,
> +       * return that, otherwise return the ID of the new tracker.
> +       * @param isJFK4 If true, we are processing a JFK(4) and must respect 
> the tracker ID chosen by the
> +       * responder. If false, we are processing a JFK(3) and we can either 
> reuse the suggested tracker ID,
> +       * which the other side is able to reuse, or we can create a new 
> tracker ID.
> +       * @param jfk4SameAsOld If true, the responder chose to use the 
> tracker ID that we provided. If
> +       * we don't have it now the connection fails.
> +       * @return The ID of the new PacketTracker. If this is different to 
> the passed-in trackerID, then
> +       * it's a new tracker. -1 to indicate failure.
>        */
> -       public boolean completedHandshake(long thisBootID, byte[] data, int 
> offset, int length, BlockCipher encCipher, byte[] encKey, Peer replyTo, 
> boolean unverified, int negType) {
> +       public long completedHandshake(long thisBootID, byte[] data, int 
> offset, int length, BlockCipher encCipher, byte[] encKey, Peer replyTo, 
> boolean unverified, int negType, long trackerID, boolean isJFK4, boolean 
> jfk4SameAsOld) {
>                logMINOR = Logger.shouldLog(Logger.MINOR, PeerNode.class);
>                long now = System.currentTimeMillis();
> +               if(logMINOR) Logger.minor(this, "Tracker ID "+trackerID+" 
> isJFK4="+isJFK4+" jfk4SameAsOld="+jfk4SameAsOld);
>
>                // Update sendHandshakeTime; don't send another handshake for 
> a while.
>                // If unverified, "a while" determines the timeout; if not, 
> it's just good practice to avoid a race below.
> @@ -1833,7 +1843,7 @@
>                        }
>                        Logger.error(this, "Failed to parse new noderef for " 
> + this + ": " + e1, e1);
>                        node.peers.disconnected(this);
> -                       return false;
> +                       return -1;
>                }
>                boolean routable = true;
>                boolean newer = false;
> @@ -1869,6 +1879,7 @@
>                KeyTracker prev = null;
>                KeyTracker newTracker;
>                MessageItem[] messagesTellDisconnected = null;
> +               PacketTracker packets = null;
>                synchronized(this) {
>                        handshakeCount = 0;
>                        bogusNoderef = false;
> @@ -1894,11 +1905,52 @@
>                        } else if(bootIDChanged && logMINOR)
>                                Logger.minor(this, "Changed boot ID from " + 
> bootID + " to " + thisBootID + " for " + getPeer());
>                        this.bootID = thisBootID;
> -                       PacketTracker packets;
>                        boolean newPacketTracker = false;
> -                       if(bootIDChanged) {
> +                       if(currentTracker != null && 
> currentTracker.packets.trackerID == trackerID && 
> !currentTracker.packets.isDeprecated()) {
> +                               if(isJFK4 && !jfk4SameAsOld)
> +                                       Logger.error(this, "In JFK(4), found 
> tracker ID "+trackerID+" but other side says is new! for "+this);
> +                               packets = currentTracker.packets;
> +                               if(logMINOR) Logger.minor(this, "Re-using 
> packet tracker ID "+trackerID+" on "+this+" from current "+currentTracker);
> +                       } else if(previousTracker != null && 
> previousTracker.packets.trackerID == trackerID && 
> !previousTracker.packets.isDeprecated()) {
> +                               if(isJFK4 && !jfk4SameAsOld)
> +                                       Logger.error(this, "In JFK(4), found 
> tracker ID "+trackerID+" but other side says is new! for "+this);
> +                               packets = previousTracker.packets;
> +                               if(logMINOR) Logger.minor(this, "Re-using 
> packet tracker ID "+trackerID+" on "+this+" from prev "+previousTracker);
> +                       } else if(isJFK4 && jfk4SameAsOld) {
> +                               isConnected = false;
> +                               Logger.error(this, "Can't reuse old tracker 
> ID "+trackerID+" as instructed - disconnecting");
> +                               return -1;
> +                       } else if(trackerID == -1) {
> +                               // Create a new tracker unconditionally
>                                packets = new PacketTracker(this);
>                                newPacketTracker = true;
> +                               if(logMINOR) Logger.minor(this, "Creating new 
> PacketTracker as instructed for "+this);
> +                       } else if(trackerID == -2 && !bootIDChanged) {
> +                               // Reuse if not deprecated and not boot ID 
> changed
> +                               if(currentTracker != null && 
> !currentTracker.packets.isDeprecated() && negType >= 3) {
> +                                       packets = currentTracker.packets;
> +                                       if(logMINOR) Logger.minor(this, 
> "Re-using packet tracker (not given an ID): "+packets.trackerID+" on "+this+" 
> from current "+currentTracker);
> +                               } else if(previousTracker != null && 
> !previousTracker.packets.isDeprecated() && negType >= 3) {
> +                                       packets = previousTracker.packets;
> +                                       if(logMINOR) Logger.minor(this, 
> "Re-using packet tracker (not given an ID): "+packets.trackerID+" on "+this+" 
> from prev "+previousTracker);
> +                               } else {
> +                                       packets = new PacketTracker(this);
> +                                       newPacketTracker = true;
> +                                       if(logMINOR) Logger.minor(this, 
> "Cannot reuse trackers (not given an ID) on "+this);
> +                               }
> +                       } else {
> +                               if(isJFK4 && negType >= 4 && trackerID < 0)
> +                                       Logger.error(this, "JFK(4) packet 
> with neg type "+negType+" has negative tracker ID: "+trackerID);
> +
> +                               if(isJFK4/* && !jfk4SameAsOld implied */ && 
> trackerID >= 0) {
> +                                       packets = new PacketTracker(this, 
> trackerID);
> +                               } else
> +                                       packets = new PacketTracker(this);
> +                               newPacketTracker = true;
> +                               if(logMINOR) Logger.minor(this, "Creating new 
> tracker (last resort) on "+this);
> +                       }
> +                       if(bootIDChanged) {
> +                               newPacketTracker = true;
>                                oldPrev = previousTracker;
>                                oldCur = currentTracker;
>                                previousTracker = null;
> @@ -1910,14 +1962,6 @@
>                                this.offeredMainJarVersion = 0;
>                        } else {
>                                // else it's a rekey
> -                               if(currentTracker != null && 
> !currentTracker.packets.isDeprecated() && negType >= 3)
> -                                       packets = currentTracker.packets;
> -                               else if(previousTracker != null && 
> !previousTracker.packets.isDeprecated() && negType >= 3)
> -                                       packets = previousTracker.packets;
> -                               else {
> -                                       packets = new PacketTracker(this);
> -                                       newPacketTracker = true;
> -                               }
>                        }
>                        newTracker = new KeyTracker(this, packets, encCipher, 
> encKey);
>                        if(logMINOR) Logger.minor(this, "New key tracker in 
> completedHandshake: "+newTracker+" for "+shortToString()+" neg type 
> "+negType+" new packet tracker: "+newPacketTracker);
> @@ -1990,7 +2034,7 @@
>                        onConnect();
>                }
>
> -               return true;
> +               return packets.trackerID;
>        }
>
>        /**
> @@ -4201,4 +4245,17 @@
>
>                return false;
>        }
> +
> +       /**
> +        * @return The ID of a reusable PacketTracker if there is one, 
> otherwise -1.
> +        */
> +       public long getReusableTrackerID() {
> +               KeyTracker cur;
> +               synchronized(this) {
> +                       cur = currentTracker;
> +               }
> +               if(cur == null) return -1;
> +               if(cur.packets.isDeprecated()) return -1;
> +               return cur.packets.trackerID;
> +       }
>  }
>
> Modified: trunk/freenet/src/freenet/support/Fields.java
> ===================================================================
> --- trunk/freenet/src/freenet/support/Fields.java       2008-12-05 16:50:17 
> UTC (rev 24069)
> +++ trunk/freenet/src/freenet/support/Fields.java       2008-12-05 20:14:58 
> UTC (rev 24070)
> @@ -502,11 +502,18 @@
>         * Convert an array of bytes to a single long.
>         */
>        public static long bytesToLong(byte[] buf) {
> -               if(buf.length < 8)
> +               return bytesToLong(buf, 0);
> +       }
> +
> +       /**
> +        * Convert an array of bytes to a single long.
> +        */
> +       public static long bytesToLong(byte[] buf, int offset) {
> +               if(buf.length < 8 + offset)
>                        throw new IllegalArgumentException();
>                long x = 0;
>                for(int j = 7; j >= 0; j--) {
> -                       long y = (buf[j] & 0xff);
> +                       long y = (buf[j + offset] & 0xff);
>                        x = (x << 8) | y;
>                }
>                return x;
>
> _______________________________________________
> cvs mailing list
> cvs at freenetproject.org
> http://emu.freenetproject.org/cgi-bin/mailman/listinfo/cvs
>

Reply via email to