// updates the tip func (f *File) ReadBlock() ([]byte, error) { var sz uint16 var next uint32 idx := int(f.tip / f.chunksz) off := int(f.tip % f.chunksz) buf := f.chunks[idx] m, p := vt.Gint16(buf[off:]) sz, p = vt.Gint16(p) next, p = vt.Gint32(p) if m != Magic { if m == 0 && sz == 0 { // end of arena return nil, nil } return nil, errors.New("magic not found") } f.lastip = f.tip f.tip += uint64(next) return p[0:sz], nil }
func (clnt *Clnt) recv() { var err *vt.Error var req *Req var csz int err = nil buf := make([]byte, vt.Maxblock*8) pos := 0 for { if len(buf) < int(vt.Maxblock) { b := make([]byte, vt.Maxblock*8) copy(b, buf[0:pos]) buf = b b = nil } n, oserr := clnt.conn.Read(buf[pos:len(buf)]) if oserr != nil || n == 0 { err = &vt.Error{oserr.Error()} goto closed } pos += n for pos > 4 { sz, _ := vt.Gint16(buf) sz += 2 if sz > vt.Maxblock { err = &vt.Error{fmt.Sprintf("bad client connection: %s", clnt.Id)} clnt.conn.Close() goto closed } if pos < int(sz) { if len(buf) < int(sz) { b := make([]byte, vt.Maxblock*8) copy(b, buf[0:pos]) buf = b b = nil } break } tag, _ := vt.Gint8(buf[3:]) clnt.Lock() for req = clnt.reqfirst; req != nil; req = req.next { if req.tag == tag { if req.prev != nil { req.prev.next = req.next } else { clnt.reqfirst = req.next } if req.next != nil { req.next.prev = req.prev } else { clnt.reqlast = req.prev } break } } clnt.Unlock() if req == nil { err = &vt.Error{"unexpected response"} clnt.conn.Close() goto closed } csz, err = vt.Unpack(buf, &req.Rc) if err != nil { clnt.conn.Close() goto closed } if clnt.Debuglevel > 0 { clnt.logFcall(&req.Rc) if clnt.Debuglevel&DbgPrintPackets != 0 { log.Println("}-}", clnt.Id, fmt.Sprint(req.Rc.Pkt)) } if clnt.Debuglevel&DbgPrintCalls != 0 { log.Println("}}}", clnt.Id, req.Rc.String()) } } if req.Tc.Id != req.Rc.Id-1 { if req.Rc.Id != vt.Rerror { req.Err = &vt.Error{"invalid response"} } else { if req.Err != nil { req.Err = &vt.Error{req.Rc.Ename} } } } if req.Done != nil { req.Done <- req } else { clnt.ReqFree(req) } pos -= csz buf = buf[csz:] } } closed: clnt.done <- true /* send error to all pending requests */ clnt.Lock() if clnt.err != nil { clnt.err = err } r := clnt.reqfirst clnt.reqfirst = nil clnt.reqlast = nil clnt.Unlock() for ; r != nil; r = r.next { r.Err = err if r.Done != nil { r.Done <- r } } clnts.Lock() if clnt == clnts.list { clnts.list = clnt.next } else { var c *Clnt for c = clnts.list; c.next != clnt; c = c.next { } c.next = clnt.next } clnts.Unlock() if sop, ok := (interface{}(clnt)).(StatsOps); ok { sop.statsUnregister() } }
func (conn *Conn) recv() { var err error var n int bufsz := 8 * vt.Maxblock buf := make([]byte, bufsz*8) srv := conn.Srv pos := 0 for { if len(buf) < vt.Maxblock { b := make([]byte, bufsz) copy(b, buf[0:pos]) buf = b b = nil } n, err = conn.conn.Read(buf[pos:]) if err != nil || n == 0 { goto closed } nreads := 1 pos += n for pos > 2 { sz, _ := vt.Gint16(buf) sz += 2 if sz > vt.Maxblock { log.Println("bad client connection: ", conn.conn.RemoteAddr()) conn.conn.Close() goto closed } if pos < int(sz) { if len(buf) < int(sz) { b := make([]byte, bufsz) copy(b, buf[0:pos]) buf = b b = nil } break } req := srv.ReqAlloc() req.Conn = conn csize, err := vt.Unpack(buf, req.Tc) if err != nil { log.Println(fmt.Sprintf("invalid packet: %v %v", err, buf)) conn.conn.Close() srv.ReqFree(req) goto closed } if conn.Debuglevel > 0 { conn.logFcall(req.Tc) if conn.Debuglevel&DbgPrintPackets != 0 { log.Println(">->", conn.Id, fmt.Sprintf("%x", req.Tc.Pkt)) } if conn.Debuglevel&DbgPrintCalls != 0 { log.Println(">>>", conn.Id, req.Tc.String()) } } conn.Lock() conn.nreqs++ conn.tsz += uint64(sz) conn.npend++ conn.nreads += nreads nreads = 0 if conn.npend > conn.maxpend { conn.maxpend = conn.npend } conn.Unlock() go req.process() buf = buf[csize:] pos -= csize } } closed: conn.done <- true conn.Srv.Lock() srv.nreqs += conn.nreqs srv.tsz += conn.tsz srv.rsz += conn.rsz srv.maxpend += conn.maxpend srv.nwrites += conn.nwrites srv.nreads += conn.nreads if conn.prev != nil { conn.prev.next = conn.next } else { conn.Srv.connlist = conn.next } if conn.next != nil { conn.next.prev = conn.prev } conn.Srv.Unlock() if sop, ok := (interface{}(conn)).(StatsOps); ok { sop.statsUnregister() } if op, ok := (conn.Srv.ops).(ConnOps); ok { op.ConnClosed(conn) } }