2010-04-13 14:49:42 -06:00
|
|
|
// Copyright 2010 The Go Authors. All rights reserved.
|
2010-01-19 20:12:29 -07:00
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package netchan
|
|
|
|
|
|
|
|
import (
|
|
|
|
"gob"
|
|
|
|
"net"
|
|
|
|
"os"
|
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
2010-04-13 14:49:42 -06:00
|
|
|
// The direction of a connection from the client's perspective.
|
2010-01-19 20:12:29 -07:00
|
|
|
type Dir int
|
|
|
|
|
|
|
|
const (
|
|
|
|
Recv Dir = iota
|
|
|
|
Send
|
|
|
|
)
|
|
|
|
|
2010-04-13 14:49:42 -06:00
|
|
|
// Payload types
|
|
|
|
const (
|
|
|
|
payRequest = iota // request structure follows
|
|
|
|
payError // error structure follows
|
|
|
|
payData // user payload follows
|
|
|
|
)
|
|
|
|
|
|
|
|
// A header is sent as a prefix to every transmission. It will be followed by
|
|
|
|
// a request structure, an error structure, or an arbitrary user payload structure.
|
|
|
|
type header struct {
|
|
|
|
name string
|
|
|
|
payloadType int
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sent with a header once per channel from importer to exporter to report
|
|
|
|
// that it wants to bind to a channel with the specified direction for count
|
|
|
|
// messages. If count is zero, it means unlimited.
|
|
|
|
type request struct {
|
|
|
|
count int
|
|
|
|
dir Dir
|
|
|
|
}
|
2010-01-19 20:12:29 -07:00
|
|
|
|
2010-04-13 14:49:42 -06:00
|
|
|
// Sent with a header to report an error.
|
|
|
|
type error struct {
|
|
|
|
error string
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mutex-protected encoder and decoder pair.
|
2010-01-19 20:12:29 -07:00
|
|
|
type encDec struct {
|
|
|
|
decLock sync.Mutex
|
|
|
|
dec *gob.Decoder
|
|
|
|
encLock sync.Mutex
|
|
|
|
enc *gob.Encoder
|
|
|
|
}
|
|
|
|
|
|
|
|
func newEncDec(conn net.Conn) *encDec {
|
|
|
|
return &encDec{
|
|
|
|
dec: gob.NewDecoder(conn),
|
|
|
|
enc: gob.NewEncoder(conn),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-13 14:49:42 -06:00
|
|
|
// Decode an item from the connection.
|
2010-01-19 20:12:29 -07:00
|
|
|
func (ed *encDec) decode(e interface{}) os.Error {
|
|
|
|
ed.decLock.Lock()
|
|
|
|
err := ed.dec.Decode(e)
|
|
|
|
if err != nil {
|
2010-04-13 14:49:42 -06:00
|
|
|
// TODO: tear down connection?
|
2010-01-19 20:12:29 -07:00
|
|
|
}
|
2010-04-13 14:49:42 -06:00
|
|
|
ed.decLock.Unlock()
|
|
|
|
return err
|
2010-01-19 20:12:29 -07:00
|
|
|
}
|
|
|
|
|
2010-04-13 14:49:42 -06:00
|
|
|
// Encode a header and payload onto the connection.
|
|
|
|
func (ed *encDec) encode(hdr *header, payloadType int, payload interface{}) os.Error {
|
2010-01-19 20:12:29 -07:00
|
|
|
ed.encLock.Lock()
|
2010-04-13 14:49:42 -06:00
|
|
|
hdr.payloadType = payloadType
|
|
|
|
err := ed.enc.Encode(hdr)
|
|
|
|
if err == nil {
|
|
|
|
err = ed.enc.Encode(payload)
|
|
|
|
} else {
|
|
|
|
// TODO: tear down connection if there is an error?
|
2010-01-19 20:12:29 -07:00
|
|
|
}
|
2010-04-13 14:49:42 -06:00
|
|
|
ed.encLock.Unlock()
|
|
|
|
return err
|
2010-01-19 20:12:29 -07:00
|
|
|
}
|