All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.netty.protocol.mysql.client.MysqlFrontendBusinessHandler Maven / Gradle / Ivy

The newest version!
package com.github.netty.protocol.mysql.client;

import com.github.netty.core.AbstractChannelHandler;
import com.github.netty.protocol.mysql.*;
import com.github.netty.protocol.mysql.listener.MysqlPacketListener;
import com.github.netty.protocol.mysql.server.*;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Here the user business logic
 * 

* follows * 1. server to client {@link ServerHandshakePacket} * 2. client to server {@link ClientHandshakePacket} * 3. server to client {@link ServerOkPacket} * 4. client to server query... {@link ClientQueryPacket} * 5. server to client {@link ServerOkPacket} * 6. any.... *

* Initial Handshake starts with server sending the `Initial Handshake Packet` {@link ServerHandshakePacket}. * After this, optionally, * client can request an SSL connection to be established with `SSL Connection Request Packet` TODO , * and then client sends the `Handshake Response Packet` {@link ClientHandshakePacket}. */ public class MysqlFrontendBusinessHandler extends AbstractChannelHandler { protected static Pattern SETTINGS_PATTERN = Pattern.compile("@@(\\w+)\\sAS\\s(\\w+)"); private int maxPacketSize; private Session session; private Collection mysqlPacketListeners; public MysqlFrontendBusinessHandler() { super(false); } @Override protected void onMessageReceived(ChannelHandlerContext ctx, ClientPacket msg) throws Exception { if (msg instanceof ClientHandshakePacket) { onHandshake(ctx, (ClientHandshakePacket) msg); } if (mysqlPacketListeners != null && !mysqlPacketListeners.isEmpty()) { for (MysqlPacketListener mysqlPacketListener : mysqlPacketListeners) { try { mysqlPacketListener.onMysqlPacket(msg, ctx, session, Constants.HANDLER_TYPE_FRONTEND); } catch (Exception e) { logger.warn("{} exception = {} ", mysqlPacketListener.toString(), e.toString(), e); } } } onMysqlPacket(ctx, msg); } protected void onMysqlPacket(ChannelHandlerContext ctx, ClientPacket packet) { } @Override protected void onUserEventTriggered(ChannelHandlerContext ctx, Object evt) { super.onUserEventTriggered(ctx, evt); if (evt instanceof EventHandshakeSuccessful) { onHandshakeSuccessful(ctx, (EventHandshakeSuccessful) evt); } } protected void onHandshake(ChannelHandlerContext ctx, ClientHandshakePacket packet) { session.setClientCharsetAttr(packet.getCharacterSet()); session.setFrontendCapabilities(packet.getCapabilities()); } protected void onHandshakeSuccessful(ChannelHandlerContext ctx, EventHandshakeSuccessful event) { if (ctx.pipeline().context(ClientConnectionDecoder.class) != null) { ctx.pipeline().replace(ClientConnectionDecoder.class, "ClientCommandDecoder", new ClientCommandDecoder(session, getMaxPacketSize())); } } public ClientHandshakePacket newClientHandshakePacket(String user, String password, String database, ServerHandshakePacket serverHandshakePacket, Set capabilities) { ClientHandshakePacket packet = ClientHandshakePacket.create() .addCapabilities(capabilities) .username(user) .addAuthData(MysqlNativePasswordUtil.hashPassword(password, serverHandshakePacket.getAuthPluginData())) .database(database) .authPluginName(Constants.MYSQL_NATIVE_PASSWORD) .build(); return packet; } /** * String query = packet.getQuery(); * if (isServerSettingQuery(query)) { * sendSettingPacket(ctx, packet); * } * * @param query query sql * @return isServerSettingQuery */ protected boolean isServerSettingQuery(String query) { query = query.toLowerCase(); return query.contains("select") && !query.contains("from") && query.contains("@@"); } protected ChannelFuture writeAndFlushSettingPacket(ChannelHandlerContext ctx, ClientQueryPacket query) { Matcher matcher = SETTINGS_PATTERN.matcher(query.getQuery()); List values = new ArrayList<>(); int sequenceId = query.getSequenceId(); while (matcher.find()) { String systemVariable = matcher.group(1); String fieldName = matcher.group(2); switch (systemVariable) { case "character_set_client": case "character_set_connection": case "character_set_results": case "character_set_server": ctx.write(newColumnDefinition(sequenceId++, fieldName, systemVariable, ColumnType.MYSQL_TYPE_VAR_STRING, 12)); values.add("utf8"); break; case "collation_server": ctx.write(newColumnDefinition(sequenceId++, fieldName, systemVariable, ColumnType.MYSQL_TYPE_LONGLONG, 21)); values.add("utf8_general_ci"); break; case "init_connect": ctx.write(newColumnDefinition(sequenceId++, fieldName, systemVariable, ColumnType.MYSQL_TYPE_VAR_STRING, 0)); values.add(""); break; case "interactive_timeout": ctx.write(newColumnDefinition(sequenceId++, fieldName, systemVariable, ColumnType.MYSQL_TYPE_VAR_STRING, 21)); values.add("28800"); break; case "language": ctx.write(newColumnDefinition(sequenceId++, fieldName, systemVariable, ColumnType.MYSQL_TYPE_VAR_STRING, 0)); values.add(""); break; case "license": ctx.write(newColumnDefinition(sequenceId++, fieldName, systemVariable, ColumnType.MYSQL_TYPE_VAR_STRING, 21)); values.add("ASLv2"); break; case "lower_case_table_names": ctx.write(newColumnDefinition(sequenceId++, fieldName, systemVariable, ColumnType.MYSQL_TYPE_LONGLONG, 63)); values.add("2"); break; case "max_allowed_packet": ctx.write(newColumnDefinition(sequenceId++, fieldName, systemVariable, ColumnType.MYSQL_TYPE_LONGLONG, 63)); values.add("4194304"); break; case "net_buffer_length": ctx.write(newColumnDefinition(sequenceId++, fieldName, systemVariable, ColumnType.MYSQL_TYPE_LONGLONG, 63)); values.add("16384"); break; case "net_write_timeout": ctx.write(newColumnDefinition(sequenceId++, fieldName, systemVariable, ColumnType.MYSQL_TYPE_LONGLONG, 63)); values.add("60"); break; case "have_query_cache": ctx.write(newColumnDefinition(sequenceId++, fieldName, systemVariable, ColumnType.MYSQL_TYPE_LONGLONG, 6)); values.add("YES"); break; case "sql_mode": ctx.write(newColumnDefinition(sequenceId++, fieldName, systemVariable, ColumnType.MYSQL_TYPE_LONGLONG, 0)); values.add(""); break; case "system_time_zone": ctx.write(newColumnDefinition(sequenceId++, fieldName, systemVariable, ColumnType.MYSQL_TYPE_LONGLONG, 6)); values.add("UTC"); break; case "time_zone": ctx.write(newColumnDefinition(sequenceId++, fieldName, systemVariable, ColumnType.MYSQL_TYPE_LONGLONG, 12)); values.add("SYSTEM"); break; case "tx_isolation": ctx.write(newColumnDefinition(sequenceId++, fieldName, systemVariable, ColumnType.MYSQL_TYPE_LONGLONG, 12)); values.add("REPEATABLE-READ"); break; case "wait_timeout": ctx.write(newColumnDefinition(sequenceId++, fieldName, systemVariable, ColumnType.MYSQL_TYPE_LONGLONG, 12)); values.add("28800"); break; default: { // throw new Error("Unknown system variable " + systemVariable); } } } ctx.write(new ServerEofPacket(++sequenceId, 0)); ctx.write(new ServerResultsetRowPacket(++sequenceId, values.toArray(new String[0]))); return ctx.writeAndFlush(new ServerEofPacket(++sequenceId, 0)); } protected ServerColumnDefinitionPacket newColumnDefinition(int packetSequence, String name, String orgName, ColumnType columnType, int length) { return ServerColumnDefinitionPacket.builder() .sequenceId(packetSequence) .name(name) .orgName(orgName) .type(columnType) .columnLength(length) .build(); } public int getMaxPacketSize() { return maxPacketSize; } public void setMaxPacketSize(int maxPacketSize) { this.maxPacketSize = maxPacketSize; } public Session getSession() { return session; } public void setSession(Session session) { this.session = session; } public Collection getMysqlPacketListeners() { return mysqlPacketListeners; } public void setMysqlPacketListeners(Collection mysqlPacketListeners) { this.mysqlPacketListeners = mysqlPacketListeners; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy