/ keychain / ckks / RateLimiter.h
RateLimiter.h
  1  /*
  2   * Copyright (c) 2017 Apple Inc. All Rights Reserved.
  3   *
  4   * @APPLE_LICENSE_HEADER_START@
  5   *
  6   * This file contains Original Code and/or Modifications of Original Code
  7   * as defined in and that are subject to the Apple Public Source License
  8   * Version 2.0 (the 'License'). You may not use this file except in
  9   * compliance with the License. Please obtain a copy of the License at
 10   * http://www.opensource.apple.com/apsl/ and read it before using this
 11   * file.
 12   *
 13   * The Original Code and all software distributed under the License are
 14   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 15   * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 16   * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 17   * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 18   * Please see the License for the specific language governing rights and
 19   * limitations under the License.
 20   *
 21   * @APPLE_LICENSE_HEADER_END@
 22   */
 23  
 24  #import <Foundation/Foundation.h>
 25  
 26  NS_ASSUME_NONNULL_BEGIN
 27  
 28  @interface RateLimiter : NSObject <NSSecureCoding>
 29  
 30  @property (readonly, nonatomic) NSDictionary* config;
 31  @property (readonly, nonatomic) NSUInteger stateSize;
 32  @property (readonly, nonatomic, nullable) NSString* assetType;
 33  
 34  typedef NS_ENUM(NSInteger, RateLimiterBadness) {
 35      RateLimiterBadnessClear = 0,  // everything is fine, process right now
 36      RateLimiterBadnessCongested,
 37      RateLimiterBadnessSeverelyCongested,
 38      RateLimiterBadnessGridlocked,
 39      RateLimiterBadnessOverloaded,  // everything is on fire, go away
 40  };
 41  
 42  - (instancetype _Nullable)initWithConfig:(NSDictionary*)config;
 43  - (instancetype _Nullable)initWithCoder:(NSCoder*)coder;
 44  - (instancetype _Nullable)init NS_UNAVAILABLE;
 45  
 46  /*!
 47   * @brief Find out whether objects may be processed or must wait.
 48   * @param obj The object being judged.
 49   * @param time Current time.
 50   * @param limitTime Assigned okay-to-process time. Nil when object may be processed immediately.
 51   * @return RateLimiterBadness enum value indicating current congestion situation, or to signal
 52   *
 53   * judge:at: will set the limitTime object to nil in case of 0 badness. For badnesses 1-4 the time object will indicate when it is okay to send the entry.
 54   * At badness 5 judge:at: has determined there is too much activity so the caller should hold off altogether. The limitTime object will indicate when
 55   * this overloaded state will end.
 56   */
 57  - (RateLimiterBadness)judge:(id)obj at:(NSDate*)time limitTime:(NSDate* _Nonnull __autoreleasing* _Nonnull)limitTime;
 58  
 59  - (void)reset;
 60  - (NSString*)diagnostics;
 61  + (BOOL)supportsSecureCoding;
 62  
 63  // TODO:
 64  // implement config loading from MobileAsset
 65  
 66  @end
 67  
 68  NS_ASSUME_NONNULL_END
 69  
 70  /* Annotated example plist
 71  
 72  <?xml version="1.0" encoding="UTF-8"?>
 73  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 74  <plist version="1.0">
 75  <dict>
 76      <key>general</key>
 77      <dict>
 78          <!-- Total item limit -->
 79          <key>maxStateSize</key>
 80          <integer>250</integer>
 81          <!-- Throw away items after this many seconds -->
 82          <key>maxItemAge</key>
 83          <integer>3600</integer>
 84          <!-- Ignore everybody for this many seconds -->
 85          <key>overloadDuration</key>
 86          <integer>1800</integer>
 87          <!-- Printable string for logs -->
 88          <key>name</key>
 89          <string>CKKS</string>
 90          <!-- Load config stored in this MobileAsset (ignored if inited with config or plist directly) -->
 91          <key>MAType</key>
 92          <string></string>
 93      </dict>
 94      <!-- Each property you want to ratelimit on must have its own group dictionary -->
 95      <key>groups</key>
 96      <array>
 97          <dict>
 98              <!-- The first group must be for the global bucket. It behaves identically otherwise -->
 99              <key>property</key>
100              <string>global</string>
101              <key>capacity</key>
102              <integer>20</integer>
103              <key>rate</key>
104              <integer>30</integer>
105              <key>badness</key>
106              <integer>1</integer>
107          </dict>
108          <dict>
109              <!-- Your object must respond to this selector that takes no arguments by returning an NSString * -->
110              <key>property</key>
111              <string>UUID</string>
112              <!-- Buckets of this type hold at most this many tokens -->
113              <key>capacity</key>
114              <integer>3</integer>
115              <!-- Tokens replenish at 1 every this many seconds -->
116              <key>rate</key>
117              <integer>600</integer>
118              <!-- Max of all empty bucket badnesses is returned to caller. See RateLimiterBadness enum -->
119              <key>badness</key>
120              <integer>3</integer>
121          </dict>
122      </array>
123  </dict>
124  </plist>
125  
126  */