veyron/runtimes/google/ipc: Call CloseSend on Finish.

When the client calls Finish on a call, inform the server that no more inputs
will be sent. (tested by TestCloseSendOnFinish)
The client may still call CloseSend before calling Finish. (tested by TestRPC)

Change-Id: I993ec814343117a3738ee057c933ab49a6cf79cc
diff --git a/runtimes/google/ipc/client.go b/runtimes/google/ipc/client.go
index c2e0aa3..7f2b09c 100644
--- a/runtimes/google/ipc/client.go
+++ b/runtimes/google/ipc/client.go
@@ -289,6 +289,11 @@
 }
 
 func (fc *flowClient) CloseSend() error {
+	return fc.closeSend()
+}
+
+// closeSend ensures CloseSend always returns verror.E.
+func (fc *flowClient) closeSend() verror.E {
 	if fc.sendClosed {
 		return errFlowClosed
 	}
@@ -305,6 +310,14 @@
 
 // finish ensures Finish always returns verror.E.
 func (fc *flowClient) finish(resultptrs ...interface{}) verror.E {
+	// Inform the server that no more items will be sent, unless
+	// a) CloseSend has already done so.
+	// b) The flow was previously closed (e.g. due to an encoding error).
+	if !fc.sendClosed && !fc.flow.IsClosed() {
+		if err := fc.closeSend(); err != nil {
+			return err
+		}
+	}
 	// Decode the response header, if it hasn't already been decoded by Recv.
 	if fc.response.Error == nil && !fc.response.EndStreamResults {
 		if err := fc.dec.Decode(&fc.response); err != nil {
diff --git a/runtimes/google/ipc/full_test.go b/runtimes/google/ipc/full_test.go
index 4260de9..941f6bd 100644
--- a/runtimes/google/ipc/full_test.go
+++ b/runtimes/google/ipc/full_test.go
@@ -352,6 +352,16 @@
 }
 
 func TestRPC(t *testing.T) {
+	testRPC(t, true)
+}
+
+// TestCloseSendOnFinish tests that Finish informs the server that no more
+// inputs will be sent by the client if CloseSend has not already done so.
+func TestRPCCloseSendOnFinish(t *testing.T) {
+	testRPC(t, false)
+}
+
+func testRPC(t *testing.T, shouldCloseSend bool) {
 	type v []interface{}
 	type testcase struct {
 		name       string
@@ -402,9 +412,11 @@
 				t.Errorf("%s call.Recv got value %v, want %v", name(test), u, sarg)
 			}
 		}
-		vlog.VI(1).Infof("%s call.CloseSend", name(test))
-		if err := call.CloseSend(); err != nil {
-			t.Errorf(`%s call.CloseSend got unexpected error "%v"`, name(test), err)
+		if shouldCloseSend {
+			vlog.VI(1).Infof("%s call.CloseSend", name(test))
+			if err := call.CloseSend(); err != nil {
+				t.Errorf(`%s call.CloseSend got unexpected error "%v"`, name(test), err)
+			}
 		}
 		vlog.VI(1).Infof("%s client.Finish", name(test))
 		results := makeResultPtrs(test.results)