mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-03 12:58:29 +00:00 
			
		
		
		
	* update github.com/blevesearch/bleve v2.0.2 -> v2.0.3 * github.com/denisenkom/go-mssqldb v0.9.0 -> v0.10.0 * github.com/editorconfig/editorconfig-core-go v2.4.1 -> v2.4.2 * github.com/go-chi/cors v1.1.1 -> v1.2.0 * github.com/go-git/go-billy v5.0.0 -> v5.1.0 * github.com/go-git/go-git v5.2.0 -> v5.3.0 * github.com/go-ldap/ldap v3.2.4 -> v3.3.0 * github.com/go-redis/redis v8.6.0 -> v8.8.2 * github.com/go-sql-driver/mysql v1.5.0 -> v1.6.0 * github.com/go-swagger/go-swagger v0.26.1 -> v0.27.0 * github.com/lib/pq v1.9.0 -> v1.10.1 * github.com/mattn/go-sqlite3 v1.14.6 -> v1.14.7 * github.com/go-testfixtures/testfixtures v3.5.0 -> v3.6.0 * github.com/issue9/identicon v1.0.1 -> v1.2.0 * github.com/klauspost/compress v1.11.8 -> v1.12.1 * github.com/mgechev/revive v1.0.3 -> v1.0.6 * github.com/microcosm-cc/bluemonday v1.0.7 -> v1.0.8 * github.com/niklasfasching/go-org v1.4.0 -> v1.5.0 * github.com/olivere/elastic v7.0.22 -> v7.0.24 * github.com/pelletier/go-toml v1.8.1 -> v1.9.0 * github.com/prometheus/client_golang v1.9.0 -> v1.10.0 * github.com/xanzy/go-gitlab v0.44.0 -> v0.48.0 * github.com/yuin/goldmark v1.3.3 -> v1.3.5 * github.com/6543/go-version v1.2.4 -> v1.3.1 * do github.com/lib/pq v1.10.0 -> v1.10.1 again ...
		
			
				
	
	
		
			272 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			272 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
package mssql
 | 
						|
 | 
						|
import (
 | 
						|
	"encoding/binary"
 | 
						|
	"errors"
 | 
						|
	"io"
 | 
						|
)
 | 
						|
 | 
						|
type packetType uint8
 | 
						|
 | 
						|
type 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 separate to make sending attn signals
 | 
						|
// possible without locks. Currently attn signals are only sent during
 | 
						|
// reads, not writes.
 | 
						|
type tdsBuffer struct {
 | 
						|
	transport io.ReadWriteCloser
 | 
						|
 | 
						|
	packetSize int
 | 
						|
 | 
						|
	// Write fields.
 | 
						|
	wbuf        []byte
 | 
						|
	wpos        int
 | 
						|
	wPacketSeq  byte
 | 
						|
	wPacketType packetType
 | 
						|
 | 
						|
	// Read fields.
 | 
						|
	rbuf        []byte
 | 
						|
	rpos        int
 | 
						|
	rsize       int
 | 
						|
	final       bool
 | 
						|
	rPacketType packetType
 | 
						|
 | 
						|
	// afterFirst is assigned to right after tdsBuffer is created and
 | 
						|
	// before the first use. It is executed after the first packet is
 | 
						|
	// written and then removed.
 | 
						|
	afterFirst func()
 | 
						|
}
 | 
						|
 | 
						|
func newTdsBuffer(bufsize uint16, transport io.ReadWriteCloser) *tdsBuffer {
 | 
						|
	return &tdsBuffer{
 | 
						|
		packetSize: int(bufsize),
 | 
						|
		wbuf:       make([]byte, bufsize),
 | 
						|
		rbuf:       make([]byte, bufsize),
 | 
						|
		rpos:       8,
 | 
						|
		transport:  transport,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (rw *tdsBuffer) ResizeBuffer(packetSize int) {
 | 
						|
	rw.packetSize = packetSize
 | 
						|
}
 | 
						|
 | 
						|
func (w *tdsBuffer) PackageSize() int {
 | 
						|
	return w.packetSize
 | 
						|
}
 | 
						|
 | 
						|
func (w *tdsBuffer) flush() (err error) {
 | 
						|
	// Write packet size.
 | 
						|
	w.wbuf[0] = byte(w.wPacketType)
 | 
						|
	binary.BigEndian.PutUint16(w.wbuf[2:], uint16(w.wpos))
 | 
						|
	w.wbuf[6] = w.wPacketSeq
 | 
						|
 | 
						|
	// Write packet into underlying transport.
 | 
						|
	if _, err = w.transport.Write(w.wbuf[:w.wpos]); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	// It is possible to create a whole new buffer after a flush.
 | 
						|
	// Useful for debugging. Normally reuse the buffer.
 | 
						|
	// w.wbuf = make([]byte, 1<<16)
 | 
						|
 | 
						|
	// Execute afterFirst hook if it is set.
 | 
						|
	if w.afterFirst != nil {
 | 
						|
		w.afterFirst()
 | 
						|
		w.afterFirst = nil
 | 
						|
	}
 | 
						|
 | 
						|
	w.wpos = 8
 | 
						|
	w.wPacketSeq++
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (w *tdsBuffer) Write(p []byte) (total int, err error) {
 | 
						|
	for {
 | 
						|
		copied := copy(w.wbuf[w.wpos:w.packetSize], p)
 | 
						|
		w.wpos += copied
 | 
						|
		total += copied
 | 
						|
		if copied == len(p) {
 | 
						|
			return
 | 
						|
		}
 | 
						|
		if err = w.flush(); err != nil {
 | 
						|
			return
 | 
						|
		}
 | 
						|
		p = p[copied:]
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (w *tdsBuffer) WriteByte(b byte) error {
 | 
						|
	if int(w.wpos) == len(w.wbuf) || w.wpos == w.packetSize {
 | 
						|
		if err := w.flush(); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	w.wbuf[w.wpos] = b
 | 
						|
	w.wpos += 1
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (w *tdsBuffer) BeginPacket(packetType packetType, resetSession bool) {
 | 
						|
	status := byte(0)
 | 
						|
	if resetSession {
 | 
						|
		switch packetType {
 | 
						|
		// Reset session can only be set on the following packet types.
 | 
						|
		case packSQLBatch, packRPCRequest, packTransMgrReq:
 | 
						|
			status = 0x8
 | 
						|
		}
 | 
						|
	}
 | 
						|
	w.wbuf[1] = status // Packet is incomplete. This byte is set again in FinishPacket.
 | 
						|
	w.wpos = 8
 | 
						|
	w.wPacketSeq = 1
 | 
						|
	w.wPacketType = packetType
 | 
						|
}
 | 
						|
 | 
						|
func (w *tdsBuffer) FinishPacket() error {
 | 
						|
	w.wbuf[1] |= 1 // Mark this as the last packet in the message.
 | 
						|
	return w.flush()
 | 
						|
}
 | 
						|
 | 
						|
var headerSize = binary.Size(header{})
 | 
						|
 | 
						|
func (r *tdsBuffer) readNextPacket() error {
 | 
						|
	buf := r.rbuf[:headerSize]
 | 
						|
	_, err := io.ReadFull(r.transport, buf)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	h := header{
 | 
						|
		PacketType: packetType(buf[0]),
 | 
						|
		Status: buf[1],
 | 
						|
		Size: binary.BigEndian.Uint16(buf[2:4]),
 | 
						|
		Spid: binary.BigEndian.Uint16(buf[4:6]),
 | 
						|
		PacketNo: buf[6],
 | 
						|
		Pad: buf[7],
 | 
						|
	}
 | 
						|
	if int(h.Size) > r.packetSize {
 | 
						|
		return errors.New("invalid packet size, it is longer than buffer size")
 | 
						|
	}
 | 
						|
	if headerSize > int(h.Size) {
 | 
						|
		return errors.New("invalid packet size, it is shorter than header size")
 | 
						|
	}
 | 
						|
	_, err = io.ReadFull(r.transport, r.rbuf[headerSize:h.Size])
 | 
						|
	//s := base64.StdEncoding.EncodeToString(r.rbuf[headerSize:h.Size])
 | 
						|
	//fmt.Print(s)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	r.rpos = headerSize
 | 
						|
	r.rsize = int(h.Size)
 | 
						|
	r.final = h.Status != 0
 | 
						|
	r.rPacketType = h.PacketType
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (r *tdsBuffer) BeginRead() (packetType, error) {
 | 
						|
	err := r.readNextPacket()
 | 
						|
	if err != nil {
 | 
						|
		return 0, err
 | 
						|
	}
 | 
						|
	return r.rPacketType, 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 {
 | 
						|
	return readBVarCharOrPanic(r)
 | 
						|
}
 | 
						|
 | 
						|
func readBVarCharOrPanic(r io.Reader) string {
 | 
						|
	s, err := readBVarChar(r)
 | 
						|
	if err != nil {
 | 
						|
		badStreamPanic(err)
 | 
						|
	}
 | 
						|
	return s
 | 
						|
}
 | 
						|
 | 
						|
func readUsVarCharOrPanic(r io.Reader) string {
 | 
						|
	s, err := readUsVarChar(r)
 | 
						|
	if err != nil {
 | 
						|
		badStreamPanic(err)
 | 
						|
	}
 | 
						|
	return s
 | 
						|
}
 | 
						|
 | 
						|
func (r *tdsBuffer) UsVarChar() string {
 | 
						|
	return readUsVarCharOrPanic(r)
 | 
						|
}
 | 
						|
 | 
						|
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 += copied
 | 
						|
	return
 | 
						|
}
 |