blob: 4ef1dcd8124373ece22d38109295333218136636 [file] [log] [blame]
Kino Roya9da9eb2022-10-07 23:13:01 -07001// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18import Foundation
19import Thrift
20
21public enum Protocol: String {
22 case binary
23 case compact
24 case header
25 case json
26}
27
28public enum Transport: String {
29 case buffered
30 case framed
31 case http
32 case anonpipe
33 case zlib
34}
35
36public enum ServerType: String {
37 case simple
38 case threadPool = "thread-pool"
39 case threaded
40 case nonblocking
41}
42
43public enum ParserError: Error {
44 case unknownArgument(argument: String)
45 case missingParameter(argument: String)
46 case invalidParameter(argument: String, parameter: String)
47
48 case unsupportedOption
49}
50
51public class ParametersBase {
52 public var showHelp = false
53 public var port: Int?
54 public var domainSocket: String?
55 public var namedPipe: String?
56 public var proto: Protocol?
57 public var transport: Transport?
58 public var multiplex = false
59 public var abstractNamespace = false
60 public var ssl = false
61 public var zlib = false
62
63 public init (arguments: [String]) throws {
64 if arguments.count > 1 {
65 for argument in arguments[1...] {
66 let equalSignPos = argument.firstIndex(of: "=") ?? argument.endIndex
67 let name = String(argument[..<equalSignPos])
68 let value: String? = (equalSignPos < argument.endIndex) ? String(argument[argument.index(equalSignPos, offsetBy: 1)..<argument.endIndex]) : nil
69
70 try processArgument(name: name, value: value)
71 }
72 }
73
74 fillDefaults()
75 try checkSupported()
76 }
77
78 open func processArgument(name: String, value: String?) throws {
79 switch name {
80 case "-h", "--help":
81 showHelp = true
82 case "--port":
83 guard value != nil else { throw ParserError.missingParameter(argument: name) }
84 port = Int(value!)
85 guard port != nil else { throw ParserError.invalidParameter(argument: name, parameter: value!) }
86 case "--domain-socket":
87 guard value != nil else { throw ParserError.missingParameter(argument: name) }
88 domainSocket = value!
89 case "--named-pipe":
90 guard value != nil else { throw ParserError.missingParameter(argument: name) }
91 namedPipe = value!
92 case "--transport":
93 guard value != nil else { throw ParserError.missingParameter(argument: name) }
94 transport = Transport(rawValue: value!)
95 guard transport != nil else { throw ParserError.invalidParameter(argument: name, parameter: value!) }
96 case "--protocol":
97 guard value != nil else { throw ParserError.missingParameter(argument: name) }
98 proto = Protocol(rawValue: value!)
99 guard proto != nil else { throw ParserError.invalidParameter(argument: name, parameter: value!) }
100 case "--multiplex":
101 multiplex = true
102 case "--abstract-namespace":
103 abstractNamespace = true
104 case "--ssl":
105 ssl = true
106 case "--zlib":
107 zlib = true
108 default:
109 throw ParserError.unknownArgument(argument: name)
110 }
111 }
112
113 open func fillDefaults() {
114 if port == nil && domainSocket == nil && namedPipe == nil {
115 port = 9090
116 }
117
118 if transport == nil {
119 transport = .buffered
120 }
121
122 if proto == nil {
123 proto = .binary
124 }
125 }
126
127 open func checkSupported() throws {
128 guard transport == .buffered || transport == .framed else { throw ParserError.unsupportedOption }
129 guard proto == .binary || proto == .compact else { throw ParserError.unsupportedOption }
130 }
131}
132
133public class TestClientParameters: ParametersBase {
134 public var host: String?
135 public var testLoops: Int?
136 public var threads: Int?
137
138 public func printHelp() {
139 print("""
140Allowed options:
141 -h | --help produce help message
142 --host=arg (localhost) Host to connect
143 --port=arg (9090) Port number to connect
144 --domain-socket=arg Domain Socket (e.g. /tmp/ThriftTest.thrift),
145 instead of host and port
146 --named-pipe=arg Windows Named Pipe (e.g. MyThriftPipe)
147 --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles)
148 --abstract-namespace Create the domain socket in the Abstract Namespace
149 (no connection with filesystem pathnames)
150 --transport=arg (buffered) Transport: buffered, framed, http, evhttp, zlib
151 --protocol=arg (binary) Protocol: binary, compact, header, json
152 --multiplex Add TMultiplexedProtocol service name "ThriftTest"
153 --ssl Encrypted Transport using SSL
154 --zlib Wrap Transport with Zlib
155 -n=arg | --testloops=arg (1) Number of Tests
156 -t=arg | --threads=arg (1) Number of Test threads
157""")
158 }
159
160 open override func processArgument(name: String, value: String?) throws {
161 switch name {
162 case "--host":
163 guard value != nil else { throw ParserError.missingParameter(argument: name) }
164 host = value!
165 case "-n", "--testloops":
166 guard value != nil else { throw ParserError.missingParameter(argument: name) }
167 testLoops = Int(value!)
168 guard testLoops != nil else { throw ParserError.invalidParameter(argument: name, parameter: value!) }
169 case "-t", "--threads":
170 guard value != nil else { throw ParserError.missingParameter(argument: name) }
171 threads = Int(value!)
172 guard threads != nil else { throw ParserError.invalidParameter(argument: name, parameter: value!) }
173 default:
174 try super.processArgument(name: name, value: value)
175 }
176 }
177
178 open override func fillDefaults() {
179 super.fillDefaults()
180
181 if host == nil {
182 host = "localhost"
183 }
184
185 if testLoops == nil {
186 testLoops = 1
187 }
188
189 if threads == nil {
190 threads = 4
191 }
192 }
193}
194
195public class TestServerParameters: ParametersBase {
196 public var serverType: ServerType?
197 public var processorEvents = false
198 public var workers: Int?
199
200 public func printHelp() {
201 print("""
202Allowed options:
203 -h | --help produce help message
204 --port=arg (=9090) Port number to listen
205 --domain-socket=arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)
206 --named-pipe=arg Windows Named Pipe (e.g. MyThriftPipe)
207 --server-type=arg (=simple) type of server, "simple", "thread-pool",
208 "threaded", or "nonblocking"
209 --transport=arg (=buffered) transport: buffered, framed, http, anonpipe, zlib
210 --protocol=arg (=binary) protocol: binary, compact, header, json
211 --multiplex Add TMultiplexedProtocol service name "ThriftTest"
212 --abstract-namespace Create the domain socket in the Abstract Namespace
213 (no connection with filesystem pathnames)
214 --ssl Encrypted Transport using SSL
215 --zlib Wrapped Transport using Zlib
216 --processor-events processor-events
217 -n=arg | --workers=arg (=4) Number of thread pools workers. Only valid for
218 thread-pool server type
219""")
220 }
221
222 open override func processArgument(name: String, value: String?) throws {
223 switch name {
224 case "--server-type":
225 guard value != nil else { throw ParserError.missingParameter(argument: name) }
226 serverType = ServerType(rawValue: value!)
227 guard serverType != nil else { throw ParserError.invalidParameter(argument: name, parameter: value!) }
228 case "--processor-events":
229 processorEvents = true
230 case "-n", "--workers":
231 guard value != nil else { throw ParserError.missingParameter(argument: name) }
232 workers = Int(value!)
233 guard workers != nil else { throw ParserError.invalidParameter(argument: name, parameter: value!) }
234 default:
235 try super.processArgument(name: name, value: value)
236 }
237 }
238
239 open override func fillDefaults() {
240 super.fillDefaults()
241
242 if serverType == nil {
243 serverType = .simple
244 }
245
246 if workers == nil {
247 workers = 4
248 }
249 }
250
251 open override func checkSupported() throws {
252 try super.checkSupported()
253 guard serverType == .simple else { throw ParserError.unsupportedOption }
254 }
255}
256