| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 | package mssqlimport (	"encoding/binary"	"errors"	"io")type packetType uint8type header struct {	PacketType packetType	Status     uint8	Size       uint16	Spid       uint16	PacketNo   uint8	Pad        uint8}// tdsBuffer reads and writes TDS packets of data to the transport.// The write and read buffers are spearate to make sending attn signals// possible without locks. Currently attn signals are only sent during// reads, not writes.type tdsBuffer struct {	transport io.ReadWriteCloser	// Write fields.	wbuf []byte	wpos uint16	// Read fields.	rbuf        []byte	rpos        uint16	rsize       uint16	final       bool	packet_type packetType	// afterFirst is assigned to right after tdsBuffer is created and	// before the first use. It is executed after the first packet is	// writen and then removed.	afterFirst func()}func newTdsBuffer(bufsize int, transport io.ReadWriteCloser) *tdsBuffer {	w := new(tdsBuffer)	w.wbuf = make([]byte, bufsize)	w.rbuf = make([]byte, bufsize)	w.wpos = 0	w.rpos = 8	w.transport = transport	return w}func (rw *tdsBuffer) ResizeBuffer(packetsizei int) {	if len(rw.rbuf) != packetsizei {		newbuf := make([]byte, packetsizei)		copy(newbuf, rw.rbuf)		rw.rbuf = newbuf	}	if len(rw.wbuf) != packetsizei {		newbuf := make([]byte, packetsizei)		copy(newbuf, rw.wbuf)		rw.wbuf = newbuf	}}func (w *tdsBuffer) PackageSize() uint32 {	return uint32(len(w.wbuf))}func (w *tdsBuffer) flush() (err error) {	// writing packet size	binary.BigEndian.PutUint16(w.wbuf[2:], w.wpos)	// writing packet into underlying transport	if _, err = w.transport.Write(w.wbuf[:w.wpos]); err != nil {		return err	}	// execute afterFirst hook if it is set	if w.afterFirst != nil {		w.afterFirst()		w.afterFirst = nil	}	w.wpos = 8	// packet number	w.wbuf[6] += 1	return nil}func (w *tdsBuffer) Write(p []byte) (total int, err error) {	total = 0	for {		copied := copy(w.wbuf[w.wpos:], p)		w.wpos += uint16(copied)		total += copied		if copied == len(p) {			break		}		if err = w.flush(); err != nil {			return		}		p = p[copied:]	}	return}func (w *tdsBuffer) WriteByte(b byte) error {	if int(w.wpos) == len(w.wbuf) {		if err := w.flush(); err != nil {			return err		}	}	w.wbuf[w.wpos] = b	w.wpos += 1	return nil}func (w *tdsBuffer) BeginPacket(packet_type packetType) {	w.wbuf[0] = byte(packet_type)	w.wbuf[1] = 0 // packet is incomplete	w.wbuf[4] = 0 // spid	w.wbuf[5] = 0	w.wbuf[6] = 1 // packet id	w.wbuf[7] = 0 // window	w.wpos = 8}func (w *tdsBuffer) FinishPacket() error {	w.wbuf[1] = 1 // this is last packet	return w.flush()}func (r *tdsBuffer) readNextPacket() error {	header := header{}	var err error	err = binary.Read(r.transport, binary.BigEndian, &header)	if err != nil {		return err	}	offset := uint16(binary.Size(header))	if int(header.Size) > len(r.rbuf) {		return errors.New("Invalid packet size, it is longer than buffer size")	}	if int(offset) > int(header.Size) {		return errors.New("Invalid packet size, it is shorter than header size")	}	_, err = io.ReadFull(r.transport, r.rbuf[offset:header.Size])	if err != nil {		return err	}	r.rpos = offset	r.rsize = header.Size	r.final = header.Status != 0	r.packet_type = header.PacketType	return nil}func (r *tdsBuffer) BeginRead() (packetType, error) {	err := r.readNextPacket()	if err != nil {		return 0, err	}	return r.packet_type, nil}func (r *tdsBuffer) ReadByte() (res byte, err error) {	if r.rpos == r.rsize {		if r.final {			return 0, io.EOF		}		err = r.readNextPacket()		if err != nil {			return 0, err		}	}	res = r.rbuf[r.rpos]	r.rpos++	return res, nil}func (r *tdsBuffer) byte() byte {	b, err := r.ReadByte()	if err != nil {		badStreamPanic(err)	}	return b}func (r *tdsBuffer) ReadFull(buf []byte) {	_, err := io.ReadFull(r, buf[:])	if err != nil {		badStreamPanic(err)	}}func (r *tdsBuffer) uint64() uint64 {	var buf [8]byte	r.ReadFull(buf[:])	return binary.LittleEndian.Uint64(buf[:])}func (r *tdsBuffer) int32() int32 {	return int32(r.uint32())}func (r *tdsBuffer) uint32() uint32 {	var buf [4]byte	r.ReadFull(buf[:])	return binary.LittleEndian.Uint32(buf[:])}func (r *tdsBuffer) uint16() uint16 {	var buf [2]byte	r.ReadFull(buf[:])	return binary.LittleEndian.Uint16(buf[:])}func (r *tdsBuffer) BVarChar() string {	l := int(r.byte())	return r.readUcs2(l)}func (r *tdsBuffer) UsVarChar() string {	l := int(r.uint16())	return r.readUcs2(l)}func (r *tdsBuffer) readUcs2(numchars int) string {	b := make([]byte, numchars*2)	r.ReadFull(b)	res, err := ucs22str(b)	if err != nil {		badStreamPanic(err)	}	return res}func (r *tdsBuffer) Read(buf []byte) (copied int, err error) {	copied = 0	err = nil	if r.rpos == r.rsize {		if r.final {			return 0, io.EOF		}		err = r.readNextPacket()		if err != nil {			return		}	}	copied = copy(buf, r.rbuf[r.rpos:r.rsize])	r.rpos += uint16(copied)	return}
 |