Merge "javascript/api: Updated javascript api to match the new serve api in go."
diff --git a/examples/pipetobrowser/browser/services/pipe-to-browser-server.js b/examples/pipetobrowser/browser/services/pipe-to-browser-server.js
index 5f40da4..21dc83e 100644
--- a/examples/pipetobrowser/browser/services/pipe-to-browser-server.js
+++ b/examples/pipetobrowser/browser/services/pipe-to-browser-server.js
@@ -91,17 +91,15 @@
 
   state.publishing = true;
 
-  return server.register('pipe', p2b).then(() => { //TODO(aghassemi) publish-issue add pipe for now since we can't register under empty name
-    return server.publish(config.publishNamePrefix + '/' + name).then((endpoint) => { //TODO(aghassemi) publish-issue
-      log.debug('published with endpoint:', endpoint);
+  return server.serve(config.publishNamePrefix + '/' + name + '/pipe', p2b).then((endpoint) => { //TODO(aghassemi) publish-issue
+    log.debug('published with endpoint:', endpoint);
 
-      state.published = true;
-      state.publishing = false;
-      state.fullServiceName = config.publishNamePrefix + '/' + name + '/pipe'; //TODO(aghassemi) publish-issue
-      state.date = new Date();
+    state.published = true;
+    state.publishing = false;
+    state.fullServiceName = config.publishNamePrefix + '/' + name + '/pipe'; //TODO(aghassemi) publish-issue
+    state.date = new Date();
 
-      return endpoint;
-    });
+    return endpoint;
   }).catch((err) => { state.reset(); throw err; });
 }
 
diff --git a/services/wspr/wsprd/lib/server.go b/services/wspr/wsprd/lib/server.go
index 901287e..8b95ea2 100644
--- a/services/wspr/wsprd/lib/server.go
+++ b/services/wspr/wsprd/lib/server.go
@@ -6,7 +6,6 @@
 	"bytes"
 	"encoding/json"
 	"fmt"
-	"strings"
 	"sync"
 
 	"veyron2"
@@ -22,6 +21,20 @@
 	writer clientWriter
 }
 
+// A request from the proxy to javascript to handle an RPC
+type serverRPCRequest struct {
+	ServerId uint64
+	Method   string
+	Args     []interface{}
+	Context  serverRPCRequestContext
+}
+
+// call context for a serverRPCRequest
+type serverRPCRequestContext struct {
+	Suffix string
+	Name   string
+}
+
 type serverHelper interface {
 	createNewFlow(server *server, sender sender) *flow
 
@@ -37,8 +50,10 @@
 
 	// The server that handles the ipc layer.  Listen on this server is
 	// lazily started.
-	server     ipc.Server
-	dispatcher exactMatchDispatcher
+	server ipc.Server
+
+	// The saved dispatcher to reuse when serve is called multiple times.
+	dispatcher ipc.Dispatcher
 
 	// The endpoint of the server.  This is empty until the server has been
 	// started and listen has been called on it.
@@ -61,7 +76,6 @@
 		helper:                    helper,
 		veyronProxy:               veyronProxy,
 		outstandingServerRequests: make(map[int64]chan *serverRPCReply),
-		dispatcher:                exactMatchDispatcher{dispatchers: make(map[string]ipc.Dispatcher)},
 	}
 	var err error
 	if server.server, err = helper.rt().NewServer(); err != nil {
@@ -74,7 +88,7 @@
 // communicate the result back via a channel to the caller
 type remoteInvokeFunc func(methodName string, args []interface{}, call ipc.ServerCall) <-chan *serverRPCReply
 
-func (s *server) createRemoteInvokerFunc(serviceName string) remoteInvokeFunc {
+func (s *server) createRemoteInvokerFunc() remoteInvokeFunc {
 	return func(methodName string, args []interface{}, call ipc.ServerCall) <-chan *serverRPCReply {
 		flow := s.helper.createNewFlow(s, senderWrapper{stream: call})
 		replyChan := make(chan *serverRPCReply, 1)
@@ -87,11 +101,10 @@
 		}
 		// Send a invocation request to JavaScript
 		message := serverRPCRequest{
-			ServerId:    s.id,
-			ServiceName: serviceName,
-			Method:      lowercaseFirstCharacter(methodName),
-			Args:        args,
-			Context:     context,
+			ServerId: s.id,
+			Method:   lowercaseFirstCharacter(methodName),
+			Args:     args,
+			Context:  context,
 		}
 
 		data := response{Type: responseServerRequest, Message: message}
@@ -114,8 +127,8 @@
 		}
 
 		s.helper.getLogger().VI(3).Infof("request received to call method %q on "+
-			"JavaScript server %q with args %v, MessageId %d was assigned.",
-			methodName, serviceName, args, flow.id)
+			"JavaScript server with args %v, MessageId %d was assigned.",
+			methodName, args, flow.id)
 
 		go proxyStream(call, flow.writer, s.helper.getLogger())
 		return replyChan
@@ -146,62 +159,28 @@
 	}
 }
 
-type exactMatchDispatcher struct {
-	sync.Mutex
-	dispatchers map[string]ipc.Dispatcher
-}
+func (s *server) serve(name string, sig JSONServiceSignature) (string, error) {
+	s.Lock()
+	defer s.Unlock()
 
-func (em *exactMatchDispatcher) Lookup(suffix string) (ipc.Invoker, security.Authorizer, error) {
-	parts := strings.Split(suffix, "/")
-	if len(parts) == 0 || len(parts[0]) == 0 {
-		return nil, nil, fmt.Errorf("can't extract first path component from %q", suffix)
-	}
-	name := parts[0]
-	em.Lock()
-	defer em.Unlock()
-	if disp := em.dispatchers[name]; disp == nil {
-		return nil, nil, fmt.Errorf("no dispatcher registered for %q, from %q", name, suffix)
-	} else {
-		suffix = strings.TrimLeft(suffix, "/")
-		suffix = strings.TrimPrefix(suffix, name)
-		suffix = strings.TrimLeft(suffix, "/")
-		return disp.Lookup(suffix)
-	}
-}
-
-// register associates a dispatcher with name, where name cannot contain
-// any /s. Incoming invocations of the form <name>/... will be passed
-// on to the dispatcher with <name>/... as the parameter to its lookup
-// method.
-func (s *server) register(name string, sig JSONServiceSignature) error {
 	serviceSig, err := sig.ServiceSignature()
 	if err != nil {
-		return err
+		return "", err
 	}
 
-	if strings.Contains(name, "/") {
-		return fmt.Errorf("%q must not contain /", name)
-	}
-
-	remoteInvokeFunc := s.createRemoteInvokerFunc(name)
+	remoteInvokeFunc := s.createRemoteInvokerFunc()
 	invoker, err := newInvoker(serviceSig, remoteInvokeFunc)
 
 	if err != nil {
-		return err
+		return "", err
 	}
-	dispatcher := newDispatcher(invoker, security.NewACLAuthorizer(
-		security.ACL{security.AllPrincipals: security.AllLabels},
-	))
 
-	s.dispatcher.Lock()
-	s.dispatcher.dispatchers[name] = dispatcher
-	s.dispatcher.Unlock()
-	return nil
-}
+	if s.dispatcher == nil {
+		s.dispatcher = newDispatcher(invoker, security.NewACLAuthorizer(
+			security.ACL{security.AllPrincipals: security.AllLabels},
+		))
+	}
 
-func (s *server) publish(name string) (string, error) {
-	s.Lock()
-	defer s.Unlock()
 	if s.endpoint == "" {
 		endpoint, err := s.server.Listen("veyron", s.veyronProxy)
 
@@ -210,7 +189,7 @@
 		}
 		s.endpoint = endpoint.String()
 	}
-	if err := s.server.Serve(name, &s.dispatcher); err != nil {
+	if err := s.server.Serve(name, s.dispatcher); err != nil {
 		return "", err
 	}
 	s.helper.getLogger().VI(1).Infof("endpoint is %s", s.endpoint)
diff --git a/services/wspr/wsprd/lib/wspr.go b/services/wspr/wsprd/lib/wspr.go
index 0147432..b48a310 100644
--- a/services/wspr/wsprd/lib/wspr.go
+++ b/services/wspr/wsprd/lib/wspr.go
@@ -87,8 +87,8 @@
 	// Making a veyron client request, streaming or otherwise
 	websocketVeyronRequest websocketMessageType = 0
 
-	// Publishing this websocket under an object name
-	websocketPublishServer = 1
+	// Serving this websocket under an object name
+	websocketServe = 1
 
 	// A response from a service in javascript to a request
 	// from the proxy.
@@ -112,7 +112,7 @@
 	// This contains the json encoded payload.
 	Data string
 
-	// Whether it is an rpc request or a publish request.
+	// Whether it is an rpc request or a serve request.
 	Type websocketMessageType
 }
 
@@ -135,32 +135,11 @@
 	IsStreaming bool
 }
 
-// A request javascript to publish on a particular name
-type publishRequest struct {
+// A request javascript to serve undern a particular name
+type serveRequest struct {
 	Name     string
 	ServerId uint64
-	Services map[string]JSONServiceSignature
-}
-
-// A request from javascript to register a particular prefix
-type registerRequest struct {
-	Prefix string
-	// TODO(bjornick): Do we care about the methods?
-}
-
-// A request from the proxy to javascript to handle an RPC
-type serverRPCRequest struct {
-	ServerId    uint64
-	ServiceName string
-	Method      string
-	Args        []interface{}
-	Context     serverRPCRequestContext
-}
-
-// call context for a serverRPCRequest
-type serverRPCRequestContext struct {
-	Suffix string
-	Name   string
+	Service  JSONServiceSignature
 }
 
 // The response from the javascript server to the proxy.
@@ -355,7 +334,7 @@
 	// A manager that handles fetching and caching signature of remote services
 	signatureManager *signatureManager
 
-	// We maintain multiple Veyron server per websocket pipe for publishing JavaScript
+	// We maintain multiple Veyron server per websocket pipe for serving JavaScript
 	// services.
 	servers map[uint64]*server
 
@@ -613,8 +592,8 @@
 			wsp.sendOnStream(msg.Id, msg.Data, ww)
 		case websocketStreamClose:
 			wsp.closeStream(msg.Id)
-		case websocketPublishServer:
-			go wsp.handlePublishRequest(msg.Data, ww)
+		case websocketServe:
+			go wsp.handleServeRequest(msg.Data, ww)
 		case websocketStopServer:
 			go wsp.handleStopRequest(msg.Data, ww)
 		case websocketServerResponse:
@@ -655,25 +634,18 @@
 	server.Stop()
 }
 
-func (wsp *websocketPipe) publish(publishRequest publishRequest, w clientWriter) {
+func (wsp *websocketPipe) serve(serveRequest serveRequest, w clientWriter) {
 	// Create a server for the websocket pipe, if it does not exist already
-	server, err := wsp.maybeCreateServer(publishRequest.ServerId)
+	server, err := wsp.maybeCreateServer(serveRequest.ServerId)
 	if err != nil {
 		w.sendError(verror.Internalf("error creating server: %v", err))
 	}
 
-	wsp.ctx.logger.VI(2).Infof("publishing under name: %q", publishRequest.Name)
+	wsp.ctx.logger.VI(2).Infof("serving under name: %q", serveRequest.Name)
 
-	// Register each service under the server
-	for serviceName, jsonIDLSig := range publishRequest.Services {
-		if err := server.register(serviceName, jsonIDLSig); err != nil {
-			w.sendError(verror.Internalf("error registering service: %v", err))
-		}
-	}
-
-	endpoint, err := server.publish(publishRequest.Name)
+	endpoint, err := server.serve(serveRequest.Name, serveRequest.Service)
 	if err != nil {
-		w.sendError(verror.Internalf("error publishing service: %v", err))
+		w.sendError(verror.Internalf("error serving service: %v", err))
 		return
 	}
 	// Send the endpoint back
@@ -689,17 +661,17 @@
 	}
 }
 
-// handlePublishRequest takes a request to publish a server, creates
+// handleServeRequest takes a request to serve a server, creates
 // a server, registers the provided services and sends the endpoint back.
-func (wsp *websocketPipe) handlePublishRequest(data string, w *websocketWriter) {
-	// Decode the publish request which includes IDL, registered services and name
-	var publishRequest publishRequest
+func (wsp *websocketPipe) handleServeRequest(data string, w *websocketWriter) {
+	// Decode the serve request which includes IDL, registered services and name
+	var serveRequest serveRequest
 	decoder := json.NewDecoder(bytes.NewBufferString(data))
-	if err := decoder.Decode(&publishRequest); err != nil {
+	if err := decoder.Decode(&serveRequest); err != nil {
 		w.sendError(verror.Internalf("can't unmarshal JSONMessage: %v", err))
 		return
 	}
-	wsp.publish(publishRequest, w)
+	wsp.serve(serveRequest, w)
 }
 
 // handleStopRequest takes a request to stop a server.
diff --git a/services/wspr/wsprd/lib/wspr_test.go b/services/wspr/wsprd/lib/wspr_test.go
index 15d4ac3..f8d6b9f 100644
--- a/services/wspr/wsprd/lib/wspr_test.go
+++ b/services/wspr/wsprd/lib/wspr_test.go
@@ -364,7 +364,7 @@
 	proxyServer      *proxy.Proxy
 }
 
-func publishServer() (*runningTest, error) {
+func serveServer() (*runningTest, error) {
 	mounttableServer, endpoint, err := startMountTableServer()
 
 	if err != nil {
@@ -389,11 +389,9 @@
 		return &writer
 	}
 	wsp.setup()
-	wsp.publish(publishRequest{
-		Name: "adder",
-		Services: map[string]JSONServiceSignature{
-			"adder": adderServiceSignature,
-		},
+	wsp.serve(serveRequest{
+		Name:    "adder",
+		Service: adderServiceSignature,
 	}, &writer)
 
 	return &runningTest{
@@ -401,14 +399,14 @@
 	}, nil
 }
 
-func TestJavascriptPublishServer(t *testing.T) {
-	rt, err := publishServer()
+func TestJavascriptServeServer(t *testing.T) {
+	rt, err := serveServer()
 	defer rt.mounttableServer.Stop()
 	defer rt.proxyServer.Shutdown()
 	defer rt.wsp.cleanup()
 
 	if err != nil {
-		t.Errorf("could not publish server %v", err)
+		t.Errorf("could not serve server %v", err)
 	}
 
 	if len(rt.writer.stream) != 1 {
@@ -419,7 +417,7 @@
 	resp := rt.writer.stream[0]
 
 	if resp.Type != responseFinal {
-		t.Errorf("unknown stream message Got: %v, expected: publish response", resp)
+		t.Errorf("unknown stream message Got: %v, expected: serve response", resp)
 		return
 	}
 
@@ -428,17 +426,17 @@
 			return
 		}
 	}
-	t.Errorf("invalid endpdoint returned from publish: %v", resp.Message)
+	t.Errorf("invalid endpdoint returned from serve: %v", resp.Message)
 }
 
 func TestJavascriptStopServer(t *testing.T) {
-	rt, err := publishServer()
+	rt, err := serveServer()
 	defer rt.mounttableServer.Stop()
 	defer rt.proxyServer.Shutdown()
 	defer rt.wsp.cleanup()
 
 	if err != nil {
-		t.Errorf("could not publish server %v", err)
+		t.Errorf("could not serve server %v", err)
 		return
 	}
 
@@ -489,13 +487,13 @@
 }
 
 func runJsServerTestCase(t *testing.T, test jsServerTestCase) {
-	rt, err := publishServer()
+	rt, err := serveServer()
 	defer rt.mounttableServer.Stop()
 	defer rt.proxyServer.Shutdown()
 	defer rt.wsp.cleanup()
 
 	if err != nil {
-		t.Errorf("could not publish server %v", err)
+		t.Errorf("could not serve server %v", err)
 	}
 
 	if len(rt.writer.stream) != 1 {
@@ -506,17 +504,17 @@
 	resp := rt.writer.stream[0]
 
 	if resp.Type != responseFinal {
-		t.Errorf("unknown stream message Got: %v, expected: publish response", resp)
+		t.Errorf("unknown stream message Got: %v, expected: serve response", resp)
 		return
 	}
 
 	msg, ok := resp.Message.(string)
 	if !ok {
-		t.Errorf("invalid endpdoint returned from publish: %v", resp.Message)
+		t.Errorf("invalid endpdoint returned from serve: %v", resp.Message)
 	}
 
 	if _, err := r.NewEndpoint(msg); err != nil {
-		t.Errorf("invalid endpdoint returned from publish: %v", resp.Message)
+		t.Errorf("invalid endpdoint returned from serve: %v", resp.Message)
 	}
 
 	rt.writer.stream = nil
@@ -528,7 +526,7 @@
 		t.Errorf("unable to create client: %v", err)
 	}
 
-	call, err := client.StartCall(rt.wspr.rt.NewContext(), "/"+msg+"//adder", test.method, test.inArgs)
+	call, err := client.StartCall(rt.wspr.rt.NewContext(), "/"+msg+"/adder", test.method, test.inArgs)
 	if err != nil {
 		t.Errorf("failed to start call: %v", err)
 	}
@@ -537,10 +535,9 @@
 		response{
 			Type: responseServerRequest,
 			Message: map[string]interface{}{
-				"serverId":    0.0,
-				"serviceName": "adder",
-				"method":      lowercaseFirstCharacter(test.method),
-				"args":        test.inArgs,
+				"serverId": 0.0,
+				"method":   lowercaseFirstCharacter(test.method),
+				"args":     test.inArgs,
 				"context": map[string]interface{}{
 					"name":   "adder",
 					"suffix": "adder",