ru.jts_dev.gameserver.service.GameSessionService.java Source code

Java tutorial

Introduction

Here is the source code for ru.jts_dev.gameserver.service.GameSessionService.java

Source

/*
 * Copyright (c) 2015, 2016, 2017 JTS-Team authors and/or its affiliates. All rights reserved.
 *
 * This file is part of JTS-V3 Project.
 *
 * JTS-V3 Project is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JTS-V3 Project is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with JTS-V3 Project.  If not, see <http://www.gnu.org/licenses/>.
 */

package ru.jts_dev.gameserver.service;

import io.netty.buffer.ByteBuf;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.integration.ip.tcp.connection.TcpConnection;
import org.springframework.integration.ip.tcp.connection.TcpConnectionCloseEvent;
import org.springframework.integration.ip.tcp.connection.TcpConnectionEvent;
import org.springframework.stereotype.Service;
import ru.jts_dev.gameserver.model.GameSession;

import javax.annotation.Nullable;
import java.nio.ByteOrder;
import java.util.Collections;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

import static io.netty.buffer.Unpooled.buffer;
import static io.netty.buffer.Unpooled.copiedBuffer;

/**
 * @author Camelion
 * @since 13.12.15
 */
@Service
public class GameSessionService {
    private static final byte[] STATIC_KEY_PART = new byte[] { (byte) 0xc8, (byte) 0x27, (byte) 0x93, (byte) 0x01,
            (byte) 0xa1, (byte) 0x6c, (byte) 0x31, (byte) 0x97 };

    private final Map<String, GameSession> sessions = new ConcurrentHashMap<>();
    private final Map<String, String> accounts = new ConcurrentHashMap<>();

    private final Random random;

    @Autowired
    public GameSessionService(Random random) {
        this.random = random;
    }

    Map<String, GameSession> getSessions() {
        return Collections.unmodifiableMap(sessions);
    }

    /**
     * Note: this method can return null.
     * Always check returned value with null, and break, if check not passed.
     * <pre>
     *     GameSession gameSession = sessionService.getSessionById(getConnectionId());
     *     if(gameSession == null) return;
     * </pre>
     *
     * @param connectionId - connection identifier of session
     * @return stored GameSession or {@code null}
     */
    @Nullable
    public GameSession getSessionBy(String connectionId) {
        return sessions.getOrDefault(connectionId, null);
    }

    /**
     * Note: this method can return null.
     * Always check returned value with null, and break, if check not passed.
     * <pre>
     *     String account = sessionService.getAccountBy(getConnectionId());
     *     if(account == null) return;
     * </pre>
     *
     * @param connectionId - connection identifier of session
     * @return stored GameSession or {@code null}
     */
    @Nullable
    public String getAccountBy(String connectionId) {
        return accounts.getOrDefault(connectionId, null);
    }

    public void forcedClose(GameSession session) {
        session.getConnection().close();
    }

    private GameSession createSession(TcpConnection connection) {
        ByteBuf encryptKey = buffer(16, 16).order(ByteOrder.LITTLE_ENDIAN);
        // randomize first 8 bytes of key
        random.nextBytes(encryptKey.array());
        encryptKey.writerIndex(8);

        // and add 8 byte as static key part
        encryptKey.writeBytes(STATIC_KEY_PART);

        // then copy encrypt key to decrypt key
        ByteBuf decryptKey = copiedBuffer(encryptKey).order(ByteOrder.LITTLE_ENDIAN);

        // and pass keys to a game session object
        return new GameSession(connection, encryptKey, decryptKey);
    }

    @Order(Ordered.HIGHEST_PRECEDENCE)
    @EventListener
    private void tcpConnectionEventListener(TcpConnectionEvent event) {
        sessions.put(event.getConnectionId(), createSession((TcpConnection) event.getSource()));
    }

    @EventListener
    private void tcpConnectionEventListener(TcpConnectionCloseEvent event) {
        sessions.remove(event.getConnectionId());
        accounts.remove(event.getConnectionId());
    }

    @EventListener
    public void accountLogged(AccountEvent event) {
        accounts.put(event.getConnectionId(), (String) event.getSource());
    }

    public static class AccountEvent extends ApplicationEvent {
        private final String connectionId;

        public AccountEvent(String connectionId, String login) {
            super(login);
            this.connectionId = connectionId;
        }

        public String getConnectionId() {
            return connectionId;
        }
    }
}