Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -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 | |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 5 | package server |
| 6 | |
| 7 | import ( |
| 8 | "strings" |
| 9 | |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 10 | wire "v.io/syncbase/v23/services/syncbase" |
Adam Sadovsky | 4926119 | 2015-05-19 17:39:59 -0700 | [diff] [blame] | 11 | pubutil "v.io/syncbase/v23/syncbase/util" |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 12 | "v.io/syncbase/x/ref/services/syncbase/server/nosql" |
Himabindu Pucha | fb26a83 | 2015-05-20 15:37:50 -0700 | [diff] [blame] | 13 | "v.io/syncbase/x/ref/services/syncbase/server/util" |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 14 | "v.io/v23/rpc" |
| 15 | "v.io/v23/security" |
| 16 | "v.io/v23/verror" |
| 17 | ) |
| 18 | |
| 19 | type dispatcher struct { |
| 20 | s *service |
| 21 | } |
| 22 | |
| 23 | var _ rpc.Dispatcher = (*dispatcher)(nil) |
| 24 | |
| 25 | func NewDispatcher(s *service) *dispatcher { |
| 26 | return &dispatcher{s: s} |
| 27 | } |
| 28 | |
| 29 | // TODO(sadovsky): Return a real authorizer in various places below. |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 30 | func (disp *dispatcher) Lookup(suffix string) (interface{}, security.Authorizer, error) { |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 31 | suffix = strings.TrimPrefix(suffix, "/") |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 32 | parts := strings.SplitN(suffix, "/", 2) |
| 33 | |
| 34 | if len(suffix) == 0 { |
| 35 | return wire.ServiceServer(disp.s), nil, nil |
| 36 | } |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 37 | |
Himabindu Pucha | fb26a83 | 2015-05-20 15:37:50 -0700 | [diff] [blame] | 38 | if parts[0] == util.SyncbaseSuffix { |
| 39 | return disp.s.sync, nil, nil |
| 40 | } |
| 41 | |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 42 | // Validate all key atoms up front, so that we can avoid doing so in all our |
| 43 | // method implementations. |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 44 | appName := parts[0] |
Adam Sadovsky | 4926119 | 2015-05-19 17:39:59 -0700 | [diff] [blame] | 45 | if !pubutil.ValidName(appName) { |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 46 | return nil, nil, wire.NewErrInvalidName(nil, suffix) |
| 47 | } |
| 48 | |
| 49 | aExists := false |
Adam Sadovsky | bc00bd6 | 2015-05-22 12:50:03 -0700 | [diff] [blame] | 50 | var a *app |
| 51 | if aint, err := disp.s.App(nil, nil, appName); err == nil { |
| 52 | a = aint.(*app) // panics on failure, as desired |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 53 | aExists = true |
| 54 | } else { |
| 55 | if verror.ErrorID(err) != verror.ErrNoExistOrNoAccess.ID { |
| 56 | return nil, nil, err |
| 57 | } else { |
| 58 | a = &app{ |
| 59 | name: appName, |
| 60 | s: disp.s, |
| 61 | } |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 62 | } |
| 63 | } |
| 64 | |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 65 | if len(parts) == 1 { |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 66 | return wire.AppServer(a), nil, nil |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 67 | } |
| 68 | |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 69 | // All database, table, and row methods require the app to exist. If it |
| 70 | // doesn't, abort early. |
| 71 | if !aExists { |
| 72 | return nil, nil, verror.New(verror.ErrNoExistOrNoAccess, nil, a.name) |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 73 | } |
| 74 | |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 75 | // Note, it's possible for the app to be deleted concurrently with downstream |
| 76 | // handling of this request. Depending on the order in which things execute, |
| 77 | // the client may not get an error, but in any case ultimately the store will |
| 78 | // end up in a consistent state. |
| 79 | return nosql.NewDispatcher(a).Lookup(parts[1]) |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 80 | } |