Example #1
0
func (r *Reader) ReadOperations(ops chan rsync.Operation, hashOps chan rsync.Operation) error {
	if r.t != TypeDelta {
		// This is a program structure issue, so panic.
		panic(ErrInvalidCall)
	}

	var v uint64
	var n, at, dataLen int

	reader := sbuffer.NewBuffer(r.body, 32*1024)

	loop := true
	for loop {
		buff, err := reader.Next(10)
		if len(buff) == 0 {
			return nil
		}
		if err != nil {
			if err != io.EOF {
				return err
			}
			loop = false
		}

		op := rsync.Operation{
			Type: rsync.OpType(buff[0]),
		}

		at = 1
		switch op.Type {
		case rsync.OpBlock:
			v, n = binary.Uvarint(buff[at:])
			if n <= 0 {
				panic(ErrBadVarintRead)
			}
			at += n
			op.BlockIndex = v
			reader.Used(at)
		case rsync.OpBlockRange:
			v, n = binary.Uvarint(buff[at:])
			if n <= 0 {
				panic(ErrBadVarintRead)
			}
			at += n
			op.BlockIndex = v

			v, n = binary.Uvarint(buff[at:])
			if n <= 0 {
				panic(ErrBadVarintRead)
			}
			at += n
			op.BlockIndexEnd = v
			reader.Used(at)
		case rsync.OpHash:
			fallthrough
		case rsync.OpData:
			v, n = binary.Uvarint(buff[at:])
			if n <= 0 {
				panic(ErrBadVarintRead)
			}
			at += n
			dataLen = int(v)
			if dataLen > maxDataLength {
				err = ErrDataTooLong(dataLen)
				panic(err)
			}
			reader.Used(at)

			buff, err := reader.Next(dataLen)
			if err != nil {
				if err != io.EOF {
					return err
				}
				loop = false
			}
			op.Data = make([]byte, dataLen)
			copy(op.Data, buff[:dataLen])

			reader.Used(dataLen)
		default:
			panic("Unreachable.")
		}

		if op.Type == rsync.OpHash {
			hashOps <- op
		} else {
			ops <- op
		}
	}

	return nil
}
Example #2
0
func (r *Reader) ReadAllSignatures() ([]rsync.BlockHash, error) {
	if r.t != TypeSignature {
		// This is a program structure issue, so panic.
		panic(ErrInvalidCall)
	}

	bb := make([]rsync.BlockHash, 0, 10)

	// Approx size of header, which uses varint encoding.
	leaveTail := 24

	var v uint64
	var n, at, hashLen int

	reader := sbuffer.NewBuffer(r.body, 32*1024)

	loop := true
	for loop {
		buff, err := reader.Next(leaveTail)
		if err != nil {
			if err != io.EOF {
				return nil, err
			}
			loop = false
		}
		if len(buff) == 0 {
			break
		}

		v, n = binary.Uvarint(buff)
		if n <= 0 {
			panic(ErrBadVarintRead)
		}
		at = n

		block := rsync.BlockHash{
			Index:    v,
			WeakHash: binary.BigEndian.Uint32(buff[at:]),
		}
		at += 4
		v, n = binary.Uvarint(buff[at:])
		if n <= 0 {
			panic(ErrBadVarintRead)
		}
		at += n

		hashLen = int(v)
		if hashLen > maxHashLength {
			err = ErrHashTooLong(hashLen)
			panic(err)
		}
		reader.Used(at)

		buff, err = reader.Next(hashLen)
		if err != nil {
			if err != io.EOF {
				return nil, err
			}
			loop = false
		}
		block.StrongHash = make([]byte, hashLen)
		copy(block.StrongHash, buff[:hashLen])

		reader.Used(hashLen)

		bb = append(bb, block)
	}

	return bb, nil
}