示例#1
0
文件: request.go 项目: droyo/styx
// Rcreate is used to respond to a succesful create request. With 9P, creating
// a file also opens the file for I/O. Once Rcreate returns, future read
// and write requests to the file handle will pass through rwc. The value
// rwc must meet the same criteria listed for the Ropen method of a Topen
// request.
func (t Tcreate) Rcreate(rwc interface{}, err error) {
	var (
		f styxfile.Interface
	)
	if err != nil {
		t.Rerror("%s", err)
		return
	}

	if dir, ok := rwc.(Directory); t.Mode.IsDir() && ok {
		f = styxfile.NewDir(dir, path.Join(t.Path(), t.Name), t.session.conn.qidpool)
	} else {
		f, err = styxfile.New(rwc)
	}
	if err != nil {
		t.session.conn.srv.logf("create %s failed: %s", t.Name, err)
		t.Rerror("create failed")
		return
	}
	file := file{name: path.Join(t.Path(), t.Name), rwc: f}

	// fid for parent directory is now the fid for the new file,
	// so there is no increase in references to this session.
	t.session.files.Put(t.fid, file)

	qtype := styxfile.QidType(styxfile.Mode9P(t.Mode))
	qid := t.session.conn.qid(file.name, qtype)
	t.session.unhandled = false
	if t.session.conn.clearTag(t.tag) {
		t.session.conn.Rcreate(t.tag, qid, 0)
	}
}
示例#2
0
文件: conn.go 项目: droyo/styx
// NOTE(droyo) consider a scenario where a malicious actor connects
// to the server that repeatedly spams Tauth requests. It can quickly
// use up resources on the server. Consider the following measures:
//
// - rate-limiting Tauth requests
// - Setting a per-connection session limit
// - close connections that have not established a session in N seconds
func (c *conn) handleTauth(cx context.Context, m styxproto.Tauth) bool {
	defer c.Flush()
	if c.srv.Auth == nil {
		c.clearTag(m.Tag())
		c.Rerror(m.Tag(), "%s", errNotSupported)
		return true
	}
	if _, ok := c.sessionFid.Get(m.Afid()); ok {
		c.clearTag(m.Tag())
		c.Rerror(m.Tag(), "fid %x in use", m.Afid())
		return true
	}
	client, server := net.Pipe()
	ch := &Channel{
		Context:         c.cx,
		ReadWriteCloser: server,
	}
	rwc, err := styxfile.New(client)
	if err != nil {
		// This should never happen
		panic(err)
	}
	s := newSession(c, m)
	go func() {
		s.authC <- c.srv.Auth(ch, s.User, s.Access)
		close(s.authC)
	}()

	c.sessionFid.Put(m.Afid(), s)
	s.files.Put(m.Afid(), file{rwc: rwc, auth: true})
	s.IncRef()
	return true
}
示例#3
0
文件: request.go 项目: droyo/styx
// The Ropen method signals to the client that a file has succesfully
// been opened and is ready for I/O. After Ropen returns, future reads
// and writes to the opened file handle will pass through rwc.
//
// The value rwc must implement some of the interfaces in the io package
// for reading and writing. If the type implements io.Seeker or io.ReaderAt
// and io.WriterAt, clients may read or write at arbitrary offsets within
// the file. Types that only implement Read or Write operations will return
// errors on writes and reads, respectively.
//
// If rwc implements the Stat method of os.File, that will be used to
// answer Tstat requests. Otherwise, the styx package will assemble Rstat
// responses out of default values merged with any methods rwc provides
// from the os.FileInfo interface.
//
// If a file does not implement any of the Read or Write interfaces in
// the io package, A generic error is returned to the client, and a message
// will be written to the server's ErrorLog.
func (t Topen) Ropen(rwc interface{}, err error) {
	var (
		file file
		f    styxfile.Interface
	)
	if err != nil {
		t.Rerror("%s", err)
		return
	}
	// The type of the file (regular or directory) will have been
	// established in a previous Twalk request.
	qid := t.session.conn.qid(t.Path(), 0)
	mode := styxfile.ModeOS(uint32(qid.Type()) << 24)

	if dir, ok := rwc.(Directory); ok && mode.IsDir() {
		f = styxfile.NewDir(dir, t.Path(), t.session.conn.qidpool)
	} else {
		f, err = styxfile.New(rwc)
	}

	if err != nil {
		t.session.conn.srv.logf("%s open %s failed: %s", t.path, err)

		// Don't want to expose too many implementation details
		// to clients.
		t.Rerror("open failed")
		return
	}
	t.session.files.Update(t.fid, &file, func() {
		file.rwc = f
	})
	t.session.unhandled = false
	if t.session.conn.clearTag(t.tag) {
		t.session.conn.Ropen(t.tag, qid, 0)
	}
}