1 module hunt.http.codec.websocket.stream.ExtensionNegotiator; 2 3 import hunt.http.codec.websocket.model.Extension; 4 import hunt.http.codec.websocket.model.ExtensionConfig; 5 import hunt.http.codec.websocket.model.extension.AbstractExtension; 6 import hunt.http.codec.websocket.model.extension.ExtensionFactory; 7 import hunt.http.codec.websocket.model.extension.WebSocketExtensionFactory; 8 9 import hunt.http.HttpHeader; 10 import hunt.http.HttpMetaData; 11 import hunt.http.WebSocketConnection; 12 import hunt.http.WebSocketFrame; 13 14 import hunt.collection; 15 import hunt.Exceptions; 16 17 import std.algorithm; 18 import std.array; 19 import std.container.array; 20 import std.range; 21 22 /** 23 * 24 */ 25 class ExtensionNegotiator { 26 27 private ExtensionFactory factory; 28 private IncomingFrames nextIncomingFrames; 29 private OutgoingFrames nextOutgoingFrames; 30 private IncomingFrames incomingFrames; 31 private OutgoingFrames outgoingFrames; 32 33 this() { 34 this(new WebSocketExtensionFactory()); 35 } 36 37 this(ExtensionFactory factory) { 38 this.factory = factory; 39 } 40 41 ExtensionFactory getFactory() { 42 return factory; 43 } 44 45 void setFactory(ExtensionFactory factory) { 46 this.factory = factory; 47 } 48 49 ExtensionConfig[] negotiate(HttpMetaData metaData) { 50 InputRange!string fieldValues = metaData.getFields().getValues(HttpHeader.SEC_WEBSOCKET_EXTENSIONS.asString()); 51 52 Array!(ExtensionConfig) configList = ExtensionConfig.parseEnum(fieldValues); 53 auto r = configList[].filter!(c => factory.isAvailable(c.getName())); 54 55 return r.array; 56 // return parseEnum(metaData.getFields().getValues(HttpHeader.SEC_WEBSOCKET_EXTENSIONS.asString())) 57 // .stream().filter(c -> factory.isAvailable(c.getName())) 58 // .collect(Collectors.toList()); 59 } 60 61 Extension[] parse(HttpMetaData metaData) { 62 assert(nextIncomingFrames !is null, "The next incoming frames MUST be not null"); 63 assert(nextOutgoingFrames !is null, "The next outgoing frames MUST be not null"); 64 65 Extension[] extensions = _parse(metaData); 66 if (!extensions.empty) { 67 size_t len = extensions.length; 68 for (size_t i = 0; i < len; i++) { 69 size_t next = i + 1; 70 if (next < len - 1) { 71 extensions[i].setNextIncomingFrames(extensions[next]); 72 } else { 73 extensions[i].setNextIncomingFrames(nextIncomingFrames); 74 } 75 } 76 incomingFrames = extensions[0]; 77 78 for (size_t i = len - 1; i >= 0; i--) { 79 size_t next = i - 1; 80 if (next > 0) { 81 extensions[i].setNextOutgoingFrames(extensions[next]); 82 } else { 83 extensions[i].setNextOutgoingFrames(nextOutgoingFrames); 84 } 85 } 86 outgoingFrames = extensions[len - 1]; 87 return extensions; 88 } else { 89 incomingFrames = nextIncomingFrames; 90 outgoingFrames = nextOutgoingFrames; 91 return []; 92 } 93 } 94 95 protected Extension[] _parse(HttpMetaData metaData) { 96 97 InputRange!string fieldValues = metaData.getFields().getValues(HttpHeader.SEC_WEBSOCKET_EXTENSIONS.asString()); 98 Array!(ExtensionConfig) configList = ExtensionConfig.parseEnum(fieldValues); 99 auto r = configList[].filter!(c => factory.isAvailable(c.getName())) 100 .map!(delegate Extension (ExtensionConfig c) { 101 Extension e = factory.newInstance(c); 102 AbstractExtension abstractExtension = cast(AbstractExtension) e; 103 if (abstractExtension !is null) 104 abstractExtension.setConfig(c); 105 return e; 106 }); 107 108 return r.array; 109 } 110 111 IncomingFrames getNextIncomingFrames() { 112 return nextIncomingFrames; 113 } 114 115 void setNextIncomingFrames(IncomingFrames nextIncomingFrames) { 116 this.nextIncomingFrames = nextIncomingFrames; 117 } 118 119 OutgoingFrames getNextOutgoingFrames() { 120 return nextOutgoingFrames; 121 } 122 123 void setNextOutgoingFrames(OutgoingFrames nextOutgoingFrames) { 124 this.nextOutgoingFrames = nextOutgoingFrames; 125 } 126 127 IncomingFrames getIncomingFrames() { 128 return incomingFrames; 129 } 130 131 OutgoingFrames getOutgoingFrames() { 132 return outgoingFrames; 133 } 134 135 }