func (c *channel) copySender(val libchan.Sender) (libchan.Sender, error) { recv, send, err := c.CreateNestedReceiver() if err != nil { return nil, err } go func() { libchan.Copy(val, recv) val.Close() }() return send, nil }
func (c *channel) copyReceiver(val libchan.Receiver) (libchan.Receiver, error) { send, recv, err := c.CreateNestedSender() if err != nil { return nil, err } go func() { libchan.Copy(send, val) send.Close() }() return recv, nil }
func (c *channel) copyReceiveChannel(recv libchan.Receiver) (*channel, error) { send, recvCopy, err := c.CreateNestedSender() if err != nil { return nil, err } // Start copying from receiver go func() { libchan.Copy(send, recv) send.Close() }() return recvCopy.(*channel), nil }
func (c *channel) copySendChannel(send libchan.Sender) (*channel, error) { recv, sendCopy, err := c.CreateNestedReceiver() if err != nil { return nil, err } // Start copying into sender go func() { libchan.Copy(send, recv) send.Close() }() return sendCopy.(*channel), nil }
func (c *Conn) Send(msg *lch.Message) (lch.Receiver, error) { if msg.Fd != nil { return nil, fmt.Errorf("file attachment not yet implemented in unix transport") } // Setup nested streams var ( fd *os.File ret lch.Receiver err error ) // Caller requested a return pipe if lch.RetPipe.Equals(msg.Ret) { local, remote, err := sendablePair() if err != nil { return nil, err } fd = remote ret = &Conn{local} // Caller specified its own return channel } else if msg.Ret != nil { // The specified return channel is a unix conn: engaging cheat mode! if retConn, ok := msg.Ret.(*Conn); ok { fd, err = retConn.UnixConn.File() if err != nil { return nil, fmt.Errorf("error passing return channel: %v", err) } // Close duplicate fd retConn.UnixConn.Close() // The specified return channel is an unknown type: proxy messages. } else { local, remote, err := sendablePair() if err != nil { return nil, fmt.Errorf("error passing return channel: %v", err) } fd = remote // FIXME: do we need a reference no all these background tasks? go func() { // Copy messages from the remote return channel to the local return channel. // When the remote return channel is closed, also close the local return channel. localConn := &Conn{local} lch.Copy(msg.Ret, localConn) msg.Ret.Close() localConn.Close() }() } } if err := c.UnixConn.Send(msg.Data, fd); err != nil { return nil, err } return ret, nil }
func BenchProxy(b *testing.B, c chan bool, sender libchan.Sender, receiver libchan.Receiver, count int) { defer close(c) n, err := libchan.Copy(sender, receiver) if err != nil { b.Errorf("Error proxying: %s", err) } err = sender.Close() if err != nil { b.Errorf("Error closing sender: %s", err) } if n != count { b.Errorf("Wrong proxy count\n\tExpected: %d\n\tActual: %d", count, n) } }
func Copy(s Sender, r Receiver) (int, error) { return libchan.Copy(s.Unwrap(), r.Unwrap()) }
func SpawnProxyTest(t *testing.T, client PipeSenderRoutine, server PipeReceiverRoutine, proxyCount int) { endClient := make(chan bool) endServer := make(chan bool) endProxy := make(chan bool) receiver1, sender1, err := Pipe() receiver2, sender2, err := Pipe() if err != nil { t.Fatalf("Error creating pipe: %s", err) } go func() { defer close(endProxy) n, err := libchan.Copy(sender2, receiver1) if err != nil { t.Errorf("Error proxying: %s", err) } err = sender2.Close() if err != nil { t.Errorf("Error closing sender: %s", err) } if n != proxyCount { t.Errorf("Wrong proxy count\n\tExpected: %d\n\tActual: %d", proxyCount, n) } }() go func() { defer close(endClient) client(t, sender1) err := sender1.Close() if err != nil { t.Errorf("Error closing sender: %s", err) } }() go func() { defer close(endServer) server(t, receiver2) }() timeout := time.After(ClientServerTimeout) for endClient != nil || endServer != nil || endProxy != nil { select { case <-endProxy: if t.Failed() { t.Fatal("Proxy failed") } endProxy = nil case <-endClient: if t.Failed() { t.Fatal("Client failed") } endClient = nil case <-endServer: if t.Failed() { t.Fatal("Server failed") } endServer = nil case <-timeout: if DumpStackOnTimeout { pprof.Lookup("goroutine").WriteTo(os.Stdout, 1) } t.Fatal("Timeout") } } }