@@ -28,22 +28,32 @@ public final class TelnetSession {
2828 /// The MSDP variable definitions to use when MSDP is initialized.
2929 public let msdpTable : [ MSDPVariableDefinition ]
3030
31+ #if canImport(CZlib)
3132 /// Whether MCCP2 compression is active for outbound data.
3233 public var isMCCP2Active : Bool { mccp2 != nil }
3334
3435 /// Whether MCCP3 decompression is active for inbound data.
3536 public var isMCCP3Active : Bool { mccp3 != nil }
37+ #else
38+ /// Whether MCCP2 compression is active for outbound data (unavailable without zlib).
39+ public var isMCCP2Active : Bool { false }
40+
41+ /// Whether MCCP3 decompression is active for inbound data (unavailable without zlib).
42+ public var isMCCP3Active : Bool { false }
43+ #endif
3644
3745 // MARK: - Private State
3846
3947 /// Buffer for incomplete telnet sequences (packet fragmentation).
4048 private var telbuf : [ UInt8 ] = [ ]
4149
50+ #if canImport(CZlib)
4251 /// MCCP2 deflate stream (server→client output compression).
4352 private var mccp2 : DeflateStream ?
4453
4554 /// MCCP3 inflate stream (client→server input decompression).
4655 private var mccp3 : InflateStream ?
56+ #endif
4757
4858 // MARK: - Init
4959
@@ -77,8 +87,10 @@ public final class TelnetSession {
7787
7888 /// Unannounce support (e.g. before copyover).
7989 public func unannounceSupport( ) {
90+ #if canImport(CZlib)
8091 endMCCP2 ( )
8192 endMCCP3 ( )
93+ #endif
8294 for i in 0 ..< min ( telnetTable. count, 255 ) {
8395 let entry = telnetTable [ i]
8496 if !entry. announce. isEmpty {
@@ -125,6 +137,7 @@ public final class TelnetSession {
125137 public func processInput( _ src: [ UInt8 ] ) -> [ UInt8 ] {
126138 var input = src
127139
140+ #if canImport(CZlib)
128141 // MCCP3: decompress incoming data if active
129142 if let inflater = mccp3 {
130143 guard let result = inflater. decompress ( input) else {
@@ -142,6 +155,7 @@ public final class TelnetSession {
142155 input = result. decompressed
143156 }
144157 }
158+ #endif
145159
146160 var out : [ UInt8 ] = [ ]
147161 out. reserveCapacity ( input. count)
@@ -230,53 +244,61 @@ public final class TelnetSession {
230244 }
231245
232246 /// Lazily built telopt pattern table.
233- private lazy var teloptPatterns : [ TeloptPattern ] = [
234- TeloptPattern ( pattern: [ TC . IAC, TC . DO, TO . EOR] ,
235- handler: { s, src, i, n in s. processDoEOR ( ) ; return 3 } ) ,
236-
237- TeloptPattern ( pattern: [ TC . IAC, TC . WILL, TO . TTYPE] ,
238- handler: { s, src, i, n in s. processWillTtype ( ) ; return 3 } ) ,
239- TeloptPattern ( pattern: [ TC . IAC, TC . SB, TO . TTYPE, TS . ENV_IS] ,
240- handler: { s, src, i, n in s. processSbTtypeIs ( src, at: i, srclen: n) } ) ,
241-
242- TeloptPattern ( pattern: [ TC . IAC, TC . SB, TO . NAWS] ,
243- handler: { s, src, i, n in s. processSbNaws ( src, at: i, srclen: n) } ) ,
244-
245- TeloptPattern ( pattern: [ TC . IAC, TC . WILL, TO . NEW_ENVIRON] ,
246- handler: { s, src, i, n in s. processWillNewEnviron ( ) ; return 3 } ) ,
247- TeloptPattern ( pattern: [ TC . IAC, TC . SB, TO . NEW_ENVIRON] ,
248- handler: { s, src, i, n in s. processSbNewEnviron ( src, at: i, srclen: n) } ) ,
249-
250- TeloptPattern ( pattern: [ TC . IAC, TC . DO, TO . CHARSET] ,
251- handler: { s, src, i, n in s. processDoCharset ( ) ; return 3 } ) ,
252- TeloptPattern ( pattern: [ TC . IAC, TC . SB, TO . CHARSET] ,
253- handler: { s, src, i, n in s. processSbCharset ( src, at: i, srclen: n) } ) ,
254-
255- TeloptPattern ( pattern: [ TC . IAC, TC . DO, TO . MSSP] ,
256- handler: { s, src, i, n in s. processDoMssp ( ) ; return 3 } ) ,
257-
258- TeloptPattern ( pattern: [ TC . IAC, TC . DO, TO . MSDP] ,
259- handler: { s, src, i, n in s. processDoMsdp ( ) ; return 3 } ) ,
260- TeloptPattern ( pattern: [ TC . IAC, TC . SB, TO . MSDP] ,
261- handler: { s, src, i, n in s. processSbMsdp ( src, at: i, srclen: n) } ) ,
262-
263- TeloptPattern ( pattern: [ TC . IAC, TC . DO, TO . GMCP] ,
264- handler: { s, src, i, n in s. processDoGmcp ( ) ; return 3 } ) ,
265- TeloptPattern ( pattern: [ TC . IAC, TC . SB, TO . GMCP] ,
266- handler: { s, src, i, n in s. processSbGmcp ( src, at: i, srclen: n) } ) ,
267-
268- // MCCP2
269- TeloptPattern ( pattern: [ TC . IAC, TC . DO, TO . MCCP2] ,
270- handler: { s, src, i, n in s. processDoMccp2 ( ) ; return 3 } ) ,
271- TeloptPattern ( pattern: [ TC . IAC, TC . DONT, TO . MCCP2] ,
272- handler: { s, src, i, n in s. processDontMccp2 ( ) ; return 3 } ) ,
273-
274- // MCCP3
275- TeloptPattern ( pattern: [ TC . IAC, TC . DO, TO . MCCP3] ,
276- handler: { s, src, i, n in return 3 } ) ,
277- TeloptPattern ( pattern: [ TC . IAC, TC . SB, TO . MCCP3, TC . IAC, TC . SE] ,
278- handler: { s, src, i, n in s. processSbMccp3 ( ) ; return 5 } ) ,
279- ]
247+ private lazy var teloptPatterns : [ TeloptPattern ] = buildTeloptPatterns ( )
248+
249+ private func buildTeloptPatterns( ) -> [ TeloptPattern ] {
250+ var patterns : [ TeloptPattern ] = [
251+ TeloptPattern ( pattern: [ TC . IAC, TC . DO, TO . EOR] ,
252+ handler: { s, src, i, n in s. processDoEOR ( ) ; return 3 } ) ,
253+
254+ TeloptPattern ( pattern: [ TC . IAC, TC . WILL, TO . TTYPE] ,
255+ handler: { s, src, i, n in s. processWillTtype ( ) ; return 3 } ) ,
256+ TeloptPattern ( pattern: [ TC . IAC, TC . SB, TO . TTYPE, TS . ENV_IS] ,
257+ handler: { s, src, i, n in s. processSbTtypeIs ( src, at: i, srclen: n) } ) ,
258+
259+ TeloptPattern ( pattern: [ TC . IAC, TC . SB, TO . NAWS] ,
260+ handler: { s, src, i, n in s. processSbNaws ( src, at: i, srclen: n) } ) ,
261+
262+ TeloptPattern ( pattern: [ TC . IAC, TC . WILL, TO . NEW_ENVIRON] ,
263+ handler: { s, src, i, n in s. processWillNewEnviron ( ) ; return 3 } ) ,
264+ TeloptPattern ( pattern: [ TC . IAC, TC . SB, TO . NEW_ENVIRON] ,
265+ handler: { s, src, i, n in s. processSbNewEnviron ( src, at: i, srclen: n) } ) ,
266+
267+ TeloptPattern ( pattern: [ TC . IAC, TC . DO, TO . CHARSET] ,
268+ handler: { s, src, i, n in s. processDoCharset ( ) ; return 3 } ) ,
269+ TeloptPattern ( pattern: [ TC . IAC, TC . SB, TO . CHARSET] ,
270+ handler: { s, src, i, n in s. processSbCharset ( src, at: i, srclen: n) } ) ,
271+
272+ TeloptPattern ( pattern: [ TC . IAC, TC . DO, TO . MSSP] ,
273+ handler: { s, src, i, n in s. processDoMssp ( ) ; return 3 } ) ,
274+
275+ TeloptPattern ( pattern: [ TC . IAC, TC . DO, TO . MSDP] ,
276+ handler: { s, src, i, n in s. processDoMsdp ( ) ; return 3 } ) ,
277+ TeloptPattern ( pattern: [ TC . IAC, TC . SB, TO . MSDP] ,
278+ handler: { s, src, i, n in s. processSbMsdp ( src, at: i, srclen: n) } ) ,
279+
280+ TeloptPattern ( pattern: [ TC . IAC, TC . DO, TO . GMCP] ,
281+ handler: { s, src, i, n in s. processDoGmcp ( ) ; return 3 } ) ,
282+ TeloptPattern ( pattern: [ TC . IAC, TC . SB, TO . GMCP] ,
283+ handler: { s, src, i, n in s. processSbGmcp ( src, at: i, srclen: n) } ) ,
284+ ]
285+ #if canImport(CZlib)
286+ patterns += [
287+ // MCCP2
288+ TeloptPattern ( pattern: [ TC . IAC, TC . DO, TO . MCCP2] ,
289+ handler: { s, src, i, n in s. processDoMccp2 ( ) ; return 3 } ) ,
290+ TeloptPattern ( pattern: [ TC . IAC, TC . DONT, TO . MCCP2] ,
291+ handler: { s, src, i, n in s. processDontMccp2 ( ) ; return 3 } ) ,
292+
293+ // MCCP3
294+ TeloptPattern ( pattern: [ TC . IAC, TC . DO, TO . MCCP3] ,
295+ handler: { s, src, i, n in return 3 } ) ,
296+ TeloptPattern ( pattern: [ TC . IAC, TC . SB, TO . MCCP3, TC . IAC, TC . SE] ,
297+ handler: { s, src, i, n in s. processSbMccp3 ( ) ; return 5 } ) ,
298+ ]
299+ #endif
300+ return patterns
301+ }
280302
281303 /// Handle generic telnet commands that don't match any specific pattern.
282304 private func handleGenericTelnet( _ src: [ UInt8 ] , at i: Int , remaining: Int , out: inout [ UInt8 ] ) -> Int {
@@ -322,13 +344,17 @@ public final class TelnetSession {
322344 // MARK: - Output
323345
324346 private func write( _ data: [ UInt8 ] ) {
347+ #if canImport(CZlib)
325348 if let mccp2 = mccp2 {
326349 if let compressed = mccp2. compress ( data) {
327350 delegate? . telnetSession ( self , write: compressed)
328351 }
329352 } else {
330353 delegate? . telnetSession ( self , write: data)
331354 }
355+ #else
356+ delegate? . telnetSession ( self , write: data)
357+ #endif
332358 }
333359
334360 /// Write data bypassing MCCP2 compression (used for the MCCP2 start marker).
@@ -685,6 +711,7 @@ public final class TelnetSession {
685711 return sbLen
686712 }
687713
714+ #if canImport(CZlib)
688715 // MARK: - Handler: MCCP2
689716
690717 private func processDoMccp2( ) {
@@ -746,4 +773,11 @@ public final class TelnetSession {
746773 log ( " MCCP3: COMPRESSION END " )
747774 mccp3 = nil
748775 }
776+ #else
777+ /// No-op: MCCP2 unavailable without zlib.
778+ public func endMCCP2( ) { }
779+
780+ /// No-op: MCCP3 unavailable without zlib.
781+ public func endMCCP3( ) { }
782+ #endif
749783}
0 commit comments