├── .github └── workflows │ ├── build-pr.yml │ └── build.yml ├── .gitignore ├── LICENSE.txt ├── README.md ├── checkstyle.xml ├── header.txt ├── pom.xml └── src ├── main └── java │ ├── com │ └── corundumstudio │ │ └── socketio │ │ ├── AckCallback.java │ │ ├── AckMode.java │ │ ├── AckRequest.java │ │ ├── AuthTokenListener.java │ │ ├── AuthTokenResult.java │ │ ├── AuthorizationListener.java │ │ ├── AuthorizationResult.java │ │ ├── BroadcastAckCallback.java │ │ ├── BroadcastOperations.java │ │ ├── ClientOperations.java │ │ ├── Configuration.java │ │ ├── Disconnectable.java │ │ ├── DisconnectableHub.java │ │ ├── HandshakeData.java │ │ ├── HttpRequestDecoderConfiguration.java │ │ ├── JsonSupportWrapper.java │ │ ├── MultiRoomBroadcastOperations.java │ │ ├── MultiTypeAckCallback.java │ │ ├── MultiTypeArgs.java │ │ ├── SingleRoomBroadcastOperations.java │ │ ├── SocketConfig.java │ │ ├── SocketIOChannelInitializer.java │ │ ├── SocketIOClient.java │ │ ├── SocketIONamespace.java │ │ ├── SocketIOServer.java │ │ ├── Transport.java │ │ ├── VoidAckCallback.java │ │ ├── ack │ │ ├── AckManager.java │ │ └── AckSchedulerKey.java │ │ ├── annotation │ │ ├── AnnotationScanner.java │ │ ├── OnConnect.java │ │ ├── OnConnectScanner.java │ │ ├── OnDisconnect.java │ │ ├── OnDisconnectScanner.java │ │ ├── OnEvent.java │ │ ├── OnEventScanner.java │ │ ├── ScannerEngine.java │ │ └── SpringAnnotationScanner.java │ │ ├── handler │ │ ├── AuthorizeHandler.java │ │ ├── ClientHead.java │ │ ├── ClientsBox.java │ │ ├── EncoderHandler.java │ │ ├── InPacketHandler.java │ │ ├── PacketListener.java │ │ ├── SocketIOException.java │ │ ├── SuccessAuthorizationListener.java │ │ ├── TransportState.java │ │ └── WrongUrlHandler.java │ │ ├── listener │ │ ├── ClientListeners.java │ │ ├── ConnectListener.java │ │ ├── DataListener.java │ │ ├── DefaultExceptionListener.java │ │ ├── DisconnectListener.java │ │ ├── EventInterceptor.java │ │ ├── ExceptionListener.java │ │ ├── ExceptionListenerAdapter.java │ │ ├── MultiTypeEventListener.java │ │ ├── PingListener.java │ │ └── PongListener.java │ │ ├── messages │ │ ├── HttpErrorMessage.java │ │ ├── HttpMessage.java │ │ ├── OutPacketMessage.java │ │ ├── PacketsMessage.java │ │ ├── XHROptionsMessage.java │ │ └── XHRPostMessage.java │ │ ├── misc │ │ ├── CompositeIterable.java │ │ ├── CompositeIterator.java │ │ └── IterableCollection.java │ │ ├── namespace │ │ ├── EventEntry.java │ │ ├── Namespace.java │ │ └── NamespacesHub.java │ │ ├── protocol │ │ ├── AckArgs.java │ │ ├── AuthPacket.java │ │ ├── ConnPacket.java │ │ ├── EngineIOVersion.java │ │ ├── Event.java │ │ ├── JacksonJsonSupport.java │ │ ├── JsonSupport.java │ │ ├── Packet.java │ │ ├── PacketDecoder.java │ │ ├── PacketEncoder.java │ │ ├── PacketType.java │ │ └── UTF8CharsScanner.java │ │ ├── scheduler │ │ ├── CancelableScheduler.java │ │ ├── HashedWheelScheduler.java │ │ ├── HashedWheelTimeoutScheduler.java │ │ └── SchedulerKey.java │ │ ├── store │ │ ├── HazelcastPubSubStore.java │ │ ├── HazelcastStore.java │ │ ├── HazelcastStoreFactory.java │ │ ├── MemoryPubSubStore.java │ │ ├── MemoryStore.java │ │ ├── MemoryStoreFactory.java │ │ ├── RedissonPubSubStore.java │ │ ├── RedissonStore.java │ │ ├── RedissonStoreFactory.java │ │ ├── Store.java │ │ ├── StoreFactory.java │ │ └── pubsub │ │ │ ├── BaseStoreFactory.java │ │ │ ├── BulkJoinLeaveMessage.java │ │ │ ├── ConnectMessage.java │ │ │ ├── DisconnectMessage.java │ │ │ ├── DispatchMessage.java │ │ │ ├── JoinLeaveMessage.java │ │ │ ├── PubSubListener.java │ │ │ ├── PubSubMessage.java │ │ │ ├── PubSubStore.java │ │ │ └── PubSubType.java │ │ └── transport │ │ ├── NamespaceClient.java │ │ ├── PollingTransport.java │ │ └── WebSocketTransport.java │ └── module-info.java └── test └── java └── com └── corundumstudio └── socketio ├── JoinIteratorsTest.java ├── parser ├── DecoderAckPacketTest.java ├── DecoderBaseTest.java ├── DecoderConnectionPacketTest.java ├── DecoderEventPacketTest.java ├── DecoderJsonPacketTest.java ├── DecoderMessagePacketTest.java ├── EncoderAckPacketTest.java ├── EncoderBaseTest.java ├── EncoderConnectionPacketTest.java ├── EncoderEventPacketTest.java ├── EncoderMessagePacketTest.java └── PayloadTest.java ├── protocol └── PacketTest.java └── transport ├── HttpTransportTest.java └── WebSocketTransportTest.java /.github/workflows/build-pr.yml: -------------------------------------------------------------------------------- 1 | name: Build PR 2 | 3 | concurrency: 4 | group: ${{ github.workflow }}-${{ github.event.pull_request.number }} 5 | cancel-in-progress: true 6 | 7 | permissions: 8 | contents: read 9 | 10 | on: 11 | pull_request: 12 | branches: 13 | - master 14 | workflow_dispatch: 15 | 16 | jobs: 17 | 18 | build: 19 | strategy: 20 | matrix: 21 | java-version: 22 | - 17 23 | - 21 24 | uses: ./.github/workflows/build.yml 25 | with: 26 | javaVersion: "${{ matrix.java-version }}" 27 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | javaVersion: 7 | required: true 8 | type: string 9 | 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: 'Checkout' 16 | uses: actions/checkout@v4 17 | - name: 'Set Up Java' 18 | uses: actions/setup-java@v3 19 | with: 20 | java-version: ${{ inputs.javaVersion }} 21 | distribution: 'temurin' 22 | cache: 'maven' 23 | - name: 'Build Project' 24 | run: | 25 | export MAVEN_OPTS="-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN" 26 | mvn --batch-mode --errors --fail-at-end test 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /.settings 3 | /.classpath 4 | /.project 5 | /target 6 | 7 | /gnupg 8 | .idea 9 | *.iml -------------------------------------------------------------------------------- /header.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2023 Nikita Koksharov 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/AckCallback.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | 19 | /** 20 | * Base ack callback class. 21 | * 22 | * Notifies about acknowledgement received from client 23 | * via {@link #onSuccess} callback method. 24 | * 25 | * By default it may wait acknowledgement from client 26 | * while {@link SocketIOClient} is alive. Timeout can be 27 | * defined {@link #timeout} as constructor argument. 28 | * 29 | * This object is NOT actual anymore if {@link #onSuccess} or 30 | * {@link #onTimeout} was executed. 31 | * 32 | * @param - any serializable type 33 | * 34 | * @see com.corundumstudio.socketio.VoidAckCallback 35 | * @see com.corundumstudio.socketio.MultiTypeAckCallback 36 | * 37 | */ 38 | public abstract class AckCallback { 39 | 40 | protected final Class resultClass; 41 | protected final int timeout; 42 | 43 | /** 44 | * Create AckCallback 45 | * 46 | * @param resultClass - result class 47 | */ 48 | public AckCallback(Class resultClass) { 49 | this(resultClass, -1); 50 | } 51 | 52 | /** 53 | * Creates AckCallback with timeout 54 | * 55 | * @param resultClass - result class 56 | * @param timeout - callback timeout in seconds 57 | */ 58 | public AckCallback(Class resultClass, int timeout) { 59 | this.resultClass = resultClass; 60 | this.timeout = timeout; 61 | } 62 | 63 | public int getTimeout() { 64 | return timeout; 65 | } 66 | 67 | /** 68 | * Executes only once when acknowledgement received from client. 69 | * 70 | * @param result - object sended by client 71 | */ 72 | public abstract void onSuccess(T result); 73 | 74 | /** 75 | * Invoked only once then timeout defined 76 | * 77 | */ 78 | public void onTimeout() { 79 | 80 | } 81 | 82 | /** 83 | * Returns class of argument in {@link #onSuccess} method 84 | * 85 | * @return - result class 86 | */ 87 | public Class getResultClass() { 88 | return resultClass; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/AckMode.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | public enum AckMode { 19 | 20 | /** 21 | * Send ack-response automatically on each ack-request 22 | * skip exceptions during packet handling 23 | */ 24 | AUTO, 25 | 26 | /** 27 | * Send ack-response automatically on each ack-request 28 | * only after success packet handling 29 | */ 30 | AUTO_SUCCESS_ONLY, 31 | 32 | /** 33 | * Turn off auto ack-response sending. 34 | * Use AckRequest.sendAckData to send ack-response each time. 35 | * 36 | */ 37 | MANUAL 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/AckRequest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | import java.util.Arrays; 19 | import java.util.List; 20 | import java.util.concurrent.atomic.AtomicBoolean; 21 | 22 | import com.corundumstudio.socketio.listener.DataListener; 23 | import com.corundumstudio.socketio.protocol.Packet; 24 | import com.corundumstudio.socketio.protocol.PacketType; 25 | 26 | /** 27 | * Ack request received from Socket.IO client. 28 | * You can always check is it true through 29 | * {@link #isAckRequested()} method. 30 | * 31 | * You can call {@link #sendAckData} methods only during 32 | * {@link DataListener#onData} invocation. If {@link #sendAckData} 33 | * not called it will be invoked with empty arguments right after 34 | * {@link DataListener#onData} method execution by server. 35 | * 36 | * This object is NOT actual anymore if {@link #sendAckData} was 37 | * executed or {@link DataListener#onData} invocation finished. 38 | * 39 | */ 40 | public class AckRequest { 41 | 42 | private final Packet originalPacket; 43 | private final SocketIOClient client; 44 | private final AtomicBoolean sended = new AtomicBoolean(); 45 | 46 | public AckRequest(Packet originalPacket, SocketIOClient client) { 47 | this.originalPacket = originalPacket; 48 | this.client = client; 49 | } 50 | 51 | /** 52 | * Check whether ack request was made 53 | * 54 | * @return true if ack requested by client 55 | */ 56 | public boolean isAckRequested() { 57 | return originalPacket.isAckRequested(); 58 | } 59 | 60 | /** 61 | * Send ack data to client. 62 | * Can be invoked only once during {@link DataListener#onData} 63 | * method invocation. 64 | * 65 | * @param objs - ack data objects 66 | */ 67 | public void sendAckData(Object ... objs) { 68 | List args = Arrays.asList(objs); 69 | sendAckData(args); 70 | } 71 | 72 | /** 73 | * Send ack data to client. 74 | * Can be invoked only once during {@link DataListener#onData} 75 | * method invocation. 76 | * 77 | * @param objs - ack data object list 78 | */ 79 | public void sendAckData(List objs) { 80 | if (!isAckRequested() || !sended.compareAndSet(false, true)) { 81 | return; 82 | } 83 | Packet ackPacket = new Packet(PacketType.MESSAGE, client.getEngineIOVersion()); 84 | ackPacket.setSubType(PacketType.ACK); 85 | ackPacket.setAckId(originalPacket.getAckId()); 86 | ackPacket.setData(objs); 87 | client.send(ackPacket); 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/AuthTokenListener.java: -------------------------------------------------------------------------------- 1 | package com.corundumstudio.socketio; 2 | 3 | /** 4 | * Copyright (c) 2012-2023 Nikita Koksharov 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | public interface AuthTokenListener { 20 | 21 | /** Socket.IO clients from version 4 can offer an auth token when connecting 22 | * to a namespace. This listener gets invoked if a token is found in the connect 23 | * packet 24 | * @param authToken the token as parsed by the JSON parser 25 | * @param client client that is connecting 26 | * @return authorization result 27 | */ 28 | AuthTokenResult getAuthTokenResult(Object authToken, SocketIOClient client); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/AuthTokenResult.java: -------------------------------------------------------------------------------- 1 | package com.corundumstudio.socketio; 2 | 3 | /** 4 | * Copyright (c) 2012-2023 Nikita Koksharov 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | public class AuthTokenResult { 20 | 21 | public final static AuthTokenResult AuthTokenResultSuccess = new AuthTokenResult(true, null); 22 | private final boolean success; 23 | private final Object errorData; 24 | 25 | public AuthTokenResult(final boolean success, final Object errorData) { 26 | this.success = success; 27 | this.errorData = errorData; 28 | } 29 | 30 | public boolean isSuccess() { 31 | return success; 32 | } 33 | 34 | public Object getErrorData() { 35 | return errorData; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/AuthorizationListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | public interface AuthorizationListener { 19 | 20 | /** 21 | * Checks whether a client with handshake data is authorized on connection 22 | * Optionally returns storeParams that will be added to {@link SocketIOClient} store 23 | * 24 | * @param data handshake data 25 | * @return - {@link AuthorizationResult} 26 | */ 27 | AuthorizationResult getAuthorizationResult(HandshakeData data); 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/AuthorizationResult.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | import java.util.Collections; 19 | import java.util.Map; 20 | 21 | public class AuthorizationResult { 22 | 23 | public static final AuthorizationResult SUCCESSFUL_AUTHORIZATION = new AuthorizationResult(true); 24 | public static final AuthorizationResult FAILED_AUTHORIZATION = new AuthorizationResult(false); 25 | private final boolean isAuthorized; 26 | private final Map storeParams; 27 | 28 | public AuthorizationResult(boolean isAuthorized) { 29 | this.isAuthorized = isAuthorized; 30 | this.storeParams = Collections.emptyMap(); 31 | } 32 | 33 | public AuthorizationResult(boolean isAuthorized, Map storeParams) { 34 | this.isAuthorized = isAuthorized; 35 | this.storeParams = isAuthorized && storeParams != null ? 36 | Collections.unmodifiableMap(storeParams) : Collections.emptyMap(); 37 | } 38 | 39 | /** 40 | * @return true if a client is authorized, otherwise - false 41 | * */ 42 | public boolean isAuthorized() { 43 | return isAuthorized; 44 | } 45 | 46 | /** 47 | * @return key-value pairs (unmodifiable) that will be added to {@link SocketIOClient } store. 48 | * If a client is not authorized, storeParams will always be ignored (empty map) 49 | * */ 50 | public Map getStoreParams() { 51 | return storeParams; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/BroadcastAckCallback.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | import java.util.concurrent.atomic.AtomicBoolean; 19 | import java.util.concurrent.atomic.AtomicInteger; 20 | 21 | public class BroadcastAckCallback { 22 | 23 | final AtomicBoolean loopFinished = new AtomicBoolean(); 24 | final AtomicInteger counter = new AtomicInteger(); 25 | final AtomicBoolean successExecuted = new AtomicBoolean(); 26 | final Class resultClass; 27 | final int timeout; 28 | 29 | public BroadcastAckCallback(Class resultClass, int timeout) { 30 | this.resultClass = resultClass; 31 | this.timeout = timeout; 32 | } 33 | 34 | public BroadcastAckCallback(Class resultClass) { 35 | this(resultClass, -1); 36 | } 37 | 38 | final AckCallback createClientCallback(final SocketIOClient client) { 39 | counter.getAndIncrement(); 40 | return new AckCallback(resultClass, timeout) { 41 | @Override 42 | public void onSuccess(T result) { 43 | counter.getAndDecrement(); 44 | onClientSuccess(client, result); 45 | executeSuccess(); 46 | } 47 | 48 | @Override 49 | public void onTimeout() { 50 | onClientTimeout(client); 51 | } 52 | 53 | }; 54 | } 55 | 56 | protected void onClientTimeout(SocketIOClient client) { 57 | 58 | } 59 | 60 | protected void onClientSuccess(SocketIOClient client, T result) { 61 | 62 | } 63 | 64 | protected void onAllSuccess() { 65 | 66 | } 67 | 68 | private void executeSuccess() { 69 | if (loopFinished.get() 70 | && counter.get() == 0 71 | && successExecuted.compareAndSet(false, true)) { 72 | onAllSuccess(); 73 | } 74 | } 75 | 76 | void loopFinished() { 77 | loopFinished.set(true); 78 | executeSuccess(); 79 | } 80 | 81 | } 82 | 83 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/BroadcastOperations.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | import com.corundumstudio.socketio.protocol.Packet; 19 | 20 | import java.util.Collection; 21 | import java.util.function.Predicate; 22 | 23 | /** 24 | * broadcast interface 25 | * 26 | */ 27 | public interface BroadcastOperations extends ClientOperations { 28 | 29 | Collection getClients(); 30 | 31 | void send(Packet packet, BroadcastAckCallback ackCallback); 32 | 33 | void sendEvent(String name, SocketIOClient excludedClient, Object... data); 34 | 35 | void sendEvent(String name, Predicate excludePredicate, Object... data); 36 | 37 | void sendEvent(String name, Object data, BroadcastAckCallback ackCallback); 38 | 39 | void sendEvent(String name, Object data, SocketIOClient excludedClient, BroadcastAckCallback ackCallback); 40 | 41 | void sendEvent(String name, Object data, Predicate excludePredicate, BroadcastAckCallback ackCallback); 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/ClientOperations.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | import com.corundumstudio.socketio.protocol.Packet; 19 | 20 | /** 21 | * Available client operations 22 | * 23 | */ 24 | public interface ClientOperations { 25 | 26 | /** 27 | * Send custom packet. 28 | * But {@link ClientOperations#sendEvent} method 29 | * usage is enough for most cases. 30 | * 31 | * @param packet - packet to send 32 | */ 33 | void send(Packet packet); 34 | 35 | /** 36 | * Disconnect client 37 | * 38 | */ 39 | void disconnect(); 40 | 41 | /** 42 | * Send event 43 | * 44 | * @param name - event name 45 | * @param data - event data 46 | */ 47 | void sendEvent(String name, Object ... data); 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/Disconnectable.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | import com.corundumstudio.socketio.handler.ClientHead; 19 | 20 | 21 | 22 | public interface Disconnectable { 23 | 24 | void onDisconnect(ClientHead client); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/DisconnectableHub.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | public interface DisconnectableHub extends Disconnectable { 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/HandshakeData.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | import java.io.Serializable; 19 | import java.net.InetSocketAddress; 20 | import java.util.Date; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | import io.netty.handler.codec.http.HttpHeaders; 25 | 26 | public class HandshakeData implements Serializable { 27 | 28 | private static final long serialVersionUID = 1196350300161819978L; 29 | 30 | private HttpHeaders headers; 31 | private InetSocketAddress address; 32 | private Date time = new Date(); 33 | private InetSocketAddress local; 34 | private String url; 35 | private Map> urlParams; 36 | private boolean xdomain; 37 | private Object authToken; 38 | 39 | // needed for correct deserialization 40 | public HandshakeData() { 41 | } 42 | 43 | public HandshakeData(HttpHeaders headers, Map> urlParams, InetSocketAddress address, String url, boolean xdomain) { 44 | this(headers, urlParams, address, null, url, xdomain); 45 | } 46 | 47 | public HandshakeData(HttpHeaders headers, Map> urlParams, InetSocketAddress address, InetSocketAddress local, String url, boolean xdomain) { 48 | super(); 49 | this.headers = headers; 50 | this.urlParams = urlParams; 51 | this.address = address; 52 | this.local = local; 53 | this.url = url; 54 | this.xdomain = xdomain; 55 | } 56 | 57 | /** 58 | * Client network address 59 | * 60 | * @return network address 61 | */ 62 | public InetSocketAddress getAddress() { 63 | return address; 64 | } 65 | 66 | /** 67 | * Connection local address 68 | * 69 | * @return local address 70 | */ 71 | public InetSocketAddress getLocal() { 72 | return local; 73 | } 74 | 75 | /** 76 | * Http headers sent during first client request 77 | * 78 | * @return headers 79 | */ 80 | public HttpHeaders getHttpHeaders() { 81 | return headers; 82 | } 83 | 84 | /** 85 | * Client connection date 86 | * 87 | * @return date 88 | */ 89 | public Date getTime() { 90 | return time; 91 | } 92 | 93 | /** 94 | * Url used by client during first request 95 | * 96 | * @return url 97 | */ 98 | public String getUrl() { 99 | return url; 100 | } 101 | 102 | public boolean isXdomain() { 103 | return xdomain; 104 | } 105 | 106 | /** 107 | * Url params stored in url used by client during first request 108 | * 109 | * @return map 110 | */ 111 | public Map> getUrlParams() { 112 | return urlParams; 113 | } 114 | 115 | public String getSingleUrlParam(String name) { 116 | List values = urlParams.get(name); 117 | if (values != null && values.size() == 1) { 118 | return values.iterator().next(); 119 | } 120 | return null; 121 | } 122 | 123 | public void setAuthToken(Object token) { 124 | this.authToken = token; 125 | } 126 | 127 | public Object getAuthToken() { 128 | return this.authToken; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/HttpRequestDecoderConfiguration.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | public class HttpRequestDecoderConfiguration { 19 | 20 | private int maxInitialLineLength; 21 | private int maxHeaderSize; 22 | private int maxChunkSize; 23 | 24 | public HttpRequestDecoderConfiguration(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) { 25 | this.maxInitialLineLength = maxInitialLineLength; 26 | this.maxHeaderSize = maxHeaderSize; 27 | this.maxChunkSize = maxChunkSize; 28 | } 29 | 30 | public HttpRequestDecoderConfiguration() { 31 | this(4096, 8192, 8192); 32 | } 33 | 34 | public int getMaxInitialLineLength() { 35 | return maxInitialLineLength; 36 | } 37 | 38 | public void setMaxInitialLineLength(int maxInitialLineLength) { 39 | this.maxInitialLineLength = maxInitialLineLength; 40 | } 41 | 42 | public int getMaxHeaderSize() { 43 | return maxHeaderSize; 44 | } 45 | 46 | public void setMaxHeaderSize(int maxHeaderSize) { 47 | this.maxHeaderSize = maxHeaderSize; 48 | } 49 | 50 | public int getMaxChunkSize() { 51 | return maxChunkSize; 52 | } 53 | 54 | public void setMaxChunkSize(int maxChunkSize) { 55 | this.maxChunkSize = maxChunkSize; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/JsonSupportWrapper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | import io.netty.buffer.ByteBufInputStream; 19 | import io.netty.buffer.ByteBufOutputStream; 20 | 21 | import java.io.IOException; 22 | import java.util.List; 23 | 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | 27 | import com.corundumstudio.socketio.protocol.AckArgs; 28 | import com.corundumstudio.socketio.protocol.JsonSupport; 29 | 30 | class JsonSupportWrapper implements JsonSupport { 31 | 32 | private static final Logger log = LoggerFactory.getLogger(JsonSupportWrapper.class); 33 | 34 | private final JsonSupport delegate; 35 | 36 | JsonSupportWrapper(JsonSupport delegate) { 37 | this.delegate = delegate; 38 | } 39 | 40 | @Override 41 | public AckArgs readAckArgs(ByteBufInputStream src, AckCallback callback) throws IOException { 42 | try { 43 | return delegate.readAckArgs(src, callback); 44 | } catch (Exception e) { 45 | src.reset(); 46 | log.error("Can't read ack args: " + src.readLine() + " for type: " + callback.getResultClass(), e); 47 | throw new IOException(e); 48 | } 49 | } 50 | 51 | @Override 52 | public T readValue(String namespaceName, ByteBufInputStream src, Class valueType) throws IOException { 53 | try { 54 | return delegate.readValue(namespaceName, src, valueType); 55 | } catch (Exception e) { 56 | src.reset(); 57 | log.error("Can't read value: " + src.readLine() + " for type: " + valueType, e); 58 | throw new IOException(e); 59 | } 60 | } 61 | 62 | @Override 63 | public void writeValue(ByteBufOutputStream out, Object value) throws IOException { 64 | try { 65 | delegate.writeValue(out, value); 66 | } catch (Exception e) { 67 | log.error("Can't write value: " + value, e); 68 | throw new IOException(e); 69 | } 70 | } 71 | 72 | @Override 73 | public void addEventMapping(String namespaceName, String eventName, Class ... eventClass) { 74 | delegate.addEventMapping(namespaceName, eventName, eventClass); 75 | } 76 | 77 | @Override 78 | public void removeEventMapping(String namespaceName, String eventName) { 79 | delegate.removeEventMapping(namespaceName, eventName); 80 | } 81 | 82 | @Override 83 | public List getArrays() { 84 | return delegate.getArrays(); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/MultiRoomBroadcastOperations.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | import com.corundumstudio.socketio.protocol.Packet; 19 | 20 | import java.util.Collection; 21 | import java.util.HashSet; 22 | import java.util.Objects; 23 | import java.util.Set; 24 | import java.util.function.Predicate; 25 | 26 | /** 27 | * author: liangjiaqi 28 | * date: 2020/8/8 6:02 PM 29 | */ 30 | public class MultiRoomBroadcastOperations implements BroadcastOperations { 31 | 32 | private final Collection broadcastOperations; 33 | 34 | public MultiRoomBroadcastOperations(Collection broadcastOperations) { 35 | this.broadcastOperations = broadcastOperations; 36 | } 37 | 38 | @Override 39 | public Collection getClients() { 40 | Set clients = new HashSet(); 41 | if( this.broadcastOperations == null || this.broadcastOperations.size() == 0 ) { 42 | return clients; 43 | } 44 | for( BroadcastOperations b : this.broadcastOperations ) { 45 | clients.addAll( b.getClients() ); 46 | } 47 | return clients; 48 | } 49 | 50 | @Override 51 | public void send(Packet packet, BroadcastAckCallback ackCallback) { 52 | if( this.broadcastOperations == null || this.broadcastOperations.size() == 0 ) { 53 | return; 54 | } 55 | for( BroadcastOperations b : this.broadcastOperations ) { 56 | b.send( packet, ackCallback ); 57 | } 58 | } 59 | 60 | @Override 61 | public void sendEvent(String name, SocketIOClient excludedClient, Object... data) { 62 | Predicate excludePredicate = (socketIOClient) -> Objects.equals( 63 | socketIOClient.getSessionId(), excludedClient.getSessionId() 64 | ); 65 | sendEvent(name, excludePredicate, data); 66 | } 67 | 68 | @Override 69 | public void sendEvent(String name, Predicate excludePredicate, Object... data) { 70 | if( this.broadcastOperations == null || this.broadcastOperations.size() == 0 ) { 71 | return; 72 | } 73 | for( BroadcastOperations b : this.broadcastOperations ) { 74 | b.sendEvent( name, excludePredicate, data ); 75 | } 76 | } 77 | 78 | @Override 79 | public void sendEvent(String name, Object data, BroadcastAckCallback ackCallback) { 80 | if( this.broadcastOperations == null || this.broadcastOperations.size() == 0 ) { 81 | return; 82 | } 83 | for( BroadcastOperations b : this.broadcastOperations ) { 84 | b.sendEvent( name, data, ackCallback ); 85 | } 86 | } 87 | 88 | @Override 89 | public void sendEvent(String name, Object data, SocketIOClient excludedClient, BroadcastAckCallback ackCallback) { 90 | Predicate excludePredicate = (socketIOClient) -> Objects.equals( 91 | socketIOClient.getSessionId(), excludedClient.getSessionId() 92 | ); 93 | sendEvent(name, data, excludePredicate, ackCallback); 94 | } 95 | 96 | @Override 97 | public void sendEvent(String name, Object data, Predicate excludePredicate, BroadcastAckCallback ackCallback) { 98 | if( this.broadcastOperations == null || this.broadcastOperations.size() == 0 ) { 99 | return; 100 | } 101 | for( BroadcastOperations b : this.broadcastOperations ) { 102 | b.sendEvent( name, data, excludePredicate, ackCallback ); 103 | } 104 | } 105 | 106 | @Override 107 | public void send(Packet packet) { 108 | if( this.broadcastOperations == null || this.broadcastOperations.size() == 0 ) { 109 | return; 110 | } 111 | for( BroadcastOperations b : this.broadcastOperations ) { 112 | b.send( packet ); 113 | } 114 | } 115 | 116 | @Override 117 | public void disconnect() { 118 | if( this.broadcastOperations == null || this.broadcastOperations.size() == 0 ) { 119 | return; 120 | } 121 | for( BroadcastOperations b : this.broadcastOperations ) { 122 | b.disconnect(); 123 | } 124 | } 125 | 126 | @Override 127 | public void sendEvent(String name, Object... data) { 128 | if( this.broadcastOperations == null || this.broadcastOperations.size() == 0 ) { 129 | return; 130 | } 131 | for( BroadcastOperations b : this.broadcastOperations ) { 132 | b.sendEvent( name, data ); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/MultiTypeAckCallback.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | /** 19 | * Multi type ack callback used in case of multiple ack arguments 20 | * 21 | */ 22 | public abstract class MultiTypeAckCallback extends AckCallback { 23 | 24 | private Class[] resultClasses; 25 | 26 | public MultiTypeAckCallback(Class ... resultClasses) { 27 | super(MultiTypeArgs.class); 28 | this.resultClasses = resultClasses; 29 | } 30 | 31 | public Class[] getResultClasses() { 32 | return resultClasses; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/MultiTypeArgs.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | import java.util.Iterator; 19 | import java.util.List; 20 | 21 | public class MultiTypeArgs implements Iterable { 22 | 23 | private final List args; 24 | 25 | public MultiTypeArgs(List args) { 26 | super(); 27 | this.args = args; 28 | } 29 | 30 | public boolean isEmpty() { 31 | return size() == 0; 32 | } 33 | 34 | public int size() { 35 | return args.size(); 36 | } 37 | 38 | public List getArgs() { 39 | return args; 40 | } 41 | 42 | public T first() { 43 | return get(0); 44 | } 45 | 46 | public T second() { 47 | return get(1); 48 | } 49 | 50 | /** 51 | * "index out of bounds"-safe method for getting elements 52 | * 53 | * @param type of argument 54 | * @param index to get 55 | * @return argument 56 | */ 57 | public T get(int index) { 58 | if (size() <= index) { 59 | return null; 60 | } 61 | return (T) args.get(index); 62 | } 63 | 64 | @Override 65 | public Iterator iterator() { 66 | return args.iterator(); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/SocketConfig.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | /** 19 | * TCP socket configuration contains configuration for main server channel 20 | * and client channels 21 | * 22 | * @see java.net.SocketOptions 23 | */ 24 | public class SocketConfig { 25 | 26 | private boolean tcpNoDelay = true; 27 | 28 | private int tcpSendBufferSize = -1; 29 | 30 | private int tcpReceiveBufferSize = -1; 31 | 32 | private boolean tcpKeepAlive = false; 33 | 34 | private int soLinger = -1; 35 | 36 | private boolean reuseAddress = false; 37 | 38 | private int acceptBackLog = 1024; 39 | 40 | private int writeBufferWaterMarkLow = -1; 41 | 42 | private int writeBufferWaterMarkHigh = -1; 43 | 44 | public boolean isTcpNoDelay() { 45 | return tcpNoDelay; 46 | } 47 | public void setTcpNoDelay(boolean tcpNoDelay) { 48 | this.tcpNoDelay = tcpNoDelay; 49 | } 50 | 51 | public int getTcpSendBufferSize() { 52 | return tcpSendBufferSize; 53 | } 54 | public void setTcpSendBufferSize(int tcpSendBufferSize) { 55 | this.tcpSendBufferSize = tcpSendBufferSize; 56 | } 57 | 58 | public int getTcpReceiveBufferSize() { 59 | return tcpReceiveBufferSize; 60 | } 61 | public void setTcpReceiveBufferSize(int tcpReceiveBufferSize) { 62 | this.tcpReceiveBufferSize = tcpReceiveBufferSize; 63 | } 64 | 65 | public boolean isTcpKeepAlive() { 66 | return tcpKeepAlive; 67 | } 68 | public void setTcpKeepAlive(boolean tcpKeepAlive) { 69 | this.tcpKeepAlive = tcpKeepAlive; 70 | } 71 | 72 | public int getSoLinger() { 73 | return soLinger; 74 | } 75 | public void setSoLinger(int soLinger) { 76 | this.soLinger = soLinger; 77 | } 78 | 79 | public boolean isReuseAddress() { 80 | return reuseAddress; 81 | } 82 | public void setReuseAddress(boolean reuseAddress) { 83 | this.reuseAddress = reuseAddress; 84 | } 85 | 86 | public int getAcceptBackLog() { 87 | return acceptBackLog; 88 | } 89 | public void setAcceptBackLog(int acceptBackLog) { 90 | this.acceptBackLog = acceptBackLog; 91 | } 92 | 93 | public int getWriteBufferWaterMarkLow() { 94 | return writeBufferWaterMarkLow; 95 | } 96 | 97 | public void setWriteBufferWaterMarkLow(int writeBufferWaterMarkLow) { 98 | this.writeBufferWaterMarkLow = writeBufferWaterMarkLow; 99 | } 100 | 101 | public int getWriteBufferWaterMarkHigh() { 102 | return writeBufferWaterMarkHigh; 103 | } 104 | 105 | public void setWriteBufferWaterMarkHigh(int writeBufferWaterMarkHigh) { 106 | this.writeBufferWaterMarkHigh = writeBufferWaterMarkHigh; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/SocketIOClient.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | import java.net.SocketAddress; 19 | import java.util.Set; 20 | import java.util.UUID; 21 | 22 | import com.corundumstudio.socketio.protocol.EngineIOVersion; 23 | import com.corundumstudio.socketio.protocol.Packet; 24 | import com.corundumstudio.socketio.store.Store; 25 | 26 | 27 | /** 28 | * Fully thread-safe. 29 | * 30 | */ 31 | public interface SocketIOClient extends ClientOperations, Store { 32 | 33 | /** 34 | * Handshake data used during client connection 35 | * 36 | * @return HandshakeData 37 | */ 38 | HandshakeData getHandshakeData(); 39 | 40 | /** 41 | * Current client transport protocol 42 | * 43 | * @return transport protocol 44 | */ 45 | Transport getTransport(); 46 | 47 | /** 48 | * Engine IO Protocol version 49 | * @return 50 | */ 51 | EngineIOVersion getEngineIOVersion(); 52 | 53 | /** 54 | * Returns true if and only if the I/O thread will perform the requested write operation immediately. 55 | * Any write requests made when this method returns false are queued until the I/O thread is ready to process the queued write requests. 56 | * @return 57 | */ 58 | boolean isWritable(); 59 | 60 | /** 61 | * Send event with ack callback 62 | * 63 | * @param name - event name 64 | * @param data - event data 65 | * @param ackCallback - ack callback 66 | */ 67 | void sendEvent(String name, AckCallback ackCallback, Object ... data); 68 | 69 | /** 70 | * Send packet with ack callback 71 | * 72 | * @param packet - packet to send 73 | * @param ackCallback - ack callback 74 | */ 75 | void send(Packet packet, AckCallback ackCallback); 76 | 77 | /** 78 | * Client namespace 79 | * 80 | * @return - namespace 81 | */ 82 | SocketIONamespace getNamespace(); 83 | 84 | /** 85 | * Client session id, uses {@link UUID} object 86 | * 87 | * @return - session id 88 | */ 89 | UUID getSessionId(); 90 | 91 | /** 92 | * Get client remote address 93 | * 94 | * @return remote address 95 | */ 96 | SocketAddress getRemoteAddress(); 97 | 98 | /** 99 | * Check is underlying channel open 100 | * 101 | * @return true if channel open, otherwise false 102 | */ 103 | boolean isChannelOpen(); 104 | 105 | /** 106 | * Join client to room 107 | * 108 | * @param room - name of room 109 | */ 110 | void joinRoom(String room); 111 | 112 | /** 113 | * Join client to rooms 114 | * 115 | * @param rooms - names of rooms 116 | */ 117 | void joinRooms(Set rooms); 118 | 119 | /** 120 | * Leave client from room 121 | * 122 | * @param room - name of room 123 | */ 124 | void leaveRoom(String room); 125 | 126 | /** 127 | * Leave client from rooms 128 | * 129 | * @param rooms - names of rooms 130 | */ 131 | void leaveRooms(Set rooms); 132 | 133 | /** 134 | * Get all rooms a client is joined in. 135 | * 136 | * @return name of rooms 137 | */ 138 | Set getAllRooms(); 139 | 140 | /** 141 | * Get current room Size (contain in cluster) 142 | * 143 | * @param room - name of room 144 | * 145 | * @return int 146 | */ 147 | int getCurrentRoomSize(String room); 148 | 149 | } 150 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/SocketIONamespace.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | import java.util.Collection; 19 | import java.util.UUID; 20 | 21 | import com.corundumstudio.socketio.listener.ClientListeners; 22 | 23 | /** 24 | * Fully thread-safe. 25 | * 26 | */ 27 | public interface SocketIONamespace extends ClientListeners { 28 | 29 | String getName(); 30 | 31 | BroadcastOperations getBroadcastOperations(); 32 | 33 | BroadcastOperations getRoomOperations(String room); 34 | 35 | BroadcastOperations getRoomOperations(String... rooms); 36 | 37 | /** 38 | * Get all clients connected to namespace 39 | * 40 | * @return collection of clients 41 | */ 42 | Collection getAllClients(); 43 | 44 | /** 45 | * Get client by uuid connected to namespace 46 | * 47 | * @param uuid - id of client 48 | * @return client 49 | */ 50 | SocketIOClient getClient(UUID uuid); 51 | 52 | void addAuthTokenListener(AuthTokenListener listener); 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/Transport.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | import com.corundumstudio.socketio.transport.WebSocketTransport; 19 | import com.corundumstudio.socketio.transport.PollingTransport; 20 | 21 | public enum Transport { 22 | 23 | WEBSOCKET(WebSocketTransport.NAME), 24 | POLLING(PollingTransport.NAME); 25 | 26 | private final String value; 27 | 28 | Transport(String value) { 29 | this.value = value; 30 | } 31 | 32 | public String getValue() { 33 | return value; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/VoidAckCallback.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | /** 19 | * Base ack callback with {@link Void} class as type. 20 | * 21 | */ 22 | public abstract class VoidAckCallback extends AckCallback { 23 | 24 | public VoidAckCallback() { 25 | super(Void.class); 26 | } 27 | 28 | public VoidAckCallback(int timeout) { 29 | super(Void.class, timeout); 30 | } 31 | 32 | @Override 33 | public final void onSuccess(Void result) { 34 | onSuccess(); 35 | } 36 | 37 | protected abstract void onSuccess(); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/ack/AckSchedulerKey.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.ack; 17 | 18 | import java.util.UUID; 19 | 20 | import com.corundumstudio.socketio.scheduler.SchedulerKey; 21 | 22 | public class AckSchedulerKey extends SchedulerKey { 23 | 24 | private final long index; 25 | 26 | public AckSchedulerKey(Type type, UUID sessionId, long index) { 27 | super(type, sessionId); 28 | this.index = index; 29 | } 30 | 31 | public long getIndex() { 32 | return index; 33 | } 34 | 35 | @Override 36 | public int hashCode() { 37 | final int prime = 31; 38 | int result = super.hashCode(); 39 | result = prime * result + (int) (index ^ (index >>> 32)); 40 | return result; 41 | } 42 | 43 | @Override 44 | public boolean equals(Object obj) { 45 | if (this == obj) 46 | return true; 47 | if (!super.equals(obj)) 48 | return false; 49 | if (getClass() != obj.getClass()) 50 | return false; 51 | AckSchedulerKey other = (AckSchedulerKey) obj; 52 | if (index != other.index) 53 | return false; 54 | return true; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/annotation/AnnotationScanner.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.annotation; 17 | 18 | import java.lang.annotation.Annotation; 19 | import java.lang.reflect.Method; 20 | 21 | import com.corundumstudio.socketio.namespace.Namespace; 22 | 23 | public interface AnnotationScanner { 24 | 25 | Class getScanAnnotation(); 26 | 27 | void addListener(Namespace namespace, Object object, Method method, Annotation annotation); 28 | 29 | void validate(Method method, Class clazz); 30 | 31 | } -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/annotation/OnConnect.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.annotation; 17 | 18 | import java.lang.annotation.ElementType; 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.annotation.Target; 22 | 23 | 24 | /** 25 | * Annotation that defines Connect handler. 26 | * 27 | * Arguments in method: 28 | * 29 | * - SocketIOClient (required) 30 | * 31 | */ 32 | @Target(ElementType.METHOD) 33 | @Retention(RetentionPolicy.RUNTIME) 34 | public @interface OnConnect { 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/annotation/OnConnectScanner.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.annotation; 17 | 18 | import java.lang.annotation.Annotation; 19 | import java.lang.reflect.InvocationTargetException; 20 | import java.lang.reflect.Method; 21 | 22 | import com.corundumstudio.socketio.SocketIOClient; 23 | import com.corundumstudio.socketio.handler.SocketIOException; 24 | import com.corundumstudio.socketio.listener.ConnectListener; 25 | import com.corundumstudio.socketio.namespace.Namespace; 26 | 27 | public class OnConnectScanner implements AnnotationScanner { 28 | 29 | @Override 30 | public Class getScanAnnotation() { 31 | return OnConnect.class; 32 | } 33 | 34 | @Override 35 | public void addListener(Namespace namespace, final Object object, final Method method, Annotation annotation) { 36 | namespace.addConnectListener(new ConnectListener() { 37 | @Override 38 | public void onConnect(SocketIOClient client) { 39 | try { 40 | method.invoke(object, client); 41 | } catch (InvocationTargetException e) { 42 | throw new SocketIOException(e.getCause()); 43 | } catch (Exception e) { 44 | throw new SocketIOException(e); 45 | } 46 | } 47 | }); 48 | } 49 | 50 | @Override 51 | public void validate(Method method, Class clazz) { 52 | if (method.getParameterTypes().length != 1) { 53 | throw new IllegalArgumentException("Wrong OnConnect listener signature: " + clazz + "." + method.getName()); 54 | } 55 | 56 | for (Class eventType : method.getParameterTypes()) { 57 | if (SocketIOClient.class.equals(eventType)) { 58 | return; 59 | } 60 | } 61 | 62 | throw new IllegalArgumentException("Wrong OnConnect listener signature: " + clazz + "." + method.getName()); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/annotation/OnDisconnect.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.annotation; 17 | 18 | import java.lang.annotation.ElementType; 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.annotation.Target; 22 | 23 | /** 24 | * Annotation that defines Disconnect handler. 25 | * 26 | * Arguments in method: 27 | * 28 | * - SocketIOClient (required) 29 | * 30 | */ 31 | @Target(ElementType.METHOD) 32 | @Retention(RetentionPolicy.RUNTIME) 33 | public @interface OnDisconnect { 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/annotation/OnDisconnectScanner.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.annotation; 17 | 18 | import java.lang.annotation.Annotation; 19 | import java.lang.reflect.InvocationTargetException; 20 | import java.lang.reflect.Method; 21 | 22 | import com.corundumstudio.socketio.SocketIOClient; 23 | import com.corundumstudio.socketio.handler.SocketIOException; 24 | import com.corundumstudio.socketio.listener.DisconnectListener; 25 | import com.corundumstudio.socketio.namespace.Namespace; 26 | 27 | public class OnDisconnectScanner implements AnnotationScanner { 28 | 29 | @Override 30 | public Class getScanAnnotation() { 31 | return OnDisconnect.class; 32 | } 33 | 34 | @Override 35 | public void addListener(Namespace namespace, final Object object, final Method method, Annotation annotation) { 36 | namespace.addDisconnectListener(new DisconnectListener() { 37 | @Override 38 | public void onDisconnect(SocketIOClient client) { 39 | try { 40 | method.invoke(object, client); 41 | } catch (InvocationTargetException e) { 42 | throw new SocketIOException(e.getCause()); 43 | } catch (Exception e) { 44 | throw new SocketIOException(e); 45 | } 46 | } 47 | }); 48 | } 49 | 50 | @Override 51 | public void validate(Method method, Class clazz) { 52 | if (method.getParameterTypes().length != 1) { 53 | throw new IllegalArgumentException("Wrong OnDisconnect listener signature: " + clazz + "." + method.getName()); 54 | } 55 | 56 | for (Class eventType : method.getParameterTypes()) { 57 | if (SocketIOClient.class.equals(eventType)) { 58 | return; 59 | } 60 | } 61 | 62 | throw new IllegalArgumentException("Wrong OnDisconnect listener signature: " + clazz + "." + method.getName()); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/annotation/OnEvent.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.annotation; 17 | 18 | import java.lang.annotation.ElementType; 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.annotation.Target; 22 | 23 | /** 24 | * Annotation that defines Event handler. 25 | * The value is required, and represents event name. 26 | * 27 | * Arguments in method: 28 | * 29 | * - SocketIOClient (optional) 30 | * - AckRequest (optional) 31 | * - Event data (optional) 32 | * 33 | */ 34 | @Target(ElementType.METHOD) 35 | @Retention(RetentionPolicy.RUNTIME) 36 | public @interface OnEvent { 37 | 38 | /** 39 | * Event name 40 | * 41 | * @return value 42 | */ 43 | String value(); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/annotation/ScannerEngine.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.annotation; 17 | 18 | import java.lang.annotation.Annotation; 19 | import java.lang.reflect.Method; 20 | import java.lang.reflect.Modifier; 21 | import java.util.Arrays; 22 | import java.util.List; 23 | 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | 27 | import com.corundumstudio.socketio.namespace.Namespace; 28 | 29 | public class ScannerEngine { 30 | 31 | private static final Logger log = LoggerFactory.getLogger(ScannerEngine.class); 32 | 33 | private static final List annotations = 34 | Arrays.asList(new OnConnectScanner(), new OnDisconnectScanner(), new OnEventScanner()); 35 | 36 | private Method findSimilarMethod(Class objectClazz, Method method) { 37 | Method[] methods = objectClazz.getDeclaredMethods(); 38 | for (Method m : methods) { 39 | if (isEquals(m, method)) { 40 | return m; 41 | } 42 | } 43 | return null; 44 | } 45 | 46 | public void scan(Namespace namespace, Object object, Class clazz) 47 | throws IllegalArgumentException { 48 | Method[] methods = clazz.getDeclaredMethods(); 49 | 50 | if (!clazz.isAssignableFrom(object.getClass())) { 51 | for (Method method : methods) { 52 | for (AnnotationScanner annotationScanner : annotations) { 53 | Annotation ann = method.getAnnotation(annotationScanner.getScanAnnotation()); 54 | if (ann != null) { 55 | annotationScanner.validate(method, clazz); 56 | 57 | Method m = findSimilarMethod(object.getClass(), method); 58 | if (m != null) { 59 | annotationScanner.addListener(namespace, object, m, ann); 60 | } else { 61 | log.warn("Method similar to " + method.getName() + " can't be found in " + object.getClass()); 62 | } 63 | } 64 | } 65 | } 66 | } else { 67 | for (Method method : methods) { 68 | for (AnnotationScanner annotationScanner : annotations) { 69 | Annotation ann = method.getAnnotation(annotationScanner.getScanAnnotation()); 70 | if (ann != null) { 71 | annotationScanner.validate(method, clazz); 72 | makeAccessible(method); 73 | annotationScanner.addListener(namespace, object, method, ann); 74 | } 75 | } 76 | } 77 | 78 | if (clazz.getSuperclass() != null) { 79 | scan(namespace, object, clazz.getSuperclass()); 80 | } else if (clazz.isInterface()) { 81 | for (Class superIfc : clazz.getInterfaces()) { 82 | scan(namespace, object, superIfc); 83 | } 84 | } 85 | } 86 | 87 | } 88 | 89 | private boolean isEquals(Method method1, Method method2) { 90 | if (!method1.getName().equals(method2.getName()) 91 | || !method1.getReturnType().equals(method2.getReturnType())) { 92 | return false; 93 | } 94 | 95 | return Arrays.equals(method1.getParameterTypes(), method2.getParameterTypes()); 96 | } 97 | 98 | private void makeAccessible(Method method) { 99 | if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) 100 | && !method.isAccessible()) { 101 | method.setAccessible(true); 102 | } 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/annotation/SpringAnnotationScanner.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.annotation; 17 | 18 | import java.lang.annotation.Annotation; 19 | import java.lang.reflect.Method; 20 | import java.util.Arrays; 21 | import java.util.List; 22 | import java.util.concurrent.atomic.AtomicBoolean; 23 | 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | import org.springframework.beans.BeansException; 27 | import org.springframework.beans.factory.config.BeanPostProcessor; 28 | import org.springframework.util.ReflectionUtils; 29 | import org.springframework.util.ReflectionUtils.MethodCallback; 30 | import org.springframework.util.ReflectionUtils.MethodFilter; 31 | 32 | import com.corundumstudio.socketio.SocketIOServer; 33 | 34 | public class SpringAnnotationScanner implements BeanPostProcessor { 35 | 36 | private static final Logger log = LoggerFactory.getLogger(SpringAnnotationScanner.class); 37 | 38 | private final List> annotations = 39 | Arrays.asList(OnConnect.class, OnDisconnect.class, OnEvent.class); 40 | 41 | private final SocketIOServer socketIOServer; 42 | 43 | private Class originalBeanClass; 44 | 45 | private Object originalBean; 46 | 47 | private String originalBeanName; 48 | 49 | public SpringAnnotationScanner(SocketIOServer socketIOServer) { 50 | super(); 51 | this.socketIOServer = socketIOServer; 52 | } 53 | 54 | @Override 55 | public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 56 | if (originalBeanClass != null) { 57 | socketIOServer.addListeners(originalBean, originalBeanClass); 58 | log.info("{} bean listeners added", originalBeanName); 59 | originalBeanClass = null; 60 | originalBeanName = null; 61 | } 62 | return bean; 63 | } 64 | 65 | @Override 66 | public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 67 | final AtomicBoolean add = new AtomicBoolean(); 68 | ReflectionUtils.doWithMethods(bean.getClass(), 69 | new MethodCallback() { 70 | @Override 71 | public void doWith(Method method) throws IllegalArgumentException, 72 | IllegalAccessException { 73 | add.set(true); 74 | } 75 | }, 76 | new MethodFilter() { 77 | @Override 78 | public boolean matches(Method method) { 79 | for (Class annotationClass : annotations) { 80 | if (method.isAnnotationPresent(annotationClass)) { 81 | return true; 82 | } 83 | } 84 | return false; 85 | } 86 | }); 87 | 88 | if (add.get()) { 89 | originalBeanClass = bean.getClass(); 90 | originalBean = bean; 91 | originalBeanName = beanName; 92 | } 93 | return bean; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/handler/ClientsBox.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.handler; 17 | 18 | import io.netty.channel.Channel; 19 | import io.netty.util.internal.PlatformDependent; 20 | 21 | import java.util.Map; 22 | import java.util.UUID; 23 | 24 | import com.corundumstudio.socketio.HandshakeData; 25 | 26 | public class ClientsBox { 27 | 28 | private final Map uuid2clients = PlatformDependent.newConcurrentHashMap(); 29 | private final Map channel2clients = PlatformDependent.newConcurrentHashMap(); 30 | 31 | // TODO use storeFactory 32 | public HandshakeData getHandshakeData(UUID sessionId) { 33 | ClientHead client = uuid2clients.get(sessionId); 34 | if (client == null) { 35 | return null; 36 | } 37 | 38 | return client.getHandshakeData(); 39 | } 40 | 41 | public void addClient(ClientHead clientHead) { 42 | uuid2clients.put(clientHead.getSessionId(), clientHead); 43 | } 44 | 45 | public ClientHead removeClient(UUID sessionId) { 46 | return uuid2clients.remove(sessionId); 47 | } 48 | 49 | public ClientHead get(UUID sessionId) { 50 | return uuid2clients.get(sessionId); 51 | } 52 | 53 | public void add(Channel channel, ClientHead clientHead) { 54 | channel2clients.put(channel, clientHead); 55 | } 56 | 57 | public void remove(Channel channel) { 58 | channel2clients.remove(channel); 59 | } 60 | 61 | 62 | public ClientHead get(Channel channel) { 63 | return channel2clients.get(channel); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/handler/PacketListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.handler; 17 | 18 | import java.util.Collections; 19 | import java.util.List; 20 | 21 | import com.corundumstudio.socketio.AckRequest; 22 | import com.corundumstudio.socketio.Transport; 23 | import com.corundumstudio.socketio.ack.AckManager; 24 | import com.corundumstudio.socketio.namespace.Namespace; 25 | import com.corundumstudio.socketio.namespace.NamespacesHub; 26 | import com.corundumstudio.socketio.protocol.EngineIOVersion; 27 | import com.corundumstudio.socketio.protocol.Packet; 28 | import com.corundumstudio.socketio.protocol.PacketType; 29 | import com.corundumstudio.socketio.scheduler.CancelableScheduler; 30 | import com.corundumstudio.socketio.scheduler.SchedulerKey; 31 | import com.corundumstudio.socketio.transport.NamespaceClient; 32 | import com.corundumstudio.socketio.transport.PollingTransport; 33 | 34 | public class PacketListener { 35 | 36 | private final NamespacesHub namespacesHub; 37 | private final AckManager ackManager; 38 | private final CancelableScheduler scheduler; 39 | 40 | public PacketListener(AckManager ackManager, NamespacesHub namespacesHub, PollingTransport xhrPollingTransport, 41 | CancelableScheduler scheduler) { 42 | this.ackManager = ackManager; 43 | this.namespacesHub = namespacesHub; 44 | this.scheduler = scheduler; 45 | } 46 | 47 | public void onPacket(Packet packet, NamespaceClient client, Transport transport) { 48 | final AckRequest ackRequest = new AckRequest(packet, client); 49 | 50 | if (packet.isAckRequested()) { 51 | ackManager.initAckIndex(client.getSessionId(), packet.getAckId()); 52 | } 53 | 54 | switch (packet.getType()) { 55 | case PING: { 56 | Packet outPacket = new Packet(PacketType.PONG, client.getEngineIOVersion()); 57 | outPacket.setData(packet.getData()); 58 | // TODO use future 59 | client.getBaseClient().send(outPacket, transport); 60 | if ("probe".equals(packet.getData())) { 61 | client.getBaseClient().send(new Packet(PacketType.NOOP, client.getEngineIOVersion()), Transport.POLLING); 62 | } else { 63 | client.getBaseClient().schedulePingTimeout(); 64 | } 65 | Namespace namespace = namespacesHub.get(packet.getNsp()); 66 | namespace.onPing(client); 67 | break; 68 | } 69 | case PONG: { 70 | client.getBaseClient().schedulePingTimeout(); 71 | Namespace namespace = namespacesHub.get(packet.getNsp()); 72 | namespace.onPong(client); 73 | break; 74 | } 75 | 76 | case UPGRADE: { 77 | client.getBaseClient().schedulePingTimeout(); 78 | 79 | SchedulerKey key = new SchedulerKey(SchedulerKey.Type.UPGRADE_TIMEOUT, client.getSessionId()); 80 | scheduler.cancel(key); 81 | 82 | client.getBaseClient().upgradeCurrentTransport(transport); 83 | break; 84 | } 85 | 86 | case MESSAGE: { 87 | client.getBaseClient().schedulePingTimeout(); 88 | 89 | if (packet.getSubType() == PacketType.DISCONNECT) { 90 | client.onDisconnect(); 91 | } 92 | 93 | if (packet.getSubType() == PacketType.CONNECT) { 94 | Namespace namespace = namespacesHub.get(packet.getNsp()); 95 | namespace.onConnect(client); 96 | // send connect handshake packet back to client 97 | if (!EngineIOVersion.V4.equals(client.getEngineIOVersion())) { 98 | client.getBaseClient().send(packet, transport); 99 | } 100 | } 101 | 102 | if (packet.getSubType() == PacketType.ACK 103 | || packet.getSubType() == PacketType.BINARY_ACK) { 104 | ackManager.onAck(client, packet); 105 | } 106 | 107 | if (packet.getSubType() == PacketType.EVENT 108 | || packet.getSubType() == PacketType.BINARY_EVENT) { 109 | Namespace namespace = namespacesHub.get(packet.getNsp()); 110 | List args = Collections.emptyList(); 111 | if (packet.getData() != null) { 112 | args = packet.getData(); 113 | } 114 | namespace.onEvent(client, packet.getName(), args, ackRequest); 115 | } 116 | break; 117 | } 118 | 119 | case CLOSE: 120 | client.getBaseClient().onChannelDisconnect(); 121 | break; 122 | 123 | default: 124 | break; 125 | } 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/handler/SocketIOException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.handler; 17 | 18 | public class SocketIOException extends RuntimeException { 19 | 20 | private static final long serialVersionUID = -9218908839842557188L; 21 | 22 | public SocketIOException(String message, Throwable cause) { 23 | super(message, cause); 24 | } 25 | 26 | public SocketIOException(String message) { 27 | super(message); 28 | } 29 | 30 | public SocketIOException(Throwable cause) { 31 | super(cause); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/handler/SuccessAuthorizationListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.handler; 17 | 18 | import com.corundumstudio.socketio.AuthorizationListener; 19 | import com.corundumstudio.socketio.AuthorizationResult; 20 | import com.corundumstudio.socketio.HandshakeData; 21 | 22 | public class SuccessAuthorizationListener implements AuthorizationListener { 23 | 24 | @Override 25 | public AuthorizationResult getAuthorizationResult(HandshakeData data) { 26 | return AuthorizationResult.SUCCESSFUL_AUTHORIZATION; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/handler/TransportState.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.handler; 17 | 18 | import java.util.Queue; 19 | import java.util.concurrent.ConcurrentLinkedQueue; 20 | 21 | import com.corundumstudio.socketio.protocol.Packet; 22 | 23 | import io.netty.channel.Channel; 24 | 25 | public class TransportState { 26 | 27 | private Queue packetsQueue = new ConcurrentLinkedQueue(); 28 | private Channel channel; 29 | 30 | public void setPacketsQueue(Queue packetsQueue) { 31 | this.packetsQueue = packetsQueue; 32 | } 33 | 34 | public Queue getPacketsQueue() { 35 | return packetsQueue; 36 | } 37 | 38 | public Channel getChannel() { 39 | return channel; 40 | } 41 | 42 | public Channel update(Channel channel) { 43 | Channel prevChannel = this.channel; 44 | this.channel = channel; 45 | return prevChannel; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/handler/WrongUrlHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.handler; 17 | 18 | import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; 19 | 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | 23 | import io.netty.channel.Channel; 24 | import io.netty.channel.ChannelFuture; 25 | import io.netty.channel.ChannelFutureListener; 26 | import io.netty.channel.ChannelHandler.Sharable; 27 | import io.netty.channel.ChannelHandlerContext; 28 | import io.netty.channel.ChannelInboundHandlerAdapter; 29 | import io.netty.handler.codec.http.DefaultHttpResponse; 30 | import io.netty.handler.codec.http.FullHttpRequest; 31 | import io.netty.handler.codec.http.HttpResponse; 32 | import io.netty.handler.codec.http.HttpResponseStatus; 33 | import io.netty.handler.codec.http.QueryStringDecoder; 34 | 35 | @Sharable 36 | public class WrongUrlHandler extends ChannelInboundHandlerAdapter { 37 | 38 | private static final Logger log = LoggerFactory.getLogger(WrongUrlHandler.class); 39 | 40 | @Override 41 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 42 | if (msg instanceof FullHttpRequest) { 43 | FullHttpRequest req = (FullHttpRequest) msg; 44 | Channel channel = ctx.channel(); 45 | QueryStringDecoder queryDecoder = new QueryStringDecoder(req.uri()); 46 | 47 | HttpResponse res = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.BAD_REQUEST); 48 | ChannelFuture f = channel.writeAndFlush(res); 49 | f.addListener(ChannelFutureListener.CLOSE); 50 | req.release(); 51 | log.warn("Blocked wrong socket.io-context request! url: {}, params: {}, ip: {}", queryDecoder.path(), queryDecoder.parameters(), channel.remoteAddress()); 52 | return; 53 | } 54 | super.channelRead(ctx, msg); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/listener/ClientListeners.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.listener; 17 | 18 | 19 | public interface ClientListeners { 20 | 21 | void addMultiTypeEventListener(String eventName, MultiTypeEventListener listener, Class ... eventClass); 22 | 23 | void addEventListener(String eventName, Class eventClass, DataListener listener); 24 | 25 | void addEventInterceptor(EventInterceptor eventInterceptor); 26 | 27 | void addDisconnectListener(DisconnectListener listener); 28 | 29 | void addConnectListener(ConnectListener listener); 30 | 31 | /** 32 | * from v4, ping will always be sent by server except probe ping packet sent from client, 33 | * and pong will always be responded by client while receiving ping except probe pong packet responded from server 34 | * it makes no more sense to listen to ping packet, instead you can listen to pong packet 35 | * @deprecated use addPongListener instead 36 | * @param listener 37 | */ 38 | @Deprecated 39 | void addPingListener(PingListener listener); 40 | void addPongListener(PongListener listener); 41 | 42 | void addListeners(Object listeners); 43 | 44 | void addListeners(Iterable listeners); 45 | 46 | void addListeners(Object listeners, Class listenersClass); 47 | 48 | void removeAllListeners(String eventName); 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/listener/ConnectListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.listener; 17 | 18 | import com.corundumstudio.socketio.SocketIOClient; 19 | 20 | public interface ConnectListener { 21 | 22 | void onConnect(SocketIOClient client); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/listener/DataListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.listener; 17 | 18 | import com.corundumstudio.socketio.AckRequest; 19 | import com.corundumstudio.socketio.SocketIOClient; 20 | 21 | public interface DataListener { 22 | 23 | /** 24 | * Invokes when data object received from client 25 | * 26 | * @param client - receiver 27 | * @param data - received object 28 | * @param ackSender - ack request 29 | * 30 | */ 31 | void onData(SocketIOClient client, T data, AckRequest ackSender) throws Exception; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/listener/DefaultExceptionListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.listener; 17 | 18 | import io.netty.channel.ChannelHandlerContext; 19 | 20 | import java.util.List; 21 | 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | import com.corundumstudio.socketio.SocketIOClient; 26 | 27 | public class DefaultExceptionListener extends ExceptionListenerAdapter { 28 | 29 | private static final Logger log = LoggerFactory.getLogger(DefaultExceptionListener.class); 30 | 31 | @Override 32 | public void onEventException(Exception e, List args, SocketIOClient client) { 33 | log.error(e.getMessage(), e); 34 | } 35 | 36 | @Override 37 | public void onDisconnectException(Exception e, SocketIOClient client) { 38 | log.error(e.getMessage(), e); 39 | } 40 | 41 | @Override 42 | public void onConnectException(Exception e, SocketIOClient client) { 43 | log.error(e.getMessage(), e); 44 | } 45 | 46 | @Override 47 | public void onPingException(Exception e, SocketIOClient client) { 48 | log.error(e.getMessage(), e); 49 | } 50 | 51 | @Override 52 | public void onPongException(Exception e, SocketIOClient client) { 53 | log.error(e.getMessage(), e); 54 | } 55 | 56 | @Override 57 | public boolean exceptionCaught(ChannelHandlerContext ctx, Throwable e) throws Exception { 58 | log.error(e.getMessage(), e); 59 | return true; 60 | } 61 | 62 | @Override 63 | public void onAuthException(Throwable e, SocketIOClient client) { 64 | log.error(e.getMessage(), e); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/listener/DisconnectListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.listener; 17 | 18 | import com.corundumstudio.socketio.SocketIOClient; 19 | 20 | public interface DisconnectListener { 21 | 22 | void onDisconnect(SocketIOClient client); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/listener/EventInterceptor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.listener; 17 | 18 | import com.corundumstudio.socketio.AckRequest; 19 | import com.corundumstudio.socketio.transport.NamespaceClient; 20 | import java.util.List; 21 | 22 | public interface EventInterceptor { 23 | void onEvent(NamespaceClient client, String eventName, List args, AckRequest ackRequest); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/listener/ExceptionListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.listener; 17 | 18 | import io.netty.channel.ChannelHandlerContext; 19 | 20 | import java.util.List; 21 | 22 | import com.corundumstudio.socketio.SocketIOClient; 23 | 24 | public interface ExceptionListener { 25 | 26 | void onEventException(Exception e, List args, SocketIOClient client); 27 | 28 | void onDisconnectException(Exception e, SocketIOClient client); 29 | 30 | void onConnectException(Exception e, SocketIOClient client); 31 | 32 | @Deprecated 33 | void onPingException(Exception e, SocketIOClient client); 34 | 35 | void onPongException(Exception e, SocketIOClient client); 36 | 37 | boolean exceptionCaught(ChannelHandlerContext ctx, Throwable e) throws Exception; 38 | 39 | void onAuthException(Throwable e, SocketIOClient client); 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/listener/ExceptionListenerAdapter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.listener; 17 | 18 | import io.netty.channel.ChannelHandlerContext; 19 | 20 | import java.util.List; 21 | 22 | import com.corundumstudio.socketio.SocketIOClient; 23 | 24 | /** 25 | * Base callback exceptions listener 26 | * 27 | * 28 | */ 29 | public abstract class ExceptionListenerAdapter implements ExceptionListener { 30 | 31 | @Override 32 | public void onEventException(Exception e, List data, SocketIOClient client) { 33 | } 34 | 35 | @Override 36 | public void onDisconnectException(Exception e, SocketIOClient client) { 37 | } 38 | 39 | @Override 40 | public void onConnectException(Exception e, SocketIOClient client) { 41 | } 42 | 43 | @Override 44 | public boolean exceptionCaught(ChannelHandlerContext ctx, Throwable e) throws Exception { 45 | return false; 46 | } 47 | 48 | @Override 49 | public void onPingException(Exception e, SocketIOClient client) { 50 | 51 | } 52 | 53 | @Override 54 | public void onPongException(Exception e, SocketIOClient client) { 55 | 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/listener/MultiTypeEventListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.listener; 17 | 18 | import com.corundumstudio.socketio.MultiTypeArgs; 19 | 20 | /** 21 | * Multi type args event listener 22 | * 23 | */ 24 | public interface MultiTypeEventListener extends DataListener { 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/listener/PingListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.listener; 17 | 18 | import com.corundumstudio.socketio.SocketIOClient; 19 | 20 | @Deprecated 21 | public interface PingListener { 22 | 23 | void onPing(SocketIOClient client); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/listener/PongListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.listener; 17 | 18 | import com.corundumstudio.socketio.SocketIOClient; 19 | 20 | public interface PongListener { 21 | 22 | void onPong(SocketIOClient client); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/messages/HttpErrorMessage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.messages; 17 | 18 | import java.util.Map; 19 | 20 | public class HttpErrorMessage extends HttpMessage { 21 | 22 | private final Map data; 23 | 24 | public HttpErrorMessage(Map data) { 25 | super(null, null); 26 | this.data = data; 27 | } 28 | 29 | public Map getData() { 30 | return data; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/messages/HttpMessage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.messages; 17 | 18 | import java.util.UUID; 19 | 20 | public abstract class HttpMessage { 21 | 22 | private final String origin; 23 | private final UUID sessionId; 24 | 25 | public HttpMessage(String origin, UUID sessionId) { 26 | this.origin = origin; 27 | this.sessionId = sessionId; 28 | } 29 | 30 | public String getOrigin() { 31 | return origin; 32 | } 33 | 34 | public UUID getSessionId() { 35 | return sessionId; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/messages/OutPacketMessage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.messages; 17 | 18 | import com.corundumstudio.socketio.Transport; 19 | import com.corundumstudio.socketio.handler.ClientHead; 20 | 21 | public class OutPacketMessage extends HttpMessage { 22 | 23 | private final ClientHead clientHead; 24 | private final Transport transport; 25 | 26 | public OutPacketMessage(ClientHead clientHead, Transport transport) { 27 | super(clientHead.getOrigin(), clientHead.getSessionId()); 28 | 29 | this.clientHead = clientHead; 30 | this.transport = transport; 31 | } 32 | 33 | public Transport getTransport() { 34 | return transport; 35 | } 36 | 37 | public ClientHead getClientHead() { 38 | return clientHead; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/messages/PacketsMessage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.messages; 17 | 18 | import io.netty.buffer.ByteBuf; 19 | 20 | import com.corundumstudio.socketio.Transport; 21 | import com.corundumstudio.socketio.handler.ClientHead; 22 | 23 | public class PacketsMessage { 24 | 25 | private final ClientHead client; 26 | private final ByteBuf content; 27 | private final Transport transport; 28 | 29 | public PacketsMessage(ClientHead client, ByteBuf content, Transport transport) { 30 | this.client = client; 31 | this.content = content; 32 | this.transport = transport; 33 | } 34 | 35 | public Transport getTransport() { 36 | return transport; 37 | } 38 | 39 | public ClientHead getClient() { 40 | return client; 41 | } 42 | 43 | public ByteBuf getContent() { 44 | return content; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/messages/XHROptionsMessage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.messages; 17 | 18 | import java.util.UUID; 19 | 20 | public class XHROptionsMessage extends XHRPostMessage { 21 | 22 | public XHROptionsMessage(String origin, UUID sessionId) { 23 | super(origin, sessionId); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/messages/XHRPostMessage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.messages; 17 | 18 | import java.util.UUID; 19 | 20 | public class XHRPostMessage extends HttpMessage { 21 | 22 | public XHRPostMessage(String origin, UUID sessionId) { 23 | super(origin, sessionId); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/misc/CompositeIterable.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.misc; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Iterator; 20 | import java.util.List; 21 | 22 | public class CompositeIterable implements Iterable { 23 | 24 | private List> iterablesList; 25 | private Iterable[] iterables; 26 | 27 | public CompositeIterable(List> iterables) { 28 | this.iterablesList = iterables; 29 | } 30 | 31 | public CompositeIterable(Iterable ... iterables) { 32 | this.iterables = iterables; 33 | } 34 | 35 | public CompositeIterable(CompositeIterable iterable) { 36 | this.iterables = iterable.iterables; 37 | this.iterablesList = iterable.iterablesList; 38 | } 39 | 40 | @Override 41 | public Iterator iterator() { 42 | List> iterators = new ArrayList>(); 43 | if (iterables != null) { 44 | for (Iterable iterable : iterables) { 45 | iterators.add(iterable.iterator()); 46 | } 47 | } else { 48 | for (Iterable iterable : iterablesList) { 49 | iterators.add(iterable.iterator()); 50 | } 51 | } 52 | return new CompositeIterator(iterators.iterator()); 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/misc/CompositeIterator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.misc; 17 | 18 | import java.util.Iterator; 19 | 20 | public class CompositeIterator implements Iterator { 21 | 22 | private final Iterator> listIterator; 23 | private Iterator currentIterator; 24 | 25 | public CompositeIterator(Iterator> listIterator) { 26 | this.currentIterator = null; 27 | this.listIterator = listIterator; 28 | } 29 | 30 | @Override 31 | public boolean hasNext() { 32 | if (currentIterator == null || !currentIterator.hasNext()) { 33 | while (listIterator.hasNext()) { 34 | Iterator iterator = listIterator.next(); 35 | if (iterator.hasNext()) { 36 | currentIterator = iterator; 37 | return true; 38 | } 39 | } 40 | return false; 41 | } 42 | return true; // can only be reached when currentIterator.hasNext() is true 43 | } 44 | 45 | @Override 46 | public T next() { 47 | hasNext(); 48 | return currentIterator.next(); 49 | } 50 | 51 | @Override 52 | public void remove() { 53 | currentIterator.remove(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/misc/IterableCollection.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.misc; 17 | 18 | import java.util.AbstractCollection; 19 | import java.util.Iterator; 20 | 21 | public class IterableCollection extends AbstractCollection { 22 | 23 | private final CompositeIterable iterable; 24 | 25 | public IterableCollection(Iterable iterable) { 26 | this(new CompositeIterable(iterable)); 27 | } 28 | 29 | public IterableCollection(CompositeIterable iterable) { 30 | this.iterable = iterable; 31 | } 32 | 33 | @Override 34 | public Iterator iterator() { 35 | return new CompositeIterable(iterable).iterator(); 36 | } 37 | 38 | @Override 39 | public int size() { 40 | Iterator iterator = new CompositeIterable(iterable).iterator(); 41 | int count = 0; 42 | while (iterator.hasNext()) { 43 | iterator.next(); 44 | count++; 45 | } 46 | return count; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/namespace/EventEntry.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.namespace; 17 | 18 | import java.util.Queue; 19 | import java.util.concurrent.ConcurrentLinkedQueue; 20 | 21 | import com.corundumstudio.socketio.listener.DataListener; 22 | 23 | public class EventEntry { 24 | 25 | private final Queue> listeners = new ConcurrentLinkedQueue>();; 26 | 27 | public EventEntry() { 28 | super(); 29 | } 30 | 31 | public void addListener(DataListener listener) { 32 | listeners.add(listener); 33 | } 34 | 35 | public Queue> getListeners() { 36 | return listeners; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/namespace/NamespacesHub.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.namespace; 17 | 18 | import io.netty.util.internal.PlatformDependent; 19 | 20 | import java.util.ArrayList; 21 | import java.util.Collection; 22 | import java.util.List; 23 | import java.util.concurrent.ConcurrentMap; 24 | 25 | import com.corundumstudio.socketio.Configuration; 26 | import com.corundumstudio.socketio.SocketIOClient; 27 | import com.corundumstudio.socketio.SocketIONamespace; 28 | import com.corundumstudio.socketio.misc.CompositeIterable; 29 | 30 | public class NamespacesHub { 31 | 32 | private final ConcurrentMap namespaces = PlatformDependent.newConcurrentHashMap(); 33 | private final Configuration configuration; 34 | 35 | public NamespacesHub(Configuration configuration) { 36 | this.configuration = configuration; 37 | } 38 | 39 | public Namespace create(String name) { 40 | Namespace namespace = (Namespace) namespaces.get(name); 41 | if (namespace == null) { 42 | namespace = new Namespace(name, configuration); 43 | Namespace oldNamespace = (Namespace) namespaces.putIfAbsent(name, namespace); 44 | if (oldNamespace != null) { 45 | namespace = oldNamespace; 46 | } 47 | } 48 | return namespace; 49 | } 50 | 51 | public Iterable getRoomClients(String room) { 52 | List> allClients = new ArrayList>(); 53 | for (SocketIONamespace namespace : namespaces.values()) { 54 | Iterable clients = ((Namespace)namespace).getRoomClients(room); 55 | allClients.add(clients); 56 | } 57 | return new CompositeIterable(allClients); 58 | } 59 | 60 | public Namespace get(String name) { 61 | return (Namespace) namespaces.get(name); 62 | } 63 | 64 | public void remove(String name) { 65 | SocketIONamespace namespace = namespaces.remove(name); 66 | if (namespace != null) { 67 | namespace.getBroadcastOperations().disconnect(); 68 | } 69 | } 70 | 71 | public Collection getAllNamespaces() { 72 | return namespaces.values(); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/protocol/AckArgs.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.protocol; 17 | 18 | import java.util.List; 19 | 20 | public class AckArgs { 21 | 22 | private List args; 23 | 24 | public AckArgs(List args) { 25 | super(); 26 | this.args = args; 27 | } 28 | 29 | public List getArgs() { 30 | return args; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/protocol/AuthPacket.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.protocol; 17 | 18 | import java.util.UUID; 19 | 20 | 21 | public class AuthPacket { 22 | 23 | private final UUID sid; 24 | private final String[] upgrades; 25 | private final int pingInterval; 26 | private final int pingTimeout; 27 | 28 | public AuthPacket(UUID sid, String[] upgrades, int pingInterval, int pingTimeout) { 29 | super(); 30 | this.sid = sid; 31 | this.upgrades = upgrades; 32 | this.pingInterval = pingInterval; 33 | this.pingTimeout = pingTimeout; 34 | } 35 | 36 | public int getPingInterval() { 37 | return pingInterval; 38 | } 39 | 40 | public int getPingTimeout() { 41 | return pingTimeout; 42 | } 43 | 44 | public UUID getSid() { 45 | return sid; 46 | } 47 | 48 | public String[] getUpgrades() { 49 | return upgrades; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/protocol/ConnPacket.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.protocol; 17 | 18 | import java.util.UUID; 19 | 20 | public class ConnPacket { 21 | 22 | private final UUID sid; 23 | 24 | public ConnPacket(UUID sid) { 25 | this.sid = sid; 26 | } 27 | 28 | public UUID getSid() { 29 | return sid; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/protocol/EngineIOVersion.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.protocol; 17 | 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | 21 | /** 22 | * Engine.IO protocol version 23 | */ 24 | public enum EngineIOVersion { 25 | /** 26 | * @link Engine.IO version 2 27 | */ 28 | V2("2"), 29 | /** 30 | * @link Engine.IO version 3 31 | */ 32 | V3("3"), 33 | /** 34 | * current version 35 | * @link Engine.IO version 4 36 | */ 37 | V4("4"), 38 | 39 | UNKNOWN(""), 40 | ; 41 | 42 | public static final String EIO = "EIO"; 43 | 44 | private static final Map VERSIONS = new HashMap<>(); 45 | 46 | static { 47 | for (EngineIOVersion value : values()) { 48 | VERSIONS.put(value.getValue(), value); 49 | } 50 | } 51 | 52 | private final String value; 53 | 54 | private EngineIOVersion(String value) { 55 | this.value = value; 56 | } 57 | 58 | public String getValue() { 59 | return value; 60 | } 61 | 62 | public static EngineIOVersion fromValue(String value) { 63 | EngineIOVersion engineIOVersion = VERSIONS.get(value); 64 | if (engineIOVersion != null) { 65 | return engineIOVersion; 66 | } 67 | return UNKNOWN; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/protocol/Event.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.protocol; 17 | 18 | import java.util.List; 19 | 20 | public class Event { 21 | 22 | private String name; 23 | private List args; 24 | 25 | public Event() { 26 | } 27 | 28 | public Event(String name, List args) { 29 | super(); 30 | this.name = name; 31 | this.args = args; 32 | } 33 | 34 | public List getArgs() { 35 | return args; 36 | } 37 | 38 | public String getName() { 39 | return name; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/protocol/JsonSupport.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.protocol; 17 | 18 | import io.netty.buffer.ByteBufInputStream; 19 | import io.netty.buffer.ByteBufOutputStream; 20 | 21 | import java.io.IOException; 22 | import java.util.List; 23 | 24 | import com.corundumstudio.socketio.AckCallback; 25 | 26 | /** 27 | * JSON infrastructure interface. 28 | * Allows to implement custom realizations 29 | * to JSON support operations. 30 | * 31 | */ 32 | public interface JsonSupport { 33 | 34 | AckArgs readAckArgs(ByteBufInputStream src, AckCallback callback) throws IOException; 35 | 36 | T readValue(String namespaceName, ByteBufInputStream src, Class valueType) throws IOException; 37 | 38 | void writeValue(ByteBufOutputStream out, Object value) throws IOException; 39 | 40 | void addEventMapping(String namespaceName, String eventName, Class ... eventClass); 41 | 42 | void removeEventMapping(String namespaceName, String eventName); 43 | 44 | List getArrays(); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/protocol/PacketType.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.protocol; 17 | 18 | 19 | public enum PacketType { 20 | 21 | OPEN(0), CLOSE(1), PING(2), PONG(3), MESSAGE(4), UPGRADE(5), NOOP(6), 22 | 23 | CONNECT(0, true), DISCONNECT(1, true), EVENT(2, true), ACK(3, true), ERROR(4, true), BINARY_EVENT(5, true), BINARY_ACK(6, true); 24 | 25 | public static final PacketType[] VALUES = values(); 26 | private final int value; 27 | private final boolean inner; 28 | 29 | PacketType(int value) { 30 | this(value, false); 31 | } 32 | 33 | PacketType(int value, boolean inner) { 34 | this.value = value; 35 | this.inner = inner; 36 | } 37 | 38 | public int getValue() { 39 | return value; 40 | } 41 | 42 | public static PacketType valueOf(int value) { 43 | for (PacketType type : VALUES) { 44 | if (type.getValue() == value && !type.inner) { 45 | return type; 46 | } 47 | } 48 | throw new IllegalStateException(); 49 | } 50 | 51 | public static PacketType valueOfInner(int value) { 52 | for (PacketType type : VALUES) { 53 | if (type.getValue() == value && type.inner) { 54 | return type; 55 | } 56 | } 57 | throw new IllegalArgumentException("Can't parse " + value); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/protocol/UTF8CharsScanner.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.protocol; 17 | 18 | import io.netty.buffer.ByteBuf; 19 | 20 | public class UTF8CharsScanner { 21 | 22 | /** 23 | * Lookup table used for determining which input characters need special 24 | * handling when contained in text segment. 25 | */ 26 | static final int[] sInputCodes; 27 | static { 28 | /* 29 | * 96 would do for most cases (backslash is ascii 94) but if we want to 30 | * do lookups by raw bytes it's better to have full table 31 | */ 32 | int[] table = new int[256]; 33 | // Control chars and non-space white space are not allowed unquoted 34 | for (int i = 0; i < 32; ++i) { 35 | table[i] = -1; 36 | } 37 | // And then string end and quote markers are special too 38 | table['"'] = 1; 39 | table['\\'] = 1; 40 | sInputCodes = table; 41 | } 42 | 43 | /** 44 | * Additionally we can combine UTF-8 decoding info into similar data table. 45 | */ 46 | static final int[] sInputCodesUtf8; 47 | static { 48 | int[] table = new int[sInputCodes.length]; 49 | System.arraycopy(sInputCodes, 0, table, 0, sInputCodes.length); 50 | for (int c = 128; c < 256; ++c) { 51 | int code; 52 | 53 | // We'll add number of bytes needed for decoding 54 | if ((c & 0xE0) == 0xC0) { // 2 bytes (0x0080 - 0x07FF) 55 | code = 2; 56 | } else if ((c & 0xF0) == 0xE0) { // 3 bytes (0x0800 - 0xFFFF) 57 | code = 3; 58 | } else if ((c & 0xF8) == 0xF0) { 59 | // 4 bytes; double-char with surrogates and all... 60 | code = 4; 61 | } else { 62 | // And -1 seems like a good "universal" error marker... 63 | code = -1; 64 | } 65 | table[c] = code; 66 | } 67 | sInputCodesUtf8 = table; 68 | } 69 | 70 | private int getCharTailIndex(ByteBuf inputBuffer, int i) { 71 | int c = (int) inputBuffer.getByte(i) & 0xFF; 72 | switch (sInputCodesUtf8[c]) { 73 | case 2: // 2-byte UTF 74 | i += 2; 75 | break; 76 | case 3: // 3-byte UTF 77 | i += 3; 78 | break; 79 | case 4: // 4-byte UTF 80 | i += 4; 81 | break; 82 | default: 83 | i++; 84 | break; 85 | } 86 | return i; 87 | } 88 | 89 | public int getActualLength(ByteBuf inputBuffer, int length) { 90 | int len = 0; 91 | int start = inputBuffer.readerIndex(); 92 | for (int i = inputBuffer.readerIndex(); i < inputBuffer.readableBytes() + inputBuffer.readerIndex();) { 93 | i = getCharTailIndex(inputBuffer, i); 94 | len++; 95 | if (length == len) { 96 | return i-start; 97 | } 98 | } 99 | throw new IllegalStateException(); 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/scheduler/CancelableScheduler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.scheduler; 17 | 18 | import io.netty.channel.ChannelHandlerContext; 19 | 20 | import java.util.concurrent.TimeUnit; 21 | 22 | public interface CancelableScheduler { 23 | 24 | void update(ChannelHandlerContext ctx); 25 | 26 | void cancel(SchedulerKey key); 27 | 28 | void scheduleCallback(SchedulerKey key, Runnable runnable, long delay, TimeUnit unit); 29 | 30 | void schedule(Runnable runnable, long delay, TimeUnit unit); 31 | 32 | void schedule(SchedulerKey key, Runnable runnable, long delay, TimeUnit unit); 33 | 34 | void shutdown(); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/scheduler/HashedWheelScheduler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.scheduler; 17 | 18 | import java.util.Map; 19 | import java.util.concurrent.ThreadFactory; 20 | import java.util.concurrent.TimeUnit; 21 | 22 | import io.netty.channel.ChannelHandlerContext; 23 | import io.netty.util.HashedWheelTimer; 24 | import io.netty.util.Timeout; 25 | import io.netty.util.TimerTask; 26 | import io.netty.util.internal.PlatformDependent; 27 | 28 | public class HashedWheelScheduler implements CancelableScheduler { 29 | 30 | private final Map scheduledFutures = PlatformDependent.newConcurrentHashMap(); 31 | private final HashedWheelTimer executorService; 32 | 33 | public HashedWheelScheduler() { 34 | executorService = new HashedWheelTimer(); 35 | } 36 | 37 | public HashedWheelScheduler(ThreadFactory threadFactory) { 38 | executorService = new HashedWheelTimer(threadFactory); 39 | } 40 | 41 | private volatile ChannelHandlerContext ctx; 42 | 43 | @Override 44 | public void update(ChannelHandlerContext ctx) { 45 | this.ctx = ctx; 46 | } 47 | 48 | @Override 49 | public void cancel(SchedulerKey key) { 50 | Timeout timeout = scheduledFutures.remove(key); 51 | if (timeout != null) { 52 | timeout.cancel(); 53 | } 54 | } 55 | 56 | @Override 57 | public void schedule(final Runnable runnable, long delay, TimeUnit unit) { 58 | executorService.newTimeout(new TimerTask() { 59 | @Override 60 | public void run(Timeout timeout) throws Exception { 61 | runnable.run(); 62 | } 63 | }, delay, unit); 64 | } 65 | 66 | @Override 67 | public void scheduleCallback(final SchedulerKey key, final Runnable runnable, long delay, TimeUnit unit) { 68 | Timeout timeout = executorService.newTimeout(new TimerTask() { 69 | @Override 70 | public void run(Timeout timeout) throws Exception { 71 | ctx.executor().execute(new Runnable() { 72 | @Override 73 | public void run() { 74 | try { 75 | runnable.run(); 76 | } finally { 77 | scheduledFutures.remove(key); 78 | } 79 | } 80 | }); 81 | } 82 | }, delay, unit); 83 | 84 | if (!timeout.isExpired()) { 85 | scheduledFutures.put(key, timeout); 86 | } 87 | } 88 | 89 | @Override 90 | public void schedule(final SchedulerKey key, final Runnable runnable, long delay, TimeUnit unit) { 91 | Timeout timeout = executorService.newTimeout(new TimerTask() { 92 | @Override 93 | public void run(Timeout timeout) throws Exception { 94 | try { 95 | runnable.run(); 96 | } finally { 97 | scheduledFutures.remove(key); 98 | } 99 | } 100 | }, delay, unit); 101 | 102 | if (!timeout.isExpired()) { 103 | scheduledFutures.put(key, timeout); 104 | } 105 | } 106 | 107 | @Override 108 | public void shutdown() { 109 | executorService.stop(); 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/scheduler/HashedWheelTimeoutScheduler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | /** 17 | * Modified version of HashedWheelScheduler specially for timeouts handling. 18 | * Difference: 19 | * - handling old timeout with same key after adding new one 20 | * fixes multithreaded problem that appears in highly concurrent non-atomic sequence cancel() -> schedule() 21 | * 22 | * (c) Alim Akbashev, 2015-02-11 23 | */ 24 | 25 | package com.corundumstudio.socketio.scheduler; 26 | 27 | import io.netty.channel.ChannelHandlerContext; 28 | import io.netty.util.HashedWheelTimer; 29 | import io.netty.util.Timeout; 30 | import io.netty.util.TimerTask; 31 | import io.netty.util.internal.PlatformDependent; 32 | 33 | import java.util.concurrent.ConcurrentMap; 34 | import java.util.concurrent.ThreadFactory; 35 | import java.util.concurrent.TimeUnit; 36 | 37 | public class HashedWheelTimeoutScheduler implements CancelableScheduler { 38 | 39 | private final ConcurrentMap scheduledFutures = PlatformDependent.newConcurrentHashMap(); 40 | private final HashedWheelTimer executorService; 41 | 42 | private volatile ChannelHandlerContext ctx; 43 | 44 | public HashedWheelTimeoutScheduler() { 45 | executorService = new HashedWheelTimer(); 46 | } 47 | 48 | public HashedWheelTimeoutScheduler(ThreadFactory threadFactory) { 49 | executorService = new HashedWheelTimer(threadFactory); 50 | } 51 | 52 | @Override 53 | public void update(ChannelHandlerContext ctx) { 54 | this.ctx = ctx; 55 | } 56 | 57 | @Override 58 | public void cancel(SchedulerKey key) { 59 | Timeout timeout = scheduledFutures.remove(key); 60 | if (timeout != null) { 61 | timeout.cancel(); 62 | } 63 | } 64 | 65 | @Override 66 | public void schedule(final Runnable runnable, long delay, TimeUnit unit) { 67 | executorService.newTimeout(new TimerTask() { 68 | @Override 69 | public void run(Timeout timeout) throws Exception { 70 | runnable.run(); 71 | } 72 | }, delay, unit); 73 | } 74 | 75 | @Override 76 | public void scheduleCallback(final SchedulerKey key, final Runnable runnable, long delay, TimeUnit unit) { 77 | Timeout timeout = executorService.newTimeout(new TimerTask() { 78 | @Override 79 | public void run(Timeout timeout) throws Exception { 80 | ctx.executor().execute(new Runnable() { 81 | @Override 82 | public void run() { 83 | scheduledFutures.remove(key); 84 | runnable.run(); 85 | } 86 | }); 87 | } 88 | }, delay, unit); 89 | 90 | replaceScheduledFuture(key, timeout); 91 | } 92 | 93 | @Override 94 | public void schedule(final SchedulerKey key, final Runnable runnable, long delay, TimeUnit unit) { 95 | Timeout timeout = executorService.newTimeout(new TimerTask() { 96 | @Override 97 | public void run(Timeout timeout) throws Exception { 98 | scheduledFutures.remove(key); 99 | runnable.run(); 100 | } 101 | }, delay, unit); 102 | 103 | replaceScheduledFuture(key, timeout); 104 | } 105 | 106 | @Override 107 | public void shutdown() { 108 | executorService.stop(); 109 | } 110 | 111 | private void replaceScheduledFuture(final SchedulerKey key, final Timeout newTimeout) { 112 | final Timeout oldTimeout; 113 | 114 | if (newTimeout.isExpired()) { 115 | // no need to put already expired timeout to scheduledFutures map. 116 | // simply remove old timeout 117 | oldTimeout = scheduledFutures.remove(key); 118 | } else { 119 | oldTimeout = scheduledFutures.put(key, newTimeout); 120 | } 121 | 122 | // if there was old timeout, cancel it 123 | if (oldTimeout != null) { 124 | oldTimeout.cancel(); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/scheduler/SchedulerKey.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.scheduler; 17 | 18 | 19 | public class SchedulerKey { 20 | 21 | public enum Type {PING, PING_TIMEOUT, ACK_TIMEOUT, UPGRADE_TIMEOUT}; 22 | 23 | private final Type type; 24 | private final Object sessionId; 25 | 26 | public SchedulerKey(Type type, Object sessionId) { 27 | this.type = type; 28 | this.sessionId = sessionId; 29 | } 30 | 31 | @Override 32 | public int hashCode() { 33 | final int prime = 31; 34 | int result = 1; 35 | result = prime * result 36 | + ((sessionId == null) ? 0 : sessionId.hashCode()); 37 | result = prime * result + ((type == null) ? 0 : type.hashCode()); 38 | return result; 39 | } 40 | 41 | @Override 42 | public boolean equals(Object obj) { 43 | if (this == obj) 44 | return true; 45 | if (obj == null) 46 | return false; 47 | if (getClass() != obj.getClass()) 48 | return false; 49 | SchedulerKey other = (SchedulerKey) obj; 50 | if (sessionId == null) { 51 | if (other.sessionId != null) 52 | return false; 53 | } else if (!sessionId.equals(other.sessionId)) 54 | return false; 55 | if (type != other.type) 56 | return false; 57 | return true; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/HazelcastPubSubStore.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store; 17 | 18 | import io.netty.util.internal.PlatformDependent; 19 | 20 | import java.util.Queue; 21 | import java.util.concurrent.ConcurrentLinkedQueue; 22 | import java.util.concurrent.ConcurrentMap; 23 | 24 | import com.corundumstudio.socketio.store.pubsub.PubSubListener; 25 | import com.corundumstudio.socketio.store.pubsub.PubSubMessage; 26 | import com.corundumstudio.socketio.store.pubsub.PubSubStore; 27 | import com.corundumstudio.socketio.store.pubsub.PubSubType; 28 | import com.hazelcast.core.HazelcastInstance; 29 | import com.hazelcast.core.ITopic; 30 | import com.hazelcast.core.Message; 31 | import com.hazelcast.core.MessageListener; 32 | 33 | 34 | public class HazelcastPubSubStore implements PubSubStore { 35 | 36 | private final HazelcastInstance hazelcastPub; 37 | private final HazelcastInstance hazelcastSub; 38 | private final Long nodeId; 39 | 40 | private final ConcurrentMap> map = PlatformDependent.newConcurrentHashMap(); 41 | 42 | public HazelcastPubSubStore(HazelcastInstance hazelcastPub, HazelcastInstance hazelcastSub, Long nodeId) { 43 | this.hazelcastPub = hazelcastPub; 44 | this.hazelcastSub = hazelcastSub; 45 | this.nodeId = nodeId; 46 | } 47 | 48 | @Override 49 | public void publish(PubSubType type, PubSubMessage msg) { 50 | msg.setNodeId(nodeId); 51 | hazelcastPub.getTopic(type.toString()).publish(msg); 52 | } 53 | 54 | @Override 55 | public void subscribe(PubSubType type, final PubSubListener listener, Class clazz) { 56 | String name = type.toString(); 57 | ITopic topic = hazelcastSub.getTopic(name); 58 | String regId = topic.addMessageListener(new MessageListener() { 59 | @Override 60 | public void onMessage(Message message) { 61 | PubSubMessage msg = message.getMessageObject(); 62 | if (!nodeId.equals(msg.getNodeId())) { 63 | listener.onMessage(message.getMessageObject()); 64 | } 65 | } 66 | }); 67 | 68 | Queue list = map.get(name); 69 | if (list == null) { 70 | list = new ConcurrentLinkedQueue(); 71 | Queue oldList = map.putIfAbsent(name, list); 72 | if (oldList != null) { 73 | list = oldList; 74 | } 75 | } 76 | list.add(regId); 77 | } 78 | 79 | @Override 80 | public void unsubscribe(PubSubType type) { 81 | String name = type.toString(); 82 | Queue regIds = map.remove(name); 83 | ITopic topic = hazelcastSub.getTopic(name); 84 | for (String id : regIds) { 85 | topic.removeMessageListener(id); 86 | } 87 | } 88 | 89 | @Override 90 | public void shutdown() { 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/HazelcastStore.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store; 17 | 18 | import java.util.UUID; 19 | 20 | import com.hazelcast.core.HazelcastInstance; 21 | import com.hazelcast.core.IMap; 22 | 23 | 24 | public class HazelcastStore implements Store { 25 | 26 | private final IMap map; 27 | 28 | public HazelcastStore(UUID sessionId, HazelcastInstance hazelcastInstance) { 29 | map = hazelcastInstance.getMap(sessionId.toString()); 30 | } 31 | 32 | @Override 33 | public void set(String key, Object val) { 34 | map.put(key, val); 35 | } 36 | 37 | @Override 38 | public T get(String key) { 39 | return (T) map.get(key); 40 | } 41 | 42 | @Override 43 | public boolean has(String key) { 44 | return map.containsKey(key); 45 | } 46 | 47 | @Override 48 | public void del(String key) { 49 | map.delete(key); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/HazelcastStoreFactory.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store; 17 | 18 | import java.util.Map; 19 | import java.util.UUID; 20 | 21 | import com.corundumstudio.socketio.store.pubsub.BaseStoreFactory; 22 | import com.corundumstudio.socketio.store.pubsub.PubSubStore; 23 | import com.hazelcast.client.HazelcastClient; 24 | import com.hazelcast.core.HazelcastInstance; 25 | 26 | /** 27 | * WARN: It's necessary to add netty-socketio.jar in hazelcast server classpath. 28 | * 29 | */ 30 | public class HazelcastStoreFactory extends BaseStoreFactory { 31 | 32 | private final HazelcastInstance hazelcastClient; 33 | private final HazelcastInstance hazelcastPub; 34 | private final HazelcastInstance hazelcastSub; 35 | 36 | private final PubSubStore pubSubStore; 37 | 38 | public HazelcastStoreFactory() { 39 | this(HazelcastClient.newHazelcastClient()); 40 | } 41 | 42 | public HazelcastStoreFactory(HazelcastInstance instance) { 43 | this.hazelcastClient = instance; 44 | this.hazelcastPub = instance; 45 | this.hazelcastSub = instance; 46 | 47 | this.pubSubStore = new HazelcastPubSubStore(hazelcastPub, hazelcastSub, getNodeId()); 48 | } 49 | 50 | public HazelcastStoreFactory(HazelcastInstance hazelcastClient, HazelcastInstance hazelcastPub, HazelcastInstance hazelcastSub) { 51 | this.hazelcastClient = hazelcastClient; 52 | this.hazelcastPub = hazelcastPub; 53 | this.hazelcastSub = hazelcastSub; 54 | 55 | this.pubSubStore = new HazelcastPubSubStore(hazelcastPub, hazelcastSub, getNodeId()); 56 | } 57 | 58 | @Override 59 | public Store createStore(UUID sessionId) { 60 | return new HazelcastStore(sessionId, hazelcastClient); 61 | } 62 | 63 | @Override 64 | public void shutdown() { 65 | hazelcastClient.shutdown(); 66 | hazelcastPub.shutdown(); 67 | hazelcastSub.shutdown(); 68 | } 69 | 70 | @Override 71 | public PubSubStore pubSubStore() { 72 | return pubSubStore; 73 | } 74 | 75 | @Override 76 | public Map createMap(String name) { 77 | return hazelcastClient.getMap(name); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/MemoryPubSubStore.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store; 17 | 18 | import com.corundumstudio.socketio.store.pubsub.PubSubListener; 19 | import com.corundumstudio.socketio.store.pubsub.PubSubMessage; 20 | import com.corundumstudio.socketio.store.pubsub.PubSubStore; 21 | import com.corundumstudio.socketio.store.pubsub.PubSubType; 22 | 23 | public class MemoryPubSubStore implements PubSubStore { 24 | 25 | @Override 26 | public void publish(PubSubType type, PubSubMessage msg) { 27 | } 28 | 29 | @Override 30 | public void subscribe(PubSubType type, PubSubListener listener, Class clazz) { 31 | } 32 | 33 | @Override 34 | public void unsubscribe(PubSubType type) { 35 | } 36 | 37 | @Override 38 | public void shutdown() { 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/MemoryStore.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store; 17 | 18 | import io.netty.util.internal.PlatformDependent; 19 | 20 | import java.util.Map; 21 | 22 | public class MemoryStore implements Store { 23 | 24 | private final Map store = PlatformDependent.newConcurrentHashMap(); 25 | 26 | @Override 27 | public void set(String key, Object value) { 28 | store.put(key, value); 29 | } 30 | 31 | @Override 32 | public T get(String key) { 33 | return (T) store.get(key); 34 | } 35 | 36 | @Override 37 | public boolean has(String key) { 38 | return store.containsKey(key); 39 | } 40 | 41 | @Override 42 | public void del(String key) { 43 | store.remove(key); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/MemoryStoreFactory.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store; 17 | 18 | import io.netty.util.internal.PlatformDependent; 19 | 20 | import java.util.Map; 21 | import java.util.UUID; 22 | 23 | import com.corundumstudio.socketio.store.pubsub.BaseStoreFactory; 24 | import com.corundumstudio.socketio.store.pubsub.PubSubStore; 25 | 26 | public class MemoryStoreFactory extends BaseStoreFactory { 27 | 28 | private final MemoryPubSubStore pubSubMemoryStore = new MemoryPubSubStore(); 29 | 30 | @Override 31 | public Store createStore(UUID sessionId) { 32 | return new MemoryStore(); 33 | } 34 | 35 | @Override 36 | public PubSubStore pubSubStore() { 37 | return pubSubMemoryStore; 38 | } 39 | 40 | @Override 41 | public void shutdown() { 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return getClass().getSimpleName() + " (local session store only)"; 47 | } 48 | 49 | @Override 50 | public Map createMap(String name) { 51 | return PlatformDependent.newConcurrentHashMap(); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/RedissonPubSubStore.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store; 17 | 18 | import java.util.Queue; 19 | import java.util.concurrent.ConcurrentLinkedQueue; 20 | import java.util.concurrent.ConcurrentMap; 21 | 22 | import org.redisson.api.RTopic; 23 | import org.redisson.api.RedissonClient; 24 | import org.redisson.api.listener.MessageListener; 25 | 26 | import com.corundumstudio.socketio.store.pubsub.PubSubListener; 27 | import com.corundumstudio.socketio.store.pubsub.PubSubMessage; 28 | import com.corundumstudio.socketio.store.pubsub.PubSubStore; 29 | import com.corundumstudio.socketio.store.pubsub.PubSubType; 30 | 31 | import io.netty.util.internal.PlatformDependent; 32 | 33 | public class RedissonPubSubStore implements PubSubStore { 34 | 35 | private final RedissonClient redissonPub; 36 | private final RedissonClient redissonSub; 37 | private final Long nodeId; 38 | 39 | private final ConcurrentMap> map = PlatformDependent.newConcurrentHashMap(); 40 | 41 | public RedissonPubSubStore(RedissonClient redissonPub, RedissonClient redissonSub, Long nodeId) { 42 | this.redissonPub = redissonPub; 43 | this.redissonSub = redissonSub; 44 | this.nodeId = nodeId; 45 | } 46 | 47 | @Override 48 | public void publish(PubSubType type, PubSubMessage msg) { 49 | msg.setNodeId(nodeId); 50 | redissonPub.getTopic(type.toString()).publish(msg); 51 | } 52 | 53 | @Override 54 | public void subscribe(PubSubType type, final PubSubListener listener, Class clazz) { 55 | String name = type.toString(); 56 | RTopic topic = redissonSub.getTopic(name); 57 | int regId = topic.addListener(PubSubMessage.class, new MessageListener() { 58 | @Override 59 | public void onMessage(CharSequence channel, PubSubMessage msg) { 60 | if (!nodeId.equals(msg.getNodeId())) { 61 | listener.onMessage((T)msg); 62 | } 63 | } 64 | }); 65 | 66 | Queue list = map.get(name); 67 | if (list == null) { 68 | list = new ConcurrentLinkedQueue(); 69 | Queue oldList = map.putIfAbsent(name, list); 70 | if (oldList != null) { 71 | list = oldList; 72 | } 73 | } 74 | list.add(regId); 75 | } 76 | 77 | @Override 78 | public void unsubscribe(PubSubType type) { 79 | String name = type.toString(); 80 | Queue regIds = map.remove(name); 81 | RTopic topic = redissonSub.getTopic(name); 82 | for (Integer id : regIds) { 83 | topic.removeListener(id); 84 | } 85 | } 86 | 87 | @Override 88 | public void shutdown() { 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/RedissonStore.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store; 17 | 18 | import java.util.Map; 19 | import java.util.UUID; 20 | 21 | import org.redisson.api.RedissonClient; 22 | 23 | public class RedissonStore implements Store { 24 | 25 | private final Map map; 26 | 27 | public RedissonStore(UUID sessionId, RedissonClient redisson) { 28 | this.map = redisson.getMap(sessionId.toString()); 29 | } 30 | 31 | @Override 32 | public void set(String key, Object value) { 33 | map.put(key, value); 34 | } 35 | 36 | @Override 37 | public T get(String key) { 38 | return (T) map.get(key); 39 | } 40 | 41 | @Override 42 | public boolean has(String key) { 43 | return map.containsKey(key); 44 | } 45 | 46 | @Override 47 | public void del(String key) { 48 | map.remove(key); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/RedissonStoreFactory.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store; 17 | 18 | import java.util.Map; 19 | import java.util.UUID; 20 | 21 | import org.redisson.Redisson; 22 | import org.redisson.api.RedissonClient; 23 | 24 | import com.corundumstudio.socketio.store.pubsub.BaseStoreFactory; 25 | import com.corundumstudio.socketio.store.pubsub.PubSubStore; 26 | 27 | public class RedissonStoreFactory extends BaseStoreFactory { 28 | 29 | private final RedissonClient redisClient; 30 | private final RedissonClient redisPub; 31 | private final RedissonClient redisSub; 32 | 33 | private final PubSubStore pubSubStore; 34 | 35 | public RedissonStoreFactory() { 36 | this(Redisson.create()); 37 | } 38 | 39 | public RedissonStoreFactory(RedissonClient redisson) { 40 | this.redisClient = redisson; 41 | this.redisPub = redisson; 42 | this.redisSub = redisson; 43 | 44 | this.pubSubStore = new RedissonPubSubStore(redisPub, redisSub, getNodeId()); 45 | } 46 | 47 | public RedissonStoreFactory(Redisson redisClient, Redisson redisPub, Redisson redisSub) { 48 | this.redisClient = redisClient; 49 | this.redisPub = redisPub; 50 | this.redisSub = redisSub; 51 | 52 | this.pubSubStore = new RedissonPubSubStore(redisPub, redisSub, getNodeId()); 53 | } 54 | 55 | @Override 56 | public Store createStore(UUID sessionId) { 57 | return new RedissonStore(sessionId, redisClient); 58 | } 59 | 60 | @Override 61 | public PubSubStore pubSubStore() { 62 | return pubSubStore; 63 | } 64 | 65 | @Override 66 | public void shutdown() { 67 | redisClient.shutdown(); 68 | redisPub.shutdown(); 69 | redisSub.shutdown(); 70 | } 71 | 72 | @Override 73 | public Map createMap(String name) { 74 | return redisClient.getMap(name); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/Store.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store; 17 | 18 | 19 | public interface Store { 20 | 21 | void set(String key, Object val); 22 | 23 | T get(String key); 24 | 25 | boolean has(String key); 26 | 27 | void del(String key); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/StoreFactory.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store; 17 | 18 | import java.util.Map; 19 | import java.util.UUID; 20 | 21 | import com.corundumstudio.socketio.Disconnectable; 22 | import com.corundumstudio.socketio.handler.AuthorizeHandler; 23 | import com.corundumstudio.socketio.namespace.NamespacesHub; 24 | import com.corundumstudio.socketio.protocol.JsonSupport; 25 | import com.corundumstudio.socketio.store.pubsub.PubSubStore; 26 | 27 | /** 28 | * 29 | * Creates a client Store and PubSubStore 30 | * 31 | */ 32 | public interface StoreFactory extends Disconnectable { 33 | 34 | PubSubStore pubSubStore(); 35 | 36 | Map createMap(String name); 37 | 38 | Store createStore(UUID sessionId); 39 | 40 | void init(NamespacesHub namespacesHub, AuthorizeHandler authorizeHandler, JsonSupport jsonSupport); 41 | 42 | void shutdown(); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/pubsub/BulkJoinLeaveMessage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store.pubsub; 17 | 18 | import java.util.Set; 19 | import java.util.UUID; 20 | 21 | public class BulkJoinLeaveMessage extends PubSubMessage { 22 | 23 | private static final long serialVersionUID = 7506016762607624388L; 24 | 25 | private UUID sessionId; 26 | private String namespace; 27 | private Set rooms; 28 | 29 | public BulkJoinLeaveMessage() { 30 | } 31 | 32 | public BulkJoinLeaveMessage(UUID id, Set rooms, String namespace) { 33 | super(); 34 | this.sessionId = id; 35 | this.rooms = rooms; 36 | this.namespace = namespace; 37 | } 38 | 39 | public String getNamespace() { 40 | return namespace; 41 | } 42 | 43 | public UUID getSessionId() { 44 | return sessionId; 45 | } 46 | 47 | public Set getRooms() { 48 | return rooms; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/pubsub/ConnectMessage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store.pubsub; 17 | 18 | import java.util.UUID; 19 | 20 | public class ConnectMessage extends PubSubMessage { 21 | 22 | private static final long serialVersionUID = 3108918714495865101L; 23 | 24 | private UUID sessionId; 25 | 26 | public ConnectMessage() { 27 | } 28 | 29 | public ConnectMessage(UUID sessionId) { 30 | super(); 31 | this.sessionId = sessionId; 32 | } 33 | 34 | public UUID getSessionId() { 35 | return sessionId; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/pubsub/DisconnectMessage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store.pubsub; 17 | 18 | import java.util.UUID; 19 | 20 | public class DisconnectMessage extends PubSubMessage { 21 | 22 | private static final long serialVersionUID = -2763553673397520368L; 23 | 24 | private UUID sessionId; 25 | 26 | public DisconnectMessage() { 27 | } 28 | 29 | public DisconnectMessage(UUID sessionId) { 30 | super(); 31 | this.sessionId = sessionId; 32 | } 33 | 34 | public UUID getSessionId() { 35 | return sessionId; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/pubsub/DispatchMessage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store.pubsub; 17 | 18 | import com.corundumstudio.socketio.protocol.Packet; 19 | 20 | public class DispatchMessage extends PubSubMessage { 21 | 22 | private static final long serialVersionUID = 6692047718303934349L; 23 | 24 | private String room; 25 | private String namespace; 26 | private Packet packet; 27 | 28 | public DispatchMessage() { 29 | } 30 | 31 | public DispatchMessage(String room, Packet packet, String namespace) { 32 | this.room = room; 33 | this.packet = packet; 34 | this.namespace = namespace; 35 | } 36 | 37 | public String getNamespace() { 38 | return namespace; 39 | } 40 | 41 | public Packet getPacket() { 42 | return packet; 43 | } 44 | 45 | public String getRoom() { 46 | return room; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/pubsub/JoinLeaveMessage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store.pubsub; 17 | 18 | import java.util.UUID; 19 | 20 | public class JoinLeaveMessage extends PubSubMessage { 21 | 22 | private static final long serialVersionUID = -944515928988033174L; 23 | 24 | private UUID sessionId; 25 | private String namespace; 26 | private String room; 27 | 28 | public JoinLeaveMessage() { 29 | } 30 | 31 | public JoinLeaveMessage(UUID id, String room, String namespace) { 32 | super(); 33 | this.sessionId = id; 34 | this.room = room; 35 | this.namespace = namespace; 36 | } 37 | 38 | public String getNamespace() { 39 | return namespace; 40 | } 41 | 42 | public UUID getSessionId() { 43 | return sessionId; 44 | } 45 | 46 | public String getRoom() { 47 | return room; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/pubsub/PubSubListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store.pubsub; 17 | 18 | 19 | public interface PubSubListener { 20 | 21 | void onMessage(T data); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/pubsub/PubSubMessage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store.pubsub; 17 | 18 | import java.io.Serializable; 19 | 20 | public abstract class PubSubMessage implements Serializable { 21 | 22 | private static final long serialVersionUID = -8789343104393884987L; 23 | 24 | private Long nodeId; 25 | 26 | public Long getNodeId() { 27 | return nodeId; 28 | } 29 | 30 | public void setNodeId(Long nodeId) { 31 | this.nodeId = nodeId; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/pubsub/PubSubStore.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store.pubsub; 17 | 18 | 19 | public interface PubSubStore { 20 | 21 | void publish(PubSubType type, PubSubMessage msg); 22 | 23 | void subscribe(PubSubType type, PubSubListener listener, Class clazz); 24 | 25 | void unsubscribe(PubSubType type); 26 | 27 | void shutdown(); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/corundumstudio/socketio/store/pubsub/PubSubType.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.store.pubsub; 17 | 18 | public enum PubSubType { 19 | 20 | CONNECT, DISCONNECT, JOIN, BULK_JOIN, LEAVE, BULK_LEAVE, DISPATCH; 21 | 22 | @Override 23 | public String toString() { 24 | return name().toLowerCase(); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module netty.socketio { 2 | exports com.corundumstudio.socketio; 3 | exports com.corundumstudio.socketio.ack; 4 | exports com.corundumstudio.socketio.annotation; 5 | exports com.corundumstudio.socketio.handler; 6 | exports com.corundumstudio.socketio.listener; 7 | exports com.corundumstudio.socketio.namespace; 8 | exports com.corundumstudio.socketio.misc; 9 | exports com.corundumstudio.socketio.messages; 10 | exports com.corundumstudio.socketio.protocol; 11 | 12 | requires static spring.beans; 13 | requires static spring.core; 14 | 15 | requires com.fasterxml.jackson.core; 16 | requires com.fasterxml.jackson.annotation; 17 | requires com.fasterxml.jackson.databind; 18 | 19 | requires static com.hazelcast.core; 20 | requires static com.hazelcast.client; 21 | 22 | requires static redisson; 23 | 24 | requires static io.netty.transport.classes.epoll; 25 | requires io.netty.codec; 26 | requires io.netty.transport; 27 | requires io.netty.buffer; 28 | requires io.netty.common; 29 | requires io.netty.handler; 30 | requires io.netty.codec.http; 31 | requires org.slf4j; 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/com/corundumstudio/socketio/JoinIteratorsTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Arrays; 20 | import java.util.List; 21 | 22 | import org.junit.Assert; 23 | import org.junit.Test; 24 | 25 | import com.corundumstudio.socketio.misc.CompositeIterable; 26 | 27 | public class JoinIteratorsTest { 28 | 29 | @Test 30 | public void testIterator() { 31 | List list1 = Arrays.asList(1, 2); 32 | List list2 = Arrays.asList(3, 4); 33 | CompositeIterable iterators = new CompositeIterable(list1, list2); 34 | 35 | // for nomemory test 36 | for (Integer integer : iterators) { 37 | } 38 | 39 | List mainList = new ArrayList(); 40 | for (Integer integer : iterators) { 41 | mainList.add(integer); 42 | } 43 | Assert.assertEquals(list1.size() + list2.size(), mainList.size()); 44 | mainList.removeAll(list1); 45 | mainList.removeAll(list2); 46 | Assert.assertTrue(mainList.isEmpty()); 47 | 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/com/corundumstudio/socketio/parser/DecoderAckPacketTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.parser; 17 | 18 | import java.io.IOException; 19 | import java.nio.charset.Charset; 20 | import java.util.UUID; 21 | 22 | import io.netty.buffer.Unpooled; 23 | import io.netty.util.CharsetUtil; 24 | import mockit.Expectations; 25 | 26 | import org.junit.Assert; 27 | import org.junit.Ignore; 28 | import org.junit.Test; 29 | 30 | import com.corundumstudio.socketio.AckCallback; 31 | import com.corundumstudio.socketio.protocol.Packet; 32 | import com.corundumstudio.socketio.protocol.PacketType; 33 | import com.fasterxml.jackson.core.JsonParseException; 34 | 35 | @Ignore 36 | public class DecoderAckPacketTest extends DecoderBaseTest { 37 | 38 | @Test 39 | public void testDecode() throws IOException { 40 | Packet packet = decoder.decodePackets(Unpooled.copiedBuffer("6:::140", CharsetUtil.UTF_8), null); 41 | Assert.assertEquals(PacketType.ACK, packet.getType()); 42 | Assert.assertEquals(140, (long)packet.getAckId()); 43 | // Assert.assertTrue(packet.getArgs().isEmpty()); 44 | } 45 | 46 | @Test 47 | public void testDecodeWithArgs() throws IOException { 48 | initExpectations(); 49 | 50 | Packet packet = decoder.decodePackets(Unpooled.copiedBuffer("6:::12+[\"woot\",\"wa\"]", CharsetUtil.UTF_8), null); 51 | Assert.assertEquals(PacketType.ACK, packet.getType()); 52 | Assert.assertEquals(12, (long)packet.getAckId()); 53 | // Assert.assertEquals(Arrays.asList("woot", "wa"), packet.getArgs()); 54 | } 55 | 56 | private void initExpectations() { 57 | new Expectations() {{ 58 | ackManager.getCallback((UUID)any, anyInt); 59 | result = new AckCallback(String.class) { 60 | @Override 61 | public void onSuccess(String result) { 62 | } 63 | }; 64 | }}; 65 | } 66 | 67 | @Test(expected = JsonParseException.class) 68 | public void testDecodeWithBadJson() throws IOException { 69 | initExpectations(); 70 | decoder.decodePackets(Unpooled.copiedBuffer("6:::1+{\"++]", CharsetUtil.UTF_8), null); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/test/java/com/corundumstudio/socketio/parser/DecoderBaseTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.parser; 17 | 18 | import mockit.Mocked; 19 | 20 | import org.junit.Before; 21 | 22 | import com.corundumstudio.socketio.ack.AckManager; 23 | import com.corundumstudio.socketio.protocol.JacksonJsonSupport; 24 | import com.corundumstudio.socketio.protocol.PacketDecoder; 25 | 26 | 27 | public class DecoderBaseTest { 28 | 29 | @Mocked 30 | protected AckManager ackManager; 31 | 32 | protected PacketDecoder decoder; 33 | 34 | @Before 35 | public void before() { 36 | decoder = new PacketDecoder(new JacksonJsonSupport(), ackManager); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/com/corundumstudio/socketio/parser/DecoderConnectionPacketTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.parser; 17 | 18 | import java.io.IOException; 19 | 20 | import io.netty.buffer.Unpooled; 21 | import io.netty.util.CharsetUtil; 22 | import org.junit.Assert; 23 | import org.junit.Ignore; 24 | import org.junit.Test; 25 | 26 | import com.corundumstudio.socketio.protocol.Packet; 27 | import com.corundumstudio.socketio.protocol.PacketType; 28 | 29 | @Ignore 30 | public class DecoderConnectionPacketTest extends DecoderBaseTest { 31 | 32 | @Test 33 | public void testDecodeHeartbeat() throws IOException { 34 | Packet packet = decoder.decodePackets(Unpooled.copiedBuffer("2:::", CharsetUtil.UTF_8), null); 35 | // Assert.assertEquals(PacketType.HEARTBEAT, packet.getType()); 36 | } 37 | 38 | @Test 39 | public void testDecode() throws IOException { 40 | Packet packet = decoder.decodePackets(Unpooled.copiedBuffer("1::/tobi", CharsetUtil.UTF_8), null); 41 | Assert.assertEquals(PacketType.CONNECT, packet.getType()); 42 | Assert.assertEquals("/tobi", packet.getNsp()); 43 | } 44 | 45 | @Test 46 | public void testDecodeWithQueryString() throws IOException { 47 | Packet packet = decoder.decodePackets(Unpooled.copiedBuffer("1::/test:?test=1", CharsetUtil.UTF_8), null); 48 | Assert.assertEquals(PacketType.CONNECT, packet.getType()); 49 | Assert.assertEquals("/test", packet.getNsp()); 50 | // Assert.assertEquals("?test=1", packet.getQs()); 51 | } 52 | 53 | @Test 54 | public void testDecodeDisconnection() throws IOException { 55 | Packet packet = decoder.decodePackets(Unpooled.copiedBuffer("0::/woot", CharsetUtil.UTF_8), null); 56 | Assert.assertEquals(PacketType.DISCONNECT, packet.getType()); 57 | Assert.assertEquals("/woot", packet.getNsp()); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/com/corundumstudio/socketio/parser/DecoderEventPacketTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.parser; 17 | 18 | import java.io.IOException; 19 | import java.util.HashMap; 20 | 21 | import io.netty.buffer.Unpooled; 22 | import io.netty.util.CharsetUtil; 23 | import org.junit.Assert; 24 | import org.junit.Ignore; 25 | import org.junit.Test; 26 | 27 | import com.corundumstudio.socketio.protocol.JacksonJsonSupport; 28 | import com.corundumstudio.socketio.protocol.Packet; 29 | import com.corundumstudio.socketio.protocol.PacketDecoder; 30 | import com.corundumstudio.socketio.protocol.PacketType; 31 | 32 | @Ignore 33 | public class DecoderEventPacketTest extends DecoderBaseTest { 34 | 35 | @Test 36 | public void testDecode() throws IOException { 37 | Packet packet = decoder.decodePackets(Unpooled.copiedBuffer("5:::{\"name\":\"woot\"}", CharsetUtil.UTF_8), null); 38 | Assert.assertEquals(PacketType.EVENT, packet.getType()); 39 | Assert.assertEquals("woot", packet.getName()); 40 | } 41 | 42 | @Test 43 | public void testDecodeWithMessageIdAndAck() throws IOException { 44 | Packet packet = decoder.decodePackets(Unpooled.copiedBuffer("5:1+::{\"name\":\"tobi\"}", CharsetUtil.UTF_8), null); 45 | Assert.assertEquals(PacketType.EVENT, packet.getType()); 46 | // Assert.assertEquals(1, (long)packet.getId()); 47 | // Assert.assertEquals(Packet.ACK_DATA, packet.getAck()); 48 | Assert.assertEquals("tobi", packet.getName()); 49 | } 50 | 51 | @Test 52 | public void testDecodeWithData() throws IOException { 53 | JacksonJsonSupport jsonSupport = new JacksonJsonSupport(); 54 | jsonSupport.addEventMapping("", "edwald", HashMap.class, Integer.class, String.class); 55 | PacketDecoder decoder = new PacketDecoder(jsonSupport, ackManager); 56 | 57 | Packet packet = decoder.decodePackets(Unpooled.copiedBuffer("5:::{\"name\":\"edwald\",\"args\":[{\"a\": \"b\"},2,\"3\"]}", CharsetUtil.UTF_8), null); 58 | Assert.assertEquals(PacketType.EVENT, packet.getType()); 59 | Assert.assertEquals("edwald", packet.getName()); 60 | // Assert.assertEquals(3, packet.getArgs().size()); 61 | // Map obj = (Map) packet.getArgs().get(0); 62 | // Assert.assertEquals("b", obj.get("a")); 63 | // Assert.assertEquals(2, packet.getArgs().get(1)); 64 | // Assert.assertEquals("3", packet.getArgs().get(2)); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/test/java/com/corundumstudio/socketio/parser/DecoderJsonPacketTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.parser; 17 | 18 | import java.io.IOException; 19 | import java.util.Map; 20 | 21 | import io.netty.buffer.Unpooled; 22 | import io.netty.util.CharsetUtil; 23 | import org.junit.Assert; 24 | import org.junit.Ignore; 25 | import org.junit.Test; 26 | 27 | import com.corundumstudio.socketio.protocol.Packet; 28 | 29 | @Ignore 30 | public class DecoderJsonPacketTest extends DecoderBaseTest { 31 | 32 | @Test 33 | public void testUTF8Decode() throws IOException { 34 | Packet packet = decoder.decodePackets(Unpooled.copiedBuffer("4:::\"Привет\"", CharsetUtil.UTF_8), null); 35 | // Assert.assertEquals(PacketType.JSON, packet.getType()); 36 | Assert.assertEquals("Привет", packet.getData()); 37 | } 38 | 39 | @Test 40 | public void testDecode() throws IOException { 41 | Packet packet = decoder.decodePackets(Unpooled.copiedBuffer("4:::\"2\"", CharsetUtil.UTF_8), null); 42 | // Assert.assertEquals(PacketType.JSON, packet.getType()); 43 | Assert.assertEquals("2", packet.getData()); 44 | } 45 | 46 | @Test 47 | public void testDecodeWithMessageIdAndAckData() throws IOException { 48 | Packet packet = decoder.decodePackets(Unpooled.copiedBuffer("4:1+::{\"a\":\"b\"}", CharsetUtil.UTF_8), null); 49 | // Assert.assertEquals(PacketType.JSON, packet.getType()); 50 | // Assert.assertEquals(1, (long)packet.getId()); 51 | // Assert.assertEquals(Packet.ACK_DATA, packet.getAck()); 52 | 53 | Map obj = (Map) packet.getData(); 54 | Assert.assertEquals("b", obj.get("a")); 55 | Assert.assertEquals(1, obj.size()); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/com/corundumstudio/socketio/parser/DecoderMessagePacketTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.parser; 17 | 18 | import java.io.IOException; 19 | 20 | import io.netty.buffer.Unpooled; 21 | import io.netty.util.CharsetUtil; 22 | import org.junit.Assert; 23 | import org.junit.Ignore; 24 | import org.junit.Test; 25 | 26 | import com.corundumstudio.socketio.protocol.Packet; 27 | import com.corundumstudio.socketio.protocol.PacketType; 28 | 29 | @Ignore 30 | public class DecoderMessagePacketTest extends DecoderBaseTest { 31 | 32 | @Test 33 | public void testDecodeId() throws IOException { 34 | Packet packet = decoder.decodePackets(Unpooled.copiedBuffer("3:1::asdfasdf", CharsetUtil.UTF_8), null); 35 | Assert.assertEquals(PacketType.MESSAGE, packet.getType()); 36 | // Assert.assertEquals(1, (long)packet.getId()); 37 | // Assert.assertTrue(packet.getArgs().isEmpty()); 38 | // Assert.assertTrue(packet.getAck().equals(Boolean.TRUE)); 39 | } 40 | 41 | @Test 42 | public void testDecode() throws IOException { 43 | Packet packet = decoder.decodePackets(Unpooled.copiedBuffer("3:::woot", CharsetUtil.UTF_8), null); 44 | Assert.assertEquals(PacketType.MESSAGE, packet.getType()); 45 | Assert.assertEquals("woot", packet.getData()); 46 | } 47 | 48 | @Test 49 | public void testDecodeWithIdAndEndpoint() throws IOException { 50 | Packet packet = decoder.decodePackets(Unpooled.copiedBuffer("3:5:/tobi", CharsetUtil.UTF_8), null); 51 | Assert.assertEquals(PacketType.MESSAGE, packet.getType()); 52 | // Assert.assertEquals(5, (long)packet.getId()); 53 | // Assert.assertEquals(true, packet.getAck()); 54 | Assert.assertEquals("/tobi", packet.getNsp()); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/com/corundumstudio/socketio/parser/EncoderAckPacketTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.parser; 17 | 18 | import io.netty.buffer.ByteBuf; 19 | import io.netty.buffer.Unpooled; 20 | import io.netty.util.CharsetUtil; 21 | 22 | import java.io.IOException; 23 | 24 | import org.junit.Assert; 25 | import org.junit.Test; 26 | 27 | import com.corundumstudio.socketio.protocol.Packet; 28 | import com.corundumstudio.socketio.protocol.PacketType; 29 | 30 | public class EncoderAckPacketTest extends EncoderBaseTest { 31 | 32 | @Test 33 | public void testEncode() throws IOException { 34 | Packet packet = new Packet(PacketType.ACK); 35 | packet.setAckId(140L); 36 | ByteBuf result = Unpooled.buffer(); 37 | // encoder.encodePacket(packet, result); 38 | Assert.assertEquals("6:::140", result.toString(CharsetUtil.UTF_8)); 39 | } 40 | 41 | @Test 42 | public void testEncodeWithArgs() throws IOException { 43 | Packet packet = new Packet(PacketType.ACK); 44 | packet.setAckId(12L); 45 | // packet.setArgs(Arrays.asList("woot", "wa")); 46 | ByteBuf result = Unpooled.buffer(); 47 | // encoder.encodePacket(packet, result); 48 | Assert.assertEquals("6:::12+[\"woot\",\"wa\"]", result.toString(CharsetUtil.UTF_8)); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/com/corundumstudio/socketio/parser/EncoderBaseTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.parser; 17 | 18 | import com.corundumstudio.socketio.Configuration; 19 | import com.corundumstudio.socketio.protocol.PacketEncoder; 20 | import com.corundumstudio.socketio.protocol.JacksonJsonSupport; 21 | 22 | public class EncoderBaseTest { 23 | 24 | final PacketEncoder encoder = new PacketEncoder(new Configuration(), new JacksonJsonSupport()); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/com/corundumstudio/socketio/parser/EncoderConnectionPacketTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.parser; 17 | 18 | import io.netty.buffer.ByteBuf; 19 | import io.netty.buffer.Unpooled; 20 | import io.netty.util.CharsetUtil; 21 | 22 | import java.io.IOException; 23 | 24 | import org.junit.Assert; 25 | import org.junit.Test; 26 | 27 | import com.corundumstudio.socketio.protocol.Packet; 28 | import com.corundumstudio.socketio.protocol.PacketType; 29 | 30 | public class EncoderConnectionPacketTest extends EncoderBaseTest { 31 | 32 | @Test 33 | public void testEncodeHeartbeat() throws IOException { 34 | // Packet packet = new Packet(PacketType.HEARTBEAT); 35 | // ByteBuf result = Unpooled.buffer(); 36 | // encoder.encodePacket(packet, result); 37 | // Assert.assertEquals("2::", result.toString(CharsetUtil.UTF_8)); 38 | } 39 | 40 | @Test 41 | public void testEncodeDisconnection() throws IOException { 42 | Packet packet = new Packet(PacketType.DISCONNECT); 43 | packet.setNsp("/woot"); 44 | ByteBuf result = Unpooled.buffer(); 45 | // encoder.encodePacket(packet, result); 46 | Assert.assertEquals("0::/woot", result.toString(CharsetUtil.UTF_8)); 47 | } 48 | 49 | @Test 50 | public void testEncode() throws IOException { 51 | Packet packet = new Packet(PacketType.CONNECT); 52 | packet.setNsp("/tobi"); 53 | ByteBuf result = Unpooled.buffer(); 54 | // encoder.encodePacket(packet, result); 55 | Assert.assertEquals("1::/tobi", result.toString(CharsetUtil.UTF_8)); 56 | } 57 | 58 | @Test 59 | public void testEncodePacketWithQueryString() throws IOException { 60 | Packet packet = new Packet(PacketType.CONNECT); 61 | packet.setNsp("/test"); 62 | // packet.setQs("?test=1"); 63 | ByteBuf result = Unpooled.buffer(); 64 | // encoder.encodePacket(packet, result); 65 | Assert.assertEquals("1::/test:?test=1", result.toString(CharsetUtil.UTF_8)); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/test/java/com/corundumstudio/socketio/parser/EncoderEventPacketTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.parser; 17 | 18 | import io.netty.buffer.ByteBuf; 19 | import io.netty.buffer.Unpooled; 20 | import io.netty.util.CharsetUtil; 21 | 22 | import java.io.IOException; 23 | 24 | import org.junit.Assert; 25 | import org.junit.Test; 26 | 27 | import com.corundumstudio.socketio.protocol.Packet; 28 | import com.corundumstudio.socketio.protocol.PacketType; 29 | 30 | public class EncoderEventPacketTest extends EncoderBaseTest { 31 | 32 | @Test 33 | public void testEncode() throws IOException { 34 | Packet packet = new Packet(PacketType.EVENT); 35 | packet.setName("woot"); 36 | ByteBuf result = Unpooled.buffer(); 37 | // encoder.encodePacket(packet, result); 38 | Assert.assertEquals("5:::{\"name\":\"woot\"}", result.toString(CharsetUtil.UTF_8)); 39 | } 40 | 41 | @Test 42 | public void testEncodeWithMessageIdAndAck() throws IOException { 43 | Packet packet = new Packet(PacketType.EVENT); 44 | // packet.setId(1L); 45 | // packet.setAck(Packet.ACK_DATA); 46 | packet.setName("tobi"); 47 | ByteBuf result = Unpooled.buffer(); 48 | // encoder.encodePacket(packet, result); 49 | Assert.assertEquals("5:1+::{\"name\":\"tobi\"}", result.toString(CharsetUtil.UTF_8)); 50 | } 51 | 52 | @Test 53 | public void testEncodeWithData() throws IOException { 54 | Packet packet = new Packet(PacketType.EVENT); 55 | packet.setName("edwald"); 56 | // packet.setArgs(Arrays.asList(Collections.singletonMap("a", "b"), 2, "3")); 57 | ByteBuf result = Unpooled.buffer(); 58 | // encoder.encodePacket(packet, result); 59 | Assert.assertEquals("5:::{\"name\":\"edwald\",\"args\":[{\"a\":\"b\"},2,\"3\"]}", 60 | result.toString(CharsetUtil.UTF_8)); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/test/java/com/corundumstudio/socketio/parser/EncoderMessagePacketTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.parser; 17 | 18 | import io.netty.buffer.ByteBuf; 19 | import io.netty.buffer.Unpooled; 20 | import io.netty.util.CharsetUtil; 21 | 22 | import java.io.IOException; 23 | 24 | import org.junit.Assert; 25 | import org.junit.Test; 26 | 27 | import com.corundumstudio.socketio.protocol.Packet; 28 | import com.corundumstudio.socketio.protocol.PacketType; 29 | 30 | public class EncoderMessagePacketTest extends EncoderBaseTest { 31 | 32 | @Test 33 | public void testEncode() throws IOException { 34 | Packet packet = new Packet(PacketType.MESSAGE); 35 | packet.setData("woot"); 36 | ByteBuf result = Unpooled.buffer(); 37 | // encoder.encodePacket(packet, result); 38 | Assert.assertEquals("3:::woot", result.toString(CharsetUtil.UTF_8)); 39 | } 40 | 41 | @Test 42 | public void testEncodeWithIdAndEndpoint() throws IOException { 43 | Packet packet = new Packet(PacketType.MESSAGE); 44 | // packet.setId(5L); 45 | // packet.setAck(true); 46 | packet.setNsp("/tobi"); 47 | ByteBuf result = Unpooled.buffer(); 48 | // encoder.encodePacket(packet, result); 49 | Assert.assertEquals("3:5:/tobi", result.toString(CharsetUtil.UTF_8)); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/com/corundumstudio/socketio/parser/PayloadTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.parser; 17 | 18 | import io.netty.buffer.ByteBuf; 19 | import io.netty.buffer.Unpooled; 20 | import io.netty.util.CharsetUtil; 21 | 22 | import java.io.IOException; 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | import java.util.Queue; 26 | import java.util.concurrent.ConcurrentLinkedQueue; 27 | 28 | import org.junit.Assert; 29 | import org.junit.Ignore; 30 | import org.junit.Test; 31 | 32 | import com.corundumstudio.socketio.Configuration; 33 | import com.corundumstudio.socketio.protocol.JacksonJsonSupport; 34 | import com.corundumstudio.socketio.protocol.Packet; 35 | import com.corundumstudio.socketio.protocol.PacketDecoder; 36 | import com.corundumstudio.socketio.protocol.PacketEncoder; 37 | import com.corundumstudio.socketio.protocol.PacketType; 38 | 39 | @Ignore 40 | public class PayloadTest { 41 | 42 | private final JacksonJsonSupport support = new JacksonJsonSupport(); 43 | private final PacketDecoder decoder = new PacketDecoder(support, null); 44 | private final PacketEncoder encoder = new PacketEncoder(new Configuration(), support); 45 | 46 | @Test 47 | public void testPayloadDecode() throws IOException { 48 | ByteBuf buffer = Unpooled.wrappedBuffer("\ufffd5\ufffd3:::5\ufffd7\ufffd3:::53d\ufffd3\ufffd0::".getBytes()); 49 | List payload = new ArrayList(); 50 | while (buffer.isReadable()) { 51 | Packet packet = decoder.decodePackets(buffer, null); 52 | payload.add(packet); 53 | } 54 | 55 | Assert.assertEquals(3, payload.size()); 56 | Packet msg1 = payload.get(0); 57 | Assert.assertEquals(PacketType.MESSAGE, msg1.getType()); 58 | Assert.assertEquals("5", msg1.getData()); 59 | Packet msg2 = payload.get(1); 60 | Assert.assertEquals(PacketType.MESSAGE, msg2.getType()); 61 | Assert.assertEquals("53d", msg2.getData()); 62 | Packet msg3 = payload.get(2); 63 | Assert.assertEquals(PacketType.DISCONNECT, msg3.getType()); 64 | } 65 | 66 | @Test 67 | public void testPayloadEncode() throws IOException { 68 | Queue packets = new ConcurrentLinkedQueue(); 69 | Packet packet1 = new Packet(PacketType.MESSAGE); 70 | packet1.setData("5"); 71 | packets.add(packet1); 72 | 73 | Packet packet2 = new Packet(PacketType.MESSAGE); 74 | packet2.setData("53d"); 75 | packets.add(packet2); 76 | 77 | ByteBuf result = Unpooled.buffer(); 78 | // encoder.encodePackets(packets, result, UnpooledByteBufAllocator.DEFAULT); 79 | Assert.assertEquals("\ufffd5\ufffd3:::5\ufffd7\ufffd3:::53d", result.toString(CharsetUtil.UTF_8)); 80 | } 81 | 82 | @Test 83 | public void testDecodingNewline() throws IOException { 84 | Packet packet = decoder.decodePackets(Unpooled.copiedBuffer("3:::\n", CharsetUtil.UTF_8), null); 85 | Assert.assertEquals(PacketType.MESSAGE, packet.getType()); 86 | Assert.assertEquals("\n", packet.getData()); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/test/java/com/corundumstudio/socketio/protocol/PacketTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.corundumstudio.socketio.protocol; 17 | 18 | import static org.junit.Assert.assertEquals; 19 | import static org.junit.Assert.assertNotSame; 20 | import static org.junit.Assert.assertNull; 21 | import static org.junit.Assert.assertSame; 22 | 23 | import io.netty.buffer.Unpooled; 24 | import org.junit.Test; 25 | 26 | public class PacketTest { 27 | 28 | @Test 29 | public void packetCopyIsCreatedWhenNamespaceDiffers() { 30 | Packet oldPacket = createPacket(); 31 | 32 | String newNs = "new"; 33 | Packet newPacket = oldPacket.withNsp(newNs, EngineIOVersion.UNKNOWN); 34 | assertEquals(newNs, newPacket.getNsp()); 35 | assertPacketCopied(oldPacket, newPacket); 36 | } 37 | 38 | @Test 39 | public void packetCopyIsCreatedWhenNewNamespaceDiffersAndIsNull() { 40 | Packet packet = createPacket(); 41 | Packet newPacket = packet.withNsp(null, EngineIOVersion.UNKNOWN); 42 | assertNull(newPacket.getNsp()); 43 | assertPacketCopied(packet, newPacket); 44 | } 45 | 46 | @Test 47 | public void originalPacketReturnedIfNamespaceIsTheSame() { 48 | Packet packet = new Packet(PacketType.MESSAGE); 49 | assertSame(packet, packet.withNsp("", EngineIOVersion.UNKNOWN)); 50 | } 51 | 52 | private void assertPacketCopied(Packet oldPacket, Packet newPacket) { 53 | assertNotSame(newPacket, oldPacket); 54 | assertEquals(oldPacket.getName(), newPacket.getName()); 55 | assertEquals(oldPacket.getType(), newPacket.getType()); 56 | assertEquals(oldPacket.getSubType(), newPacket.getSubType()); 57 | assertEquals(oldPacket.getAckId(), newPacket.getAckId()); 58 | assertEquals(oldPacket.getAttachments().size(), newPacket.getAttachments().size()); 59 | assertSame(oldPacket.getAttachments(), newPacket.getAttachments()); 60 | assertEquals(oldPacket.getData(), newPacket.getData()); 61 | assertSame(oldPacket.getDataSource(), newPacket.getDataSource()); 62 | } 63 | 64 | private Packet createPacket() { 65 | Packet packet = new Packet(PacketType.MESSAGE); 66 | packet.setSubType(PacketType.EVENT); 67 | packet.setName("packetName"); 68 | packet.setData("data"); 69 | packet.setAckId(1L); 70 | packet.setNsp("old"); 71 | packet.setDataSource(Unpooled.wrappedBuffer(new byte[]{10})); 72 | packet.initAttachments(1); 73 | packet.addAttachment(Unpooled.wrappedBuffer(new byte[]{20})); 74 | return packet; 75 | } 76 | } -------------------------------------------------------------------------------- /src/test/java/com/corundumstudio/socketio/transport/WebSocketTransportTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2023 Nikita Koksharov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | /* 17 | * @(#)WebSocketTransportTest.java 2018. 5. 23. 18 | * 19 | * Licensed under the Apache License, Version 2.0 (the "License"); 20 | * you may not use this file except in compliance with the License. 21 | * You may obtain a copy of the License at 22 | * 23 | * http://www.apache.org/licenses/LICENSE-2.0 24 | * 25 | * Unless required by applicable law or agreed to in writing, software 26 | * distributed under the License is distributed on an "AS IS" BASIS, 27 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 28 | * See the License for the specific language governing permissions and 29 | * limitations under the License. 30 | */ 31 | package com.corundumstudio.socketio.transport; 32 | 33 | import static org.junit.Assert.assertTrue; 34 | 35 | import org.junit.Test; 36 | 37 | import io.netty.channel.ChannelHandlerContext; 38 | import io.netty.channel.embedded.EmbeddedChannel; 39 | import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; 40 | 41 | /** 42 | * @author hangsu.cho@navercorp.com 43 | * 44 | */ 45 | public class WebSocketTransportTest { 46 | 47 | /** 48 | * Test method for {@link com.corundumstudio.socketio.transport.WebSocketTransport#channelRead()}. 49 | */ 50 | @Test 51 | public void testCloseFrame() { 52 | EmbeddedChannel channel = createChannel(); 53 | 54 | channel.writeInbound(new CloseWebSocketFrame()); 55 | Object msg = channel.readOutbound(); 56 | 57 | // https://tools.ietf.org/html/rfc6455#section-5.5.1 58 | // If an endpoint receives a Close frame and did not previously send a Close frame, the endpoint 59 | // MUST send a Close frame in response. 60 | assertTrue(msg instanceof CloseWebSocketFrame); 61 | } 62 | 63 | private EmbeddedChannel createChannel() { 64 | return new EmbeddedChannel(new WebSocketTransport(false, null, null, null, null) { 65 | /* 66 | * (non-Javadoc) 67 | * 68 | * @see 69 | * com.corundumstudio.socketio.transport.WebSocketTransport#channelInactive(io.netty.channel. 70 | * ChannelHandlerContext) 71 | */ 72 | @Override 73 | public void channelInactive(ChannelHandlerContext ctx) throws Exception {} 74 | }); 75 | } 76 | 77 | } 78 | --------------------------------------------------------------------------------