1 module hunt.http.codec.websocket.model.common; 2 3 final class WebSocketConstants { 4 enum string SEC_WEBSOCKET_EXTENSIONS = "Sec-WebSocket-Extensions"; 5 enum string SEC_WEBSOCKET_PROTOCOL = "Sec-WebSocket-Protocol"; 6 enum string SEC_WEBSOCKET_VERSION = "Sec-WebSocket-Version"; 7 enum int SPEC_VERSION = 13; 8 } 9 10 11 /** 12 * Behavior for how the WebSocket should operate. 13 * <p> 14 * This dictated by the <a href="https://tools.ietf.org/html/rfc6455">RFC 6455</a> spec in various places, where certain behavior must be performed depending on 15 * operation as a <a href="https://tools.ietf.org/html/rfc6455#section-4.1">CLIENT</a> vs a <a href="https://tools.ietf.org/html/rfc6455#section-4.2">SERVER</a> 16 */ 17 enum WebSocketBehavior { 18 CLIENT, SERVER 19 } 20 21 22 /** 23 * Connection states as outlined in <a href="https://tools.ietf.org/html/rfc6455">RFC6455</a>. 24 */ 25 enum ConnectionState { 26 Unknown, 27 28 /** 29 * [RFC] Initial state of a connection, the upgrade request / response is in progress 30 */ 31 CONNECTING, 32 /** 33 * [Impl] Intermediate state between CONNECTING and OPEN, used to indicate that a upgrade request/response is successful, but the end-user provided socket's 34 * onOpen code has yet to run. 35 * <p> 36 * This state is to allow the local socket to initiate messages and frames, but to NOT start reading yet. 37 */ 38 CONNECTED, 39 /** 40 * [RFC] The websocket connection is established and open. 41 * <p> 42 * This indicates that the Upgrade has succeed, and the end-user provided socket's onOpen code has completed. 43 * <p> 44 * It is now time to start reading from the remote endpoint. 45 */ 46 OPEN, 47 /** 48 * [RFC] The websocket closing handshake is started. 49 * <p> 50 * This can be considered a half-closed state. 51 * <p> 52 * When receiving this as an event on {@link ConnectionStateListener#onConnectionStateChange(ConnectionState)} a close frame should be sent using 53 * the {@link CloseInfo} available from {@link IOState#getCloseInfo()} 54 */ 55 CLOSING, 56 /** 57 * [RFC] The websocket connection is closed. 58 * <p> 59 * Connection should be disconnected and no further reads or writes should occur. 60 */ 61 CLOSED 62 } 63 64 final class OpCode { 65 /** 66 * OpCode for a Continuation Frame 67 * 68 * @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a> 69 */ 70 enum byte CONTINUATION = cast(byte) 0x00; 71 72 /** 73 * OpCode for a Text Frame 74 * 75 * @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a> 76 */ 77 enum byte TEXT = cast(byte) 0x01; 78 79 /** 80 * OpCode for a Binary Frame 81 * 82 * @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a> 83 */ 84 enum byte BINARY = cast(byte) 0x02; 85 86 /** 87 * OpCode for a Close Frame 88 * 89 * @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a> 90 */ 91 enum byte CLOSE = cast(byte) 0x08; 92 93 /** 94 * OpCode for a Ping Frame 95 * 96 * @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a> 97 */ 98 enum byte PING = cast(byte) 0x09; 99 100 /** 101 * OpCode for a Pong Frame 102 * 103 * @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a> 104 */ 105 enum byte PONG = cast(byte) 0x0A; 106 107 /** 108 * An undefined OpCode 109 */ 110 enum byte UNDEFINED = cast(byte) -1; 111 112 static bool isControlFrame(byte opcode) { 113 return (opcode >= CLOSE); 114 } 115 116 static bool isDataFrame(byte opcode) { 117 return (opcode == TEXT) || (opcode == BINARY); 118 } 119 120 /** 121 * Test for known opcodes (per the RFC spec) 122 * 123 * @param opcode the opcode to test 124 * @return true if known. false if unknown, undefined, or reserved 125 */ 126 static bool isKnown(byte opcode) { 127 return (opcode == CONTINUATION) || (opcode == TEXT) || (opcode == BINARY) || 128 (opcode == CLOSE) || (opcode == PING) || (opcode == PONG); 129 } 130 131 static string name(byte opcode) { 132 switch (opcode) { 133 case -1: 134 return "NO-OP"; 135 case CONTINUATION: 136 return "CONTINUATION"; 137 case TEXT: 138 return "TEXT"; 139 case BINARY: 140 return "BINARY"; 141 case CLOSE: 142 return "CLOSE"; 143 case PING: 144 return "PING"; 145 case PONG: 146 return "PONG"; 147 default: 148 return "NON-SPEC[" ~ opcode ~ "]"; 149 } 150 } 151 }