Jiri Simsa | d7616c9 | 2015-03-24 23:44:30 -0700 | [diff] [blame] | 1 | // Copyright 2015 The Vanadium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 5 | // An implementation of a server for WSPR |
| 6 | |
| 7 | package server |
| 8 | |
| 9 | import ( |
Nicolas LaCasse | e3867dc | 2015-02-05 14:44:53 -0800 | [diff] [blame] | 10 | "fmt" |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 11 | "sync" |
Matt Rosencrantz | 4aabe57 | 2014-10-22 09:25:50 -0700 | [diff] [blame] | 12 | "time" |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 13 | |
Jiri Simsa | 1f1302c | 2015-02-23 16:18:34 -0800 | [diff] [blame] | 14 | "v.io/v23" |
| 15 | "v.io/v23/context" |
Shyam Jayaraman | 8e301b5 | 2015-04-27 14:12:16 -0700 | [diff] [blame] | 16 | "v.io/v23/i18n" |
Jiri Simsa | 1f1302c | 2015-02-23 16:18:34 -0800 | [diff] [blame] | 17 | "v.io/v23/naming" |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 18 | "v.io/v23/rpc" |
Jiri Simsa | 1f1302c | 2015-02-23 16:18:34 -0800 | [diff] [blame] | 19 | "v.io/v23/security" |
| 20 | "v.io/v23/vdl" |
Todd Wang | ac9e190 | 2015-02-25 01:58:01 -0800 | [diff] [blame] | 21 | "v.io/v23/vdlroot/signature" |
Shyam Jayaraman | 7efedbe | 2015-03-05 12:57:18 -0800 | [diff] [blame] | 22 | vdltime "v.io/v23/vdlroot/time" |
Jiri Simsa | 1f1302c | 2015-02-23 16:18:34 -0800 | [diff] [blame] | 23 | "v.io/v23/verror" |
Shyam Jayaraman | 3facd24 | 2015-05-29 11:20:59 -0700 | [diff] [blame] | 24 | "v.io/v23/vom" |
Matt Rosencrantz | e7bf2bc | 2015-03-13 09:54:27 -0700 | [diff] [blame] | 25 | "v.io/v23/vtrace" |
Todd Wang | 5b77a34 | 2015-04-06 18:31:37 -0700 | [diff] [blame] | 26 | "v.io/x/ref/services/wspr/internal/lib" |
| 27 | "v.io/x/ref/services/wspr/internal/principal" |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 28 | ) |
| 29 | |
| 30 | type Flow struct { |
Benjamin Prosnitz | 86d5228 | 2014-12-19 15:48:38 -0800 | [diff] [blame] | 31 | ID int32 |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 32 | Writer lib.ClientWriter |
| 33 | } |
| 34 | |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 35 | type FlowHandler interface { |
Benjamin Prosnitz | bf71e96 | 2015-04-14 16:43:07 -0700 | [diff] [blame] | 36 | CreateNewFlow(server interface{}, sender rpc.Stream) *Flow |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 37 | |
Benjamin Prosnitz | 86d5228 | 2014-12-19 15:48:38 -0800 | [diff] [blame] | 38 | CleanupFlow(id int32) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 39 | } |
| 40 | |
Shyam Jayaraman | 0062e27 | 2015-06-04 11:25:13 -0700 | [diff] [blame] | 41 | type VomHelper interface { |
| 42 | TypeEncoder() *vom.TypeEncoder |
| 43 | |
| 44 | TypeDecoder() *vom.TypeDecoder |
| 45 | } |
Benjamin Prosnitz | ae30020 | 2015-06-04 19:36:49 -0700 | [diff] [blame] | 46 | |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 47 | type ServerHelper interface { |
| 48 | FlowHandler |
Shyam Jayaraman | 0062e27 | 2015-06-04 11:25:13 -0700 | [diff] [blame] | 49 | VomHelper |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 50 | |
Shyam Jayaraman | c17abda | 2015-04-06 16:49:17 -0700 | [diff] [blame] | 51 | SendLogMessage(level lib.LogLevel, msg string) error |
Benjamin Prosnitz | c65917c | 2015-05-26 14:21:53 -0700 | [diff] [blame] | 52 | BlessingsCache() *principal.BlessingsCache |
Shyam Jayaraman | c17abda | 2015-04-06 16:49:17 -0700 | [diff] [blame] | 53 | |
Matt Rosencrantz | c90eb7b | 2015-01-09 08:32:01 -0800 | [diff] [blame] | 54 | Context() *context.T |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 55 | } |
| 56 | |
Shyam Jayaraman | 907219d | 2014-11-26 12:14:37 -0800 | [diff] [blame] | 57 | // AuthRequest is a request for a javascript authorizer to run |
| 58 | // This is exported to make the app test easier. |
| 59 | type AuthRequest struct { |
Benjamin Prosnitz | 2be28dc | 2015-03-11 13:33:22 -0700 | [diff] [blame] | 60 | ServerId uint32 `json:"serverId"` |
Shyam Jayaraman | 250aac3 | 2015-03-05 15:29:11 -0800 | [diff] [blame] | 61 | Handle int32 `json:"handle"` |
| 62 | Call SecurityCall `json:"call"` |
Shyam Jayaraman | 8e301b5 | 2015-04-27 14:12:16 -0700 | [diff] [blame] | 63 | Context Context |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 64 | } |
| 65 | |
| 66 | type Server struct { |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 67 | // serverStateLock should be aquired when starting or stopping the server. |
| 68 | // This should be locked before outstandingRequestLock. |
| 69 | serverStateLock sync.Mutex |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 70 | |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 71 | // The rpc.ListenSpec to use with server.Listen |
| 72 | listenSpec *rpc.ListenSpec |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 73 | |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 74 | // The server that handles the rpc layer. Listen on this server is |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 75 | // lazily started. |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 76 | server rpc.Server |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 77 | |
| 78 | // The saved dispatcher to reuse when serve is called multiple times. |
| 79 | dispatcher *dispatcher |
| 80 | |
Nicolas LaCasse | 27b57c7 | 2014-11-19 13:40:20 -0800 | [diff] [blame] | 81 | // Whether the server is listening. |
| 82 | isListening bool |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 83 | |
| 84 | // The server id. |
Benjamin Prosnitz | 86d5228 | 2014-12-19 15:48:38 -0800 | [diff] [blame] | 85 | id uint32 |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 86 | helper ServerHelper |
| 87 | |
Suharsh Sivakumar | 4cc7c2d | 2015-04-09 15:21:56 -0700 | [diff] [blame] | 88 | // outstandingRequestLock should be acquired only to update the outstanding request maps below. |
| 89 | outstandingRequestLock sync.Mutex |
| 90 | outstandingServerRequests map[int32]chan *lib.ServerRpcReply // GUARDED_BY outstandingRequestLock |
| 91 | outstandingAuthRequests map[int32]chan error // GUARDED_BY outstandingRequestLock |
| 92 | outstandingValidationRequests map[int32]chan []error // GUARDED_BY outstandingRequestLock |
Shyam Jayaraman | c17abda | 2015-04-06 16:49:17 -0700 | [diff] [blame] | 93 | |
| 94 | // statusClose will be closed when the server is shutting down, this will |
| 95 | // cause the status poller to exit. |
| 96 | statusClose chan struct{} |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 97 | |
| 98 | ctx *context.T |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 99 | } |
| 100 | |
Todd Wang | 555097f | 2015-04-21 10:49:06 -0700 | [diff] [blame] | 101 | type serverContextKey struct{} |
| 102 | |
Ali Ghassemi | bac3403 | 2015-04-30 18:27:57 -0700 | [diff] [blame] | 103 | func NewServer(id uint32, listenSpec *rpc.ListenSpec, helper ServerHelper, opts ...rpc.ServerOpt) (*Server, error) { |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 104 | server := &Server{ |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 105 | id: id, |
| 106 | helper: helper, |
| 107 | listenSpec: listenSpec, |
Todd Wang | baf1684 | 2015-03-16 14:12:29 -0700 | [diff] [blame] | 108 | outstandingServerRequests: make(map[int32]chan *lib.ServerRpcReply), |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 109 | outstandingAuthRequests: make(map[int32]chan error), |
| 110 | outstandingValidationRequests: make(map[int32]chan []error), |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 111 | } |
| 112 | var err error |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 113 | ctx := helper.Context() |
Todd Wang | 555097f | 2015-04-21 10:49:06 -0700 | [diff] [blame] | 114 | ctx = context.WithValue(ctx, serverContextKey{}, server) |
Ali Ghassemi | bac3403 | 2015-04-30 18:27:57 -0700 | [diff] [blame] | 115 | if server.server, err = v23.NewServer(ctx, opts...); err != nil { |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 116 | return nil, err |
| 117 | } |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 118 | server.ctx = ctx |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 119 | return server, nil |
| 120 | } |
| 121 | |
| 122 | // remoteInvokeFunc is a type of function that can invoke a remote method and |
| 123 | // communicate the result back via a channel to the caller |
Todd Wang | 54feabe | 2015-04-15 23:38:26 -0700 | [diff] [blame] | 124 | type remoteInvokeFunc func(ctx *context.T, call rpc.StreamServerCall, methodName string, args []interface{}) <-chan *lib.ServerRpcReply |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 125 | |
Benjamin Prosnitz | 86d5228 | 2014-12-19 15:48:38 -0800 | [diff] [blame] | 126 | func (s *Server) createRemoteInvokerFunc(handle int32) remoteInvokeFunc { |
Todd Wang | 54feabe | 2015-04-15 23:38:26 -0700 | [diff] [blame] | 127 | return func(ctx *context.T, call rpc.StreamServerCall, methodName string, args []interface{}) <-chan *lib.ServerRpcReply { |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 128 | securityCall := ConvertSecurityCall(s.helper, ctx, call.Security(), true) |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 129 | |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 130 | flow := s.helper.CreateNewFlow(s, call) |
Todd Wang | baf1684 | 2015-03-16 14:12:29 -0700 | [diff] [blame] | 131 | replyChan := make(chan *lib.ServerRpcReply, 1) |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 132 | s.outstandingRequestLock.Lock() |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 133 | s.outstandingServerRequests[flow.ID] = replyChan |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 134 | s.outstandingRequestLock.Unlock() |
Matt Rosencrantz | 4aabe57 | 2014-10-22 09:25:50 -0700 | [diff] [blame] | 135 | |
Shyam Jayaraman | 7efedbe | 2015-03-05 12:57:18 -0800 | [diff] [blame] | 136 | var timeout vdltime.Deadline |
Todd Wang | 54feabe | 2015-04-15 23:38:26 -0700 | [diff] [blame] | 137 | if deadline, ok := ctx.Deadline(); ok { |
Shyam Jayaraman | 7efedbe | 2015-03-05 12:57:18 -0800 | [diff] [blame] | 138 | timeout.Time = deadline |
Matt Rosencrantz | 4aabe57 | 2014-10-22 09:25:50 -0700 | [diff] [blame] | 139 | } |
| 140 | |
Todd Wang | baf1684 | 2015-03-16 14:12:29 -0700 | [diff] [blame] | 141 | errHandler := func(err error) <-chan *lib.ServerRpcReply { |
Matt Rosencrantz | 4aabe57 | 2014-10-22 09:25:50 -0700 | [diff] [blame] | 142 | if ch := s.popServerRequest(flow.ID); ch != nil { |
Todd Wang | 54feabe | 2015-04-15 23:38:26 -0700 | [diff] [blame] | 143 | stdErr := verror.Convert(verror.ErrInternal, ctx, err).(verror.E) |
Todd Wang | baf1684 | 2015-03-16 14:12:29 -0700 | [diff] [blame] | 144 | ch <- &lib.ServerRpcReply{nil, &stdErr, vtrace.Response{}} |
Matt Rosencrantz | 4aabe57 | 2014-10-22 09:25:50 -0700 | [diff] [blame] | 145 | s.helper.CleanupFlow(flow.ID) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 146 | } |
| 147 | return replyChan |
Shyam Jayaraman | c96e1aa | 2014-11-12 16:42:39 -0800 | [diff] [blame] | 148 | } |
Shyam Jayaraman | 907219d | 2014-11-26 12:14:37 -0800 | [diff] [blame] | 149 | |
Benjamin Prosnitz | c65917c | 2015-05-26 14:21:53 -0700 | [diff] [blame] | 150 | var grantedBlessings principal.BlessingsId |
Benjamin Prosnitz | bf71e96 | 2015-04-14 16:43:07 -0700 | [diff] [blame] | 151 | if !call.GrantedBlessings().IsZero() { |
Benjamin Prosnitz | ae30020 | 2015-06-04 19:36:49 -0700 | [diff] [blame] | 152 | grantedBlessings = s.helper.BlessingsCache().Put(call.GrantedBlessings()) |
Shyam Jayaraman | 907219d | 2014-11-26 12:14:37 -0800 | [diff] [blame] | 153 | } |
Benjamin Prosnitz | bf71e96 | 2015-04-14 16:43:07 -0700 | [diff] [blame] | 154 | |
| 155 | rpcCall := ServerRpcRequestCall{ |
Shyam Jayaraman | 8e301b5 | 2015-04-27 14:12:16 -0700 | [diff] [blame] | 156 | SecurityCall: securityCall, |
| 157 | Deadline: timeout, |
| 158 | TraceRequest: vtrace.GetRequest(ctx), |
| 159 | Context: Context{ |
| 160 | Language: string(i18n.GetLangID(ctx)), |
| 161 | }, |
Benjamin Prosnitz | bf71e96 | 2015-04-14 16:43:07 -0700 | [diff] [blame] | 162 | GrantedBlessings: grantedBlessings, |
| 163 | } |
| 164 | |
| 165 | var vdlValArgs []*vdl.Value = make([]*vdl.Value, len(args)) |
| 166 | for i, arg := range args { |
Benjamin Prosnitz | bf71e96 | 2015-04-14 16:43:07 -0700 | [diff] [blame] | 167 | vdlValArgs[i] = vdl.ValueOf(arg) |
Shyam Jayaraman | 07136a7 | 2015-04-13 13:34:41 -0700 | [diff] [blame] | 168 | } |
Benjamin Prosnitz | bf71e96 | 2015-04-14 16:43:07 -0700 | [diff] [blame] | 169 | |
Shyam Jayaraman | 907219d | 2014-11-26 12:14:37 -0800 | [diff] [blame] | 170 | // Send a invocation request to JavaScript |
Benjamin Prosnitz | bf71e96 | 2015-04-14 16:43:07 -0700 | [diff] [blame] | 171 | message := ServerRpcRequest{ |
Shyam Jayaraman | 907219d | 2014-11-26 12:14:37 -0800 | [diff] [blame] | 172 | ServerId: s.id, |
| 173 | Handle: handle, |
| 174 | Method: lib.LowercaseFirstCharacter(methodName), |
Benjamin Prosnitz | bf71e96 | 2015-04-14 16:43:07 -0700 | [diff] [blame] | 175 | Args: vdlValArgs, |
Shyam Jayaraman | 250aac3 | 2015-03-05 15:29:11 -0800 | [diff] [blame] | 176 | Call: rpcCall, |
Shyam Jayaraman | 907219d | 2014-11-26 12:14:37 -0800 | [diff] [blame] | 177 | } |
Shyam Jayaraman | 0062e27 | 2015-06-04 11:25:13 -0700 | [diff] [blame] | 178 | vomMessage, err := lib.HexVomEncode(message, s.helper.TypeEncoder()) |
Shyam Jayaraman | c96e1aa | 2014-11-12 16:42:39 -0800 | [diff] [blame] | 179 | if err != nil { |
| 180 | return errHandler(err) |
| 181 | } |
Shyam Jayaraman | 907219d | 2014-11-26 12:14:37 -0800 | [diff] [blame] | 182 | if err := flow.Writer.Send(lib.ResponseServerRequest, vomMessage); err != nil { |
Shyam Jayaraman | c96e1aa | 2014-11-12 16:42:39 -0800 | [diff] [blame] | 183 | return errHandler(err) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 184 | } |
| 185 | |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 186 | ctx.VI(3).Infof("calling method %q with args %v, MessageID %d assigned\n", methodName, args, flow.ID) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 187 | |
Matt Rosencrantz | 4aabe57 | 2014-10-22 09:25:50 -0700 | [diff] [blame] | 188 | // Watch for cancellation. |
| 189 | go func() { |
Todd Wang | 54feabe | 2015-04-15 23:38:26 -0700 | [diff] [blame] | 190 | <-ctx.Done() |
Matt Rosencrantz | 4aabe57 | 2014-10-22 09:25:50 -0700 | [diff] [blame] | 191 | ch := s.popServerRequest(flow.ID) |
| 192 | if ch == nil { |
| 193 | return |
| 194 | } |
| 195 | |
| 196 | // Send a cancel message to the JS server. |
| 197 | flow.Writer.Send(lib.ResponseCancel, nil) |
| 198 | s.helper.CleanupFlow(flow.ID) |
| 199 | |
Todd Wang | 54feabe | 2015-04-15 23:38:26 -0700 | [diff] [blame] | 200 | err := verror.Convert(verror.ErrAborted, ctx, ctx.Err()).(verror.E) |
Todd Wang | baf1684 | 2015-03-16 14:12:29 -0700 | [diff] [blame] | 201 | ch <- &lib.ServerRpcReply{nil, &err, vtrace.Response{}} |
Matt Rosencrantz | 4aabe57 | 2014-10-22 09:25:50 -0700 | [diff] [blame] | 202 | }() |
| 203 | |
Benjamin Prosnitz | ae30020 | 2015-06-04 19:36:49 -0700 | [diff] [blame] | 204 | go s.proxyStream(call, flow, s.helper.TypeEncoder()) |
Matt Rosencrantz | 4aabe57 | 2014-10-22 09:25:50 -0700 | [diff] [blame] | 205 | |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 206 | return replyChan |
| 207 | } |
| 208 | } |
| 209 | |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 210 | type globStream struct { |
Todd Wang | 2331dd0 | 2015-03-17 15:38:39 -0700 | [diff] [blame] | 211 | ch chan naming.GlobReply |
Matt Rosencrantz | 99ed678 | 2015-01-27 19:58:34 -0800 | [diff] [blame] | 212 | ctx *context.T |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 213 | } |
| 214 | |
| 215 | func (g *globStream) Send(item interface{}) error { |
Todd Wang | 2331dd0 | 2015-03-17 15:38:39 -0700 | [diff] [blame] | 216 | if v, ok := item.(naming.GlobReply); ok { |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 217 | g.ch <- v |
| 218 | return nil |
| 219 | } |
Jiri Simsa | 94f68d0 | 2015-02-17 10:22:08 -0800 | [diff] [blame] | 220 | return verror.New(verror.ErrBadArg, g.ctx, item) |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 221 | } |
| 222 | |
| 223 | func (g *globStream) Recv(itemptr interface{}) error { |
Jiri Simsa | 94f68d0 | 2015-02-17 10:22:08 -0800 | [diff] [blame] | 224 | return verror.New(verror.ErrNoExist, g.ctx, "Can't call recieve on glob stream") |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 225 | } |
| 226 | |
| 227 | func (g *globStream) CloseSend() error { |
| 228 | close(g.ch) |
| 229 | return nil |
| 230 | } |
| 231 | |
| 232 | // remoteGlobFunc is a type of function that can invoke a remote glob and |
| 233 | // communicate the result back via the channel returned |
Todd Wang | 54feabe | 2015-04-15 23:38:26 -0700 | [diff] [blame] | 234 | type remoteGlobFunc func(ctx *context.T, call rpc.ServerCall, pattern string) (<-chan naming.GlobReply, error) |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 235 | |
| 236 | func (s *Server) createRemoteGlobFunc(handle int32) remoteGlobFunc { |
Todd Wang | 54feabe | 2015-04-15 23:38:26 -0700 | [diff] [blame] | 237 | return func(ctx *context.T, call rpc.ServerCall, pattern string) (<-chan naming.GlobReply, error) { |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 238 | // Until the tests get fixed, we need to create a security context before creating the flow |
| 239 | // because creating the security context creates a flow and flow ids will be off. |
Suharsh Sivakumar | 78b2bd8 | 2015-04-22 19:15:46 -0700 | [diff] [blame] | 240 | // See https://github.com/vanadium/issues/issues/175 |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 241 | securityCall := ConvertSecurityCall(s.helper, ctx, call.Security(), true) |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 242 | |
Todd Wang | 2331dd0 | 2015-03-17 15:38:39 -0700 | [diff] [blame] | 243 | globChan := make(chan naming.GlobReply, 1) |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 244 | flow := s.helper.CreateNewFlow(s, &globStream{ |
Matt Rosencrantz | 99ed678 | 2015-01-27 19:58:34 -0800 | [diff] [blame] | 245 | ch: globChan, |
Todd Wang | 54feabe | 2015-04-15 23:38:26 -0700 | [diff] [blame] | 246 | ctx: ctx, |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 247 | }) |
Todd Wang | baf1684 | 2015-03-16 14:12:29 -0700 | [diff] [blame] | 248 | replyChan := make(chan *lib.ServerRpcReply, 1) |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 249 | s.outstandingRequestLock.Lock() |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 250 | s.outstandingServerRequests[flow.ID] = replyChan |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 251 | s.outstandingRequestLock.Unlock() |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 252 | |
Shyam Jayaraman | 7efedbe | 2015-03-05 12:57:18 -0800 | [diff] [blame] | 253 | var timeout vdltime.Deadline |
Todd Wang | 54feabe | 2015-04-15 23:38:26 -0700 | [diff] [blame] | 254 | if deadline, ok := ctx.Deadline(); ok { |
Shyam Jayaraman | 7efedbe | 2015-03-05 12:57:18 -0800 | [diff] [blame] | 255 | timeout.Time = deadline |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 256 | } |
| 257 | |
Todd Wang | 2331dd0 | 2015-03-17 15:38:39 -0700 | [diff] [blame] | 258 | errHandler := func(err error) (<-chan naming.GlobReply, error) { |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 259 | if ch := s.popServerRequest(flow.ID); ch != nil { |
| 260 | s.helper.CleanupFlow(flow.ID) |
| 261 | } |
Todd Wang | 54feabe | 2015-04-15 23:38:26 -0700 | [diff] [blame] | 262 | return nil, verror.Convert(verror.ErrInternal, ctx, err).(verror.E) |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 263 | } |
| 264 | |
Benjamin Prosnitz | bf71e96 | 2015-04-14 16:43:07 -0700 | [diff] [blame] | 265 | rpcCall := ServerRpcRequestCall{ |
| 266 | SecurityCall: securityCall, |
| 267 | Deadline: timeout, |
Benjamin Prosnitz | ae30020 | 2015-06-04 19:36:49 -0700 | [diff] [blame] | 268 | GrantedBlessings: s.helper.BlessingsCache().Put(call.GrantedBlessings()), |
Shyam Jayaraman | 8e301b5 | 2015-04-27 14:12:16 -0700 | [diff] [blame] | 269 | Context: Context{ |
| 270 | Language: string(i18n.GetLangID(ctx)), |
| 271 | }, |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 272 | } |
| 273 | |
| 274 | // Send a invocation request to JavaScript |
Benjamin Prosnitz | bf71e96 | 2015-04-14 16:43:07 -0700 | [diff] [blame] | 275 | message := ServerRpcRequest{ |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 276 | ServerId: s.id, |
| 277 | Handle: handle, |
| 278 | Method: "Glob__", |
Benjamin Prosnitz | bf71e96 | 2015-04-14 16:43:07 -0700 | [diff] [blame] | 279 | Args: []*vdl.Value{vdl.ValueOf(pattern)}, |
Shyam Jayaraman | 250aac3 | 2015-03-05 15:29:11 -0800 | [diff] [blame] | 280 | Call: rpcCall, |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 281 | } |
Shyam Jayaraman | 0062e27 | 2015-06-04 11:25:13 -0700 | [diff] [blame] | 282 | vomMessage, err := lib.HexVomEncode(message, s.helper.TypeEncoder()) |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 283 | if err != nil { |
| 284 | return errHandler(err) |
| 285 | } |
| 286 | if err := flow.Writer.Send(lib.ResponseServerRequest, vomMessage); err != nil { |
| 287 | return errHandler(err) |
| 288 | } |
| 289 | |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 290 | ctx.VI(3).Infof("calling method 'Glob__' with args %v, MessageID %d assigned\n", []interface{}{pattern}, flow.ID) |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 291 | |
| 292 | // Watch for cancellation. |
| 293 | go func() { |
Todd Wang | 54feabe | 2015-04-15 23:38:26 -0700 | [diff] [blame] | 294 | <-ctx.Done() |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 295 | ch := s.popServerRequest(flow.ID) |
| 296 | if ch == nil { |
| 297 | return |
| 298 | } |
| 299 | |
| 300 | // Send a cancel message to the JS server. |
| 301 | flow.Writer.Send(lib.ResponseCancel, nil) |
| 302 | s.helper.CleanupFlow(flow.ID) |
| 303 | |
Todd Wang | 54feabe | 2015-04-15 23:38:26 -0700 | [diff] [blame] | 304 | err := verror.Convert(verror.ErrAborted, ctx, ctx.Err()).(verror.E) |
Todd Wang | baf1684 | 2015-03-16 14:12:29 -0700 | [diff] [blame] | 305 | ch <- &lib.ServerRpcReply{nil, &err, vtrace.Response{}} |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 306 | }() |
| 307 | |
| 308 | return globChan, nil |
| 309 | } |
| 310 | } |
| 311 | |
Benjamin Prosnitz | ae30020 | 2015-06-04 19:36:49 -0700 | [diff] [blame] | 312 | func (s *Server) proxyStream(stream rpc.Stream, flow *Flow, typeEncoder *vom.TypeEncoder) { |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 313 | var item interface{} |
Benjamin Prosnitz | c65917c | 2015-05-26 14:21:53 -0700 | [diff] [blame] | 314 | var err error |
Shyam Jayaraman | dc07fc5 | 2015-05-29 15:32:22 -0700 | [diff] [blame] | 315 | w := flow.Writer |
Benjamin Prosnitz | c65917c | 2015-05-26 14:21:53 -0700 | [diff] [blame] | 316 | for err = stream.Recv(&item); err == nil; err = stream.Recv(&item) { |
Shyam Jayaraman | 3facd24 | 2015-05-29 11:20:59 -0700 | [diff] [blame] | 317 | vomItem, err := lib.HexVomEncode(item, typeEncoder) |
Shyam Jayaraman | c96e1aa | 2014-11-12 16:42:39 -0800 | [diff] [blame] | 318 | if err != nil { |
Jiri Simsa | 94f68d0 | 2015-02-17 10:22:08 -0800 | [diff] [blame] | 319 | w.Error(verror.Convert(verror.ErrInternal, nil, err)) |
Shyam Jayaraman | c96e1aa | 2014-11-12 16:42:39 -0800 | [diff] [blame] | 320 | return |
| 321 | } |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 322 | if err := w.Send(lib.ResponseStream, vomItem); err != nil { |
Jiri Simsa | 94f68d0 | 2015-02-17 10:22:08 -0800 | [diff] [blame] | 323 | w.Error(verror.Convert(verror.ErrInternal, nil, err)) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 324 | return |
| 325 | } |
| 326 | } |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 327 | s.ctx.VI(1).Infof("Error reading from stream: %v\n", err) |
Shyam Jayaraman | dc07fc5 | 2015-05-29 15:32:22 -0700 | [diff] [blame] | 328 | s.outstandingRequestLock.Lock() |
| 329 | _, found := s.outstandingServerRequests[flow.ID] |
| 330 | s.outstandingRequestLock.Unlock() |
| 331 | |
| 332 | if !found { |
| 333 | // The flow has already been closed. This is usually because we got a response |
| 334 | // from the javascript server. |
| 335 | return |
| 336 | } |
Benjamin Prosnitz | c65917c | 2015-05-26 14:21:53 -0700 | [diff] [blame] | 337 | |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 338 | if err := w.Send(lib.ResponseStreamClose, nil); err != nil { |
Jiri Simsa | 94f68d0 | 2015-02-17 10:22:08 -0800 | [diff] [blame] | 339 | w.Error(verror.Convert(verror.ErrInternal, nil, err)) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 340 | return |
| 341 | } |
| 342 | } |
| 343 | |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 344 | func makeListOfErrors(numErrors int, err error) []error { |
| 345 | errs := make([]error, numErrors) |
| 346 | for i := 0; i < numErrors; i++ { |
| 347 | errs[i] = err |
Shyam Jayaraman | a42622c | 2015-01-05 16:55:53 -0800 | [diff] [blame] | 348 | } |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 349 | return errs |
| 350 | } |
| 351 | |
Todd Wang | 555097f | 2015-04-21 10:49:06 -0700 | [diff] [blame] | 352 | // caveatValidationInGo validates caveats in Go, using the default logic. |
| 353 | func caveatValidationInGo(ctx *context.T, call security.Call, sets [][]security.Caveat) []error { |
| 354 | results := make([]error, len(sets)) |
| 355 | for i, set := range sets { |
| 356 | for _, cav := range set { |
| 357 | if err := cav.Validate(ctx, call); err != nil { |
| 358 | results[i] = err |
| 359 | break |
| 360 | } |
| 361 | } |
| 362 | } |
| 363 | return results |
| 364 | } |
| 365 | |
| 366 | // caveatValidationInJavascript validates caveats in javascript. It resolves |
| 367 | // each []security.Caveat in cavs to an error (or nil) and collects them in a |
| 368 | // slice. |
| 369 | func (s *Server) caveatValidationInJavascript(ctx *context.T, call security.Call, cavs [][]security.Caveat) []error { |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 370 | flow := s.helper.CreateNewFlow(s, nil) |
| 371 | req := CaveatValidationRequest{ |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 372 | Call: ConvertSecurityCall(s.helper, ctx, call, false), |
Shyam Jayaraman | 8e301b5 | 2015-04-27 14:12:16 -0700 | [diff] [blame] | 373 | Context: Context{ |
| 374 | Language: string(i18n.GetLangID(ctx)), |
| 375 | }, |
Ankur | ef39ba8 | 2015-03-19 13:34:03 -0700 | [diff] [blame] | 376 | Cavs: cavs, |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 377 | } |
| 378 | |
| 379 | replyChan := make(chan []error, 1) |
| 380 | s.outstandingRequestLock.Lock() |
| 381 | s.outstandingValidationRequests[flow.ID] = replyChan |
| 382 | s.outstandingRequestLock.Unlock() |
| 383 | |
| 384 | defer func() { |
| 385 | s.outstandingRequestLock.Lock() |
| 386 | delete(s.outstandingValidationRequests, flow.ID) |
| 387 | s.outstandingRequestLock.Unlock() |
| 388 | s.cleanupFlow(flow.ID) |
| 389 | }() |
| 390 | |
| 391 | if err := flow.Writer.Send(lib.ResponseValidate, req); err != nil { |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 392 | ctx.VI(2).Infof("Failed to send validate response: %v", err) |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 393 | replyChan <- makeListOfErrors(len(cavs), err) |
| 394 | } |
| 395 | |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 396 | // TODO(bprosnitz) Consider using a different timeout than the standard rpc timeout. |
Todd Wang | f6a0688 | 2015-02-27 17:38:01 -0800 | [diff] [blame] | 397 | var timeoutChan <-chan time.Time |
Matt Rosencrantz | 317b0c5 | 2015-03-24 20:47:01 -0700 | [diff] [blame] | 398 | if deadline, ok := ctx.Deadline(); ok { |
Todd Wang | f6a0688 | 2015-02-27 17:38:01 -0800 | [diff] [blame] | 399 | timeoutChan = time.After(deadline.Sub(time.Now())) |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 400 | } |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 401 | |
| 402 | select { |
Shyam Jayaraman | f0a995c | 2015-04-21 17:34:38 -0700 | [diff] [blame] | 403 | case <-s.statusClose: |
| 404 | return caveatValidationInGo(ctx, call, cavs) |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 405 | case <-timeoutChan: |
Matt Rosencrantz | 317b0c5 | 2015-03-24 20:47:01 -0700 | [diff] [blame] | 406 | return makeListOfErrors(len(cavs), NewErrCaveatValidationTimeout(ctx)) |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 407 | case reply := <-replyChan: |
| 408 | if len(reply) != len(cavs) { |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 409 | ctx.VI(2).Infof("Wspr caveat validator received %d results from javascript but expected %d", len(reply), len(cavs)) |
Matt Rosencrantz | 317b0c5 | 2015-03-24 20:47:01 -0700 | [diff] [blame] | 410 | return makeListOfErrors(len(cavs), NewErrInvalidValidationResponseFromJavascript(ctx)) |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 411 | } |
| 412 | |
| 413 | return reply |
| 414 | } |
| 415 | } |
| 416 | |
Todd Wang | 555097f | 2015-04-21 10:49:06 -0700 | [diff] [blame] | 417 | // CaveatValidation implements a function suitable for passing to |
| 418 | // security.OverrideCaveatValidation. |
| 419 | // |
Suharsh Sivakumar | 60b78e9 | 2015-04-23 21:36:49 -0700 | [diff] [blame] | 420 | // Certain caveats (PublicKeyThirdPartyCaveat) are intercepted and handled in |
Todd Wang | 555097f | 2015-04-21 10:49:06 -0700 | [diff] [blame] | 421 | // go, while all other caveats are evaluated in javascript. |
| 422 | func CaveatValidation(ctx *context.T, call security.Call, cavs [][]security.Caveat) []error { |
| 423 | // If the server isn't set in the context, we just perform validation in Go. |
| 424 | ctxServer := ctx.Value(serverContextKey{}) |
| 425 | if ctxServer == nil { |
| 426 | return caveatValidationInGo(ctx, call, cavs) |
| 427 | } |
| 428 | // Otherwise we run our special logic. |
| 429 | server := ctxServer.(*Server) |
Benjamin Prosnitz | 2c8c237 | 2015-03-13 12:03:08 -0700 | [diff] [blame] | 430 | type validationStatus struct { |
| 431 | err error |
| 432 | isSet bool |
| 433 | } |
| 434 | valStatus := make([]validationStatus, len(cavs)) |
| 435 | |
| 436 | var caveatChainsToValidate [][]security.Caveat |
| 437 | nextCav: |
| 438 | for i, chainCavs := range cavs { |
| 439 | var newChainCavs []security.Caveat |
| 440 | for _, cav := range chainCavs { |
Suharsh Sivakumar | bc74089 | 2015-04-17 10:54:17 -0700 | [diff] [blame] | 441 | // If the server is closed handle all caveats in Go, because Javascript is |
| 442 | // no longer there. |
| 443 | select { |
Todd Wang | 555097f | 2015-04-21 10:49:06 -0700 | [diff] [blame] | 444 | case <-server.statusClose: |
Suharsh Sivakumar | bc74089 | 2015-04-17 10:54:17 -0700 | [diff] [blame] | 445 | res := cav.Validate(ctx, call) |
| 446 | if res != nil { |
| 447 | valStatus[i] = validationStatus{ |
| 448 | err: res, |
| 449 | isSet: true, |
| 450 | } |
| 451 | continue nextCav |
| 452 | } |
| 453 | default: |
| 454 | } |
Benjamin Prosnitz | 2c8c237 | 2015-03-13 12:03:08 -0700 | [diff] [blame] | 455 | switch cav.Id { |
Suharsh Sivakumar | 60b78e9 | 2015-04-23 21:36:49 -0700 | [diff] [blame] | 456 | case security.PublicKeyThirdPartyCaveat.Id: |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 457 | res := cav.Validate(ctx, call) |
Benjamin Prosnitz | 2c8c237 | 2015-03-13 12:03:08 -0700 | [diff] [blame] | 458 | if res != nil { |
| 459 | valStatus[i] = validationStatus{ |
| 460 | err: res, |
| 461 | isSet: true, |
| 462 | } |
| 463 | continue nextCav |
| 464 | } |
| 465 | default: |
| 466 | newChainCavs = append(newChainCavs, cav) |
| 467 | } |
| 468 | } |
| 469 | if len(newChainCavs) == 0 { |
| 470 | valStatus[i] = validationStatus{ |
| 471 | err: nil, |
| 472 | isSet: true, |
| 473 | } |
| 474 | } else { |
| 475 | caveatChainsToValidate = append(caveatChainsToValidate, newChainCavs) |
| 476 | } |
| 477 | } |
| 478 | |
Todd Wang | 555097f | 2015-04-21 10:49:06 -0700 | [diff] [blame] | 479 | jsRes := server.caveatValidationInJavascript(ctx, call, caveatChainsToValidate) |
Benjamin Prosnitz | 2c8c237 | 2015-03-13 12:03:08 -0700 | [diff] [blame] | 480 | |
| 481 | outResults := make([]error, len(cavs)) |
| 482 | jsIndex := 0 |
| 483 | for i, status := range valStatus { |
| 484 | if status.isSet { |
| 485 | outResults[i] = status.err |
| 486 | } else { |
| 487 | outResults[i] = jsRes[jsIndex] |
| 488 | jsIndex++ |
| 489 | } |
| 490 | } |
| 491 | |
| 492 | return outResults |
| 493 | } |
| 494 | |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 495 | func ConvertSecurityCall(helper ServerHelper, ctx *context.T, call security.Call, includeBlessingStrings bool) SecurityCall { |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 496 | var localEndpoint string |
Matt Rosencrantz | 9dce9b2 | 2015-03-02 10:48:37 -0800 | [diff] [blame] | 497 | if call.LocalEndpoint() != nil { |
| 498 | localEndpoint = call.LocalEndpoint().String() |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 499 | } |
| 500 | var remoteEndpoint string |
Matt Rosencrantz | 9dce9b2 | 2015-03-02 10:48:37 -0800 | [diff] [blame] | 501 | if call.RemoteEndpoint() != nil { |
| 502 | remoteEndpoint = call.RemoteEndpoint().String() |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 503 | } |
Matt Rosencrantz | 9dce9b2 | 2015-03-02 10:48:37 -0800 | [diff] [blame] | 504 | anymtags := make([]*vdl.Value, len(call.MethodTags())) |
| 505 | for i, mtag := range call.MethodTags() { |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 506 | anymtags[i] = mtag |
| 507 | } |
Matt Rosencrantz | 250558f | 2015-03-17 11:37:31 -0700 | [diff] [blame] | 508 | secCall := SecurityCall{ |
Matt Rosencrantz | 9dce9b2 | 2015-03-02 10:48:37 -0800 | [diff] [blame] | 509 | Method: lib.LowercaseFirstCharacter(call.Method()), |
| 510 | Suffix: call.Suffix(), |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 511 | MethodTags: anymtags, |
| 512 | LocalEndpoint: localEndpoint, |
| 513 | RemoteEndpoint: remoteEndpoint, |
Benjamin Prosnitz | ae30020 | 2015-06-04 19:36:49 -0700 | [diff] [blame] | 514 | LocalBlessings: helper.BlessingsCache().Put(call.LocalBlessings()), |
| 515 | RemoteBlessings: helper.BlessingsCache().Put(call.RemoteBlessings()), |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 516 | } |
| 517 | if includeBlessingStrings { |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 518 | secCall.LocalBlessingStrings = security.LocalBlessingNames(ctx, call) |
| 519 | secCall.RemoteBlessingStrings, _ = security.RemoteBlessingNames(ctx, call) |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 520 | } |
Matt Rosencrantz | 250558f | 2015-03-17 11:37:31 -0700 | [diff] [blame] | 521 | return secCall |
Shyam Jayaraman | a42622c | 2015-01-05 16:55:53 -0800 | [diff] [blame] | 522 | } |
| 523 | |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 524 | type remoteAuth struct { |
| 525 | Func func(*context.T, security.Call, int32) error |
| 526 | Handle int32 |
| 527 | } |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 528 | |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 529 | func (r remoteAuth) Authorize(ctx *context.T, call security.Call) error { |
| 530 | return r.Func(ctx, call, r.Handle) |
| 531 | } |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 532 | |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 533 | func (s *Server) createRemoteAuthorizer(handle int32) security.Authorizer { |
| 534 | return remoteAuth{s.authorizeRemote, handle} |
| 535 | } |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 536 | |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 537 | func (s *Server) authorizeRemote(ctx *context.T, call security.Call, handle int32) error { |
| 538 | // Until the tests get fixed, we need to create a security context before |
| 539 | // creating the flow because creating the security context creates a flow and |
| 540 | // flow ids will be off. |
| 541 | securityCall := ConvertSecurityCall(s.helper, ctx, call, true) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 542 | |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 543 | flow := s.helper.CreateNewFlow(s, nil) |
| 544 | replyChan := make(chan error, 1) |
| 545 | s.outstandingRequestLock.Lock() |
| 546 | s.outstandingAuthRequests[flow.ID] = replyChan |
| 547 | s.outstandingRequestLock.Unlock() |
| 548 | message := AuthRequest{ |
| 549 | ServerId: s.id, |
| 550 | Handle: handle, |
| 551 | Call: securityCall, |
Shyam Jayaraman | 8e301b5 | 2015-04-27 14:12:16 -0700 | [diff] [blame] | 552 | Context: Context{ |
| 553 | Language: string(i18n.GetLangID(ctx)), |
| 554 | }, |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 555 | } |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 556 | ctx.VI(0).Infof("Sending out auth request for %v, %v", flow.ID, message) |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 557 | |
Shyam Jayaraman | 0062e27 | 2015-06-04 11:25:13 -0700 | [diff] [blame] | 558 | vomMessage, err := lib.HexVomEncode(message, s.helper.TypeEncoder()) |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 559 | if err != nil { |
| 560 | replyChan <- verror.Convert(verror.ErrInternal, nil, err) |
| 561 | } else if err := flow.Writer.Send(lib.ResponseAuthRequest, vomMessage); err != nil { |
| 562 | replyChan <- verror.Convert(verror.ErrInternal, nil, err) |
| 563 | } |
| 564 | |
| 565 | err = <-replyChan |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 566 | ctx.VI(0).Infof("going to respond with %v", err) |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 567 | s.outstandingRequestLock.Lock() |
| 568 | delete(s.outstandingAuthRequests, flow.ID) |
| 569 | s.outstandingRequestLock.Unlock() |
| 570 | s.helper.CleanupFlow(flow.ID) |
| 571 | return err |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 572 | } |
| 573 | |
Shyam Jayaraman | c17abda | 2015-04-06 16:49:17 -0700 | [diff] [blame] | 574 | func (s *Server) readStatus() { |
| 575 | // A map of names to the last error message sent. |
| 576 | lastErrors := map[string]string{} |
| 577 | for { |
| 578 | status := s.server.Status() |
| 579 | for _, mountStatus := range status.Mounts { |
| 580 | var errMsg string |
| 581 | if mountStatus.LastMountErr != nil { |
| 582 | errMsg = mountStatus.LastMountErr.Error() |
| 583 | } |
| 584 | mountName := mountStatus.Name |
| 585 | if lastMessage, ok := lastErrors[mountName]; !ok || errMsg != lastMessage { |
| 586 | if errMsg == "" { |
| 587 | s.helper.SendLogMessage( |
| 588 | lib.LogLevelInfo, "serve: "+mountName+" successfully mounted ") |
| 589 | } else { |
| 590 | s.helper.SendLogMessage( |
| 591 | lib.LogLevelError, "serve: "+mountName+" failed with: "+errMsg) |
| 592 | } |
| 593 | } |
| 594 | lastErrors[mountName] = errMsg |
| 595 | } |
| 596 | select { |
| 597 | case <-time.After(10 * time.Second): |
| 598 | continue |
| 599 | case <-s.statusClose: |
| 600 | return |
| 601 | } |
| 602 | } |
| 603 | } |
| 604 | |
Nicolas LaCasse | 27b57c7 | 2014-11-19 13:40:20 -0800 | [diff] [blame] | 605 | func (s *Server) Serve(name string) error { |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 606 | s.serverStateLock.Lock() |
| 607 | defer s.serverStateLock.Unlock() |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 608 | |
| 609 | if s.dispatcher == nil { |
Shyam Jayaraman | 0062e27 | 2015-06-04 11:25:13 -0700 | [diff] [blame] | 610 | s.dispatcher = newDispatcher(s.id, s, s, s, s.helper) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 611 | } |
| 612 | |
Nicolas LaCasse | 27b57c7 | 2014-11-19 13:40:20 -0800 | [diff] [blame] | 613 | if !s.isListening { |
| 614 | _, err := s.server.Listen(*s.listenSpec) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 615 | if err != nil { |
Nicolas LaCasse | 27b57c7 | 2014-11-19 13:40:20 -0800 | [diff] [blame] | 616 | return err |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 617 | } |
Nicolas LaCasse | 27b57c7 | 2014-11-19 13:40:20 -0800 | [diff] [blame] | 618 | s.isListening = true |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 619 | } |
Cosmos Nicolaou | 89303d6 | 2014-11-02 12:58:11 -0800 | [diff] [blame] | 620 | if err := s.server.ServeDispatcher(name, s.dispatcher); err != nil { |
Nicolas LaCasse | 27b57c7 | 2014-11-19 13:40:20 -0800 | [diff] [blame] | 621 | return err |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 622 | } |
Shyam Jayaraman | c17abda | 2015-04-06 16:49:17 -0700 | [diff] [blame] | 623 | s.statusClose = make(chan struct{}, 1) |
| 624 | go s.readStatus() |
Nicolas LaCasse | 27b57c7 | 2014-11-19 13:40:20 -0800 | [diff] [blame] | 625 | return nil |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 626 | } |
| 627 | |
Todd Wang | baf1684 | 2015-03-16 14:12:29 -0700 | [diff] [blame] | 628 | func (s *Server) popServerRequest(id int32) chan *lib.ServerRpcReply { |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 629 | s.outstandingRequestLock.Lock() |
| 630 | defer s.outstandingRequestLock.Unlock() |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 631 | ch := s.outstandingServerRequests[id] |
| 632 | delete(s.outstandingServerRequests, id) |
Matt Rosencrantz | 4aabe57 | 2014-10-22 09:25:50 -0700 | [diff] [blame] | 633 | |
| 634 | return ch |
| 635 | } |
| 636 | |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 637 | func (s *Server) HandleServerResponse(ctx *context.T, id int32, data string) { |
Matt Rosencrantz | 4aabe57 | 2014-10-22 09:25:50 -0700 | [diff] [blame] | 638 | ch := s.popServerRequest(id) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 639 | if ch == nil { |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 640 | ctx.Errorf("unexpected result from JavaScript. No channel "+ |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 641 | "for MessageId: %d exists. Ignoring the results.", id) |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 642 | // Ignore unknown responses that don't belong to any channel |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 643 | return |
| 644 | } |
Matt Rosencrantz | 4aabe57 | 2014-10-22 09:25:50 -0700 | [diff] [blame] | 645 | |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 646 | // Decode the result and send it through the channel |
Todd Wang | baf1684 | 2015-03-16 14:12:29 -0700 | [diff] [blame] | 647 | var reply lib.ServerRpcReply |
Shyam Jayaraman | 0062e27 | 2015-06-04 11:25:13 -0700 | [diff] [blame] | 648 | if err := lib.HexVomDecode(data, &reply, s.helper.TypeDecoder()); err != nil { |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 649 | reply.Err = err |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 650 | } |
| 651 | |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 652 | ctx.VI(0).Infof("response received from JavaScript server for "+ |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 653 | "MessageId %d with result %v", id, reply) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 654 | s.helper.CleanupFlow(id) |
Shyam Jayaraman | 07136a7 | 2015-04-13 13:34:41 -0700 | [diff] [blame] | 655 | if reply.Err != nil { |
| 656 | ch <- &reply |
| 657 | return |
| 658 | } |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 659 | ch <- &reply |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 660 | } |
| 661 | |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 662 | func (s *Server) HandleLookupResponse(ctx *context.T, id int32, data string) { |
| 663 | s.dispatcher.handleLookupResponse(ctx, id, data) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 664 | } |
| 665 | |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 666 | func (s *Server) HandleAuthResponse(ctx *context.T, id int32, data string) { |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 667 | s.outstandingRequestLock.Lock() |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 668 | ch := s.outstandingAuthRequests[id] |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 669 | s.outstandingRequestLock.Unlock() |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 670 | if ch == nil { |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 671 | ctx.Errorf("unexpected result from JavaScript. No channel "+ |
Shyam Jayaraman | e56df9a | 2014-11-20 17:38:54 -0800 | [diff] [blame] | 672 | "for MessageId: %d exists. Ignoring the results(%s)", id, data) |
Suharsh Sivakumar | 4cc7c2d | 2015-04-09 15:21:56 -0700 | [diff] [blame] | 673 | // Ignore unknown responses that don't belong to any channel |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 674 | return |
| 675 | } |
| 676 | // Decode the result and send it through the channel |
Nicolas Lacasse | fb931a2 | 2015-05-13 16:11:29 -0700 | [diff] [blame] | 677 | var reply AuthReply |
Shyam Jayaraman | 0062e27 | 2015-06-04 11:25:13 -0700 | [diff] [blame] | 678 | if err := lib.HexVomDecode(data, &reply, s.helper.TypeDecoder()); err != nil { |
Nicolas Lacasse | fb931a2 | 2015-05-13 16:11:29 -0700 | [diff] [blame] | 679 | err = verror.Convert(verror.ErrInternal, nil, err) |
| 680 | reply = AuthReply{Err: err} |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 681 | } |
| 682 | |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 683 | ctx.VI(0).Infof("response received from JavaScript server for "+ |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 684 | "MessageId %d with result %v", id, reply) |
| 685 | s.helper.CleanupFlow(id) |
Mike Burrows | 2ec2bb3 | 2015-02-26 15:14:43 -0800 | [diff] [blame] | 686 | // A nil verror.E does not result in an nil error. Instead, we have create |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 687 | // a variable for the error interface and only set it's value if the struct is non- |
| 688 | // nil. |
| 689 | var err error |
| 690 | if reply.Err != nil { |
| 691 | err = reply.Err |
| 692 | } |
| 693 | ch <- err |
| 694 | } |
| 695 | |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 696 | func (s *Server) HandleCaveatValidationResponse(ctx *context.T, id int32, data string) { |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 697 | s.outstandingRequestLock.Lock() |
| 698 | ch := s.outstandingValidationRequests[id] |
| 699 | s.outstandingRequestLock.Unlock() |
| 700 | if ch == nil { |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 701 | ctx.Errorf("unexpected result from JavaScript. No channel "+ |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 702 | "for validation response with MessageId: %d exists. Ignoring the results(%s)", id, data) |
Suharsh Sivakumar | 4cc7c2d | 2015-04-09 15:21:56 -0700 | [diff] [blame] | 703 | // Ignore unknown responses that don't belong to any channel |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 704 | return |
| 705 | } |
| 706 | |
| 707 | var reply CaveatValidationResponse |
Shyam Jayaraman | 0062e27 | 2015-06-04 11:25:13 -0700 | [diff] [blame] | 708 | if err := lib.HexVomDecode(data, &reply, s.helper.TypeDecoder()); err != nil { |
Cosmos Nicolaou | d922992 | 2015-06-24 14:12:24 -0700 | [diff] [blame] | 709 | ctx.Errorf("failed to decode validation response %q: error %v", data, err) |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 710 | ch <- []error{} |
| 711 | return |
| 712 | } |
| 713 | |
| 714 | ch <- reply.Results |
| 715 | } |
| 716 | |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 717 | func (s *Server) createFlow() *Flow { |
| 718 | return s.helper.CreateNewFlow(s, nil) |
| 719 | } |
| 720 | |
Benjamin Prosnitz | 86d5228 | 2014-12-19 15:48:38 -0800 | [diff] [blame] | 721 | func (s *Server) cleanupFlow(id int32) { |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 722 | s.helper.CleanupFlow(id) |
| 723 | } |
| 724 | |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 725 | func (s *Server) createInvoker(handle int32, sig []signature.Interface, hasGlobber bool) (rpc.Invoker, error) { |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 726 | remoteInvokeFunc := s.createRemoteInvokerFunc(handle) |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 727 | var globFunc remoteGlobFunc |
| 728 | if hasGlobber { |
| 729 | globFunc = s.createRemoteGlobFunc(handle) |
| 730 | } |
| 731 | return newInvoker(sig, remoteInvokeFunc, globFunc), nil |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 732 | } |
| 733 | |
Benjamin Prosnitz | 86d5228 | 2014-12-19 15:48:38 -0800 | [diff] [blame] | 734 | func (s *Server) createAuthorizer(handle int32, hasAuthorizer bool) (security.Authorizer, error) { |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 735 | if hasAuthorizer { |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 736 | return s.createRemoteAuthorizer(handle), nil |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 737 | } |
Asim Shankar | 8572f6c | 2014-10-28 15:24:17 -0700 | [diff] [blame] | 738 | return nil, nil |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 739 | } |
| 740 | |
| 741 | func (s *Server) Stop() { |
Mike Burrows | 2ec2bb3 | 2015-02-26 15:14:43 -0800 | [diff] [blame] | 742 | stdErr := verror.New(verror.ErrTimeout, nil).(verror.E) |
Todd Wang | baf1684 | 2015-03-16 14:12:29 -0700 | [diff] [blame] | 743 | result := lib.ServerRpcReply{ |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 744 | Results: nil, |
Mike Burrows | b6689c2 | 2014-10-08 11:14:15 -0700 | [diff] [blame] | 745 | Err: &stdErr, |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 746 | } |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 747 | s.serverStateLock.Lock() |
Nicolas LaCasse | e3867dc | 2015-02-05 14:44:53 -0800 | [diff] [blame] | 748 | |
Shyam Jayaraman | c17abda | 2015-04-06 16:49:17 -0700 | [diff] [blame] | 749 | if s.statusClose != nil { |
| 750 | close(s.statusClose) |
| 751 | } |
Nicolas LaCasse | e3867dc | 2015-02-05 14:44:53 -0800 | [diff] [blame] | 752 | if s.dispatcher != nil { |
| 753 | s.dispatcher.Cleanup() |
| 754 | } |
| 755 | |
Benjamin Prosnitz | c65917c | 2015-05-26 14:21:53 -0700 | [diff] [blame] | 756 | s.outstandingRequestLock.Lock() |
Nicolas LaCasse | e3867dc | 2015-02-05 14:44:53 -0800 | [diff] [blame] | 757 | for _, ch := range s.outstandingAuthRequests { |
| 758 | ch <- fmt.Errorf("Cleaning up server") |
| 759 | } |
Nicolas LaCasse | e3867dc | 2015-02-05 14:44:53 -0800 | [diff] [blame] | 760 | |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 761 | for _, ch := range s.outstandingServerRequests { |
| 762 | select { |
| 763 | case ch <- &result: |
| 764 | default: |
| 765 | } |
| 766 | } |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 767 | s.outstandingAuthRequests = make(map[int32]chan error) |
Todd Wang | baf1684 | 2015-03-16 14:12:29 -0700 | [diff] [blame] | 768 | s.outstandingServerRequests = make(map[int32]chan *lib.ServerRpcReply) |
Benjamin Prosnitz | e8e2b9b | 2015-02-24 12:55:25 -0800 | [diff] [blame] | 769 | s.outstandingRequestLock.Unlock() |
| 770 | s.serverStateLock.Unlock() |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 771 | s.server.Stop() |
Matt Rosencrantz | 317b0c5 | 2015-03-24 20:47:01 -0700 | [diff] [blame] | 772 | |
Suharsh Sivakumar | 4cc7c2d | 2015-04-09 15:21:56 -0700 | [diff] [blame] | 773 | // Only clear the validation requests map after stopping. Clearing them before |
| 774 | // can cause the publisher to get stuck waiting for a caveat validation that |
| 775 | // will never be answered, which prevents the server from stopping. |
Matt Rosencrantz | 317b0c5 | 2015-03-24 20:47:01 -0700 | [diff] [blame] | 776 | s.serverStateLock.Lock() |
| 777 | s.outstandingRequestLock.Lock() |
| 778 | s.outstandingValidationRequests = make(map[int32]chan []error) |
| 779 | s.outstandingRequestLock.Unlock() |
| 780 | s.serverStateLock.Unlock() |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 781 | } |
Ali Ghassemi | 1008bbe | 2014-11-07 16:36:08 -0800 | [diff] [blame] | 782 | |
| 783 | func (s *Server) AddName(name string) error { |
| 784 | return s.server.AddName(name) |
| 785 | } |
| 786 | |
Cosmos Nicolaou | b1a41af | 2015-01-25 22:13:40 -0800 | [diff] [blame] | 787 | func (s *Server) RemoveName(name string) { |
| 788 | s.server.RemoveName(name) |
Ali Ghassemi | 1008bbe | 2014-11-07 16:36:08 -0800 | [diff] [blame] | 789 | } |