blob: 624397ef46db514e75a601749f7883669d9718c8 [file] [log] [blame]
// Copyright 2010 The Go Authors. All rights reserved.
// 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"
"reflect"
"sync"
)
// The direction of a connection from the client's perspective.
type Dir int
const (
Recv Dir = iota
Send
)
// 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
}
// Sent with a header to report an error.
type error struct {
error string
}
// Mutex-protected encoder and decoder pair.
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),
}
}
// Decode an item from the connection.
func (ed *encDec) decode(value reflect.Value) os.Error {
ed.decLock.Lock()
err := ed.dec.DecodeValue(value)
if err != nil {
// TODO: tear down connection?
}
ed.decLock.Unlock()
return err
}
// Encode a header and payload onto the connection.
func (ed *encDec) encode(hdr *header, payloadType int, payload interface{}) os.Error {
ed.encLock.Lock()
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?
}
ed.encLock.Unlock()
return err
}