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

org.wildfly.transaction.client.provider.remoting.Protocol Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 34.0.0.Final
Show newest version
/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2016 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.wildfly.transaction.client.provider.remoting;

import static org.jboss.remoting3.util.StreamUtils.*;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

import javax.transaction.xa.Xid;

import org.wildfly.transaction.client.SimpleXid;

/**
 * @author David M. Lloyd
 */
class Protocol {
    public static final boolean SIGNED = true;
    public static final boolean UNSIGNED = false;

    public static final int VERSION_MIN = 0;
    public static final int VERSION_MAX = 0;

    // all msgs are initiated by the client
    // msg format
    // byte 0-1: inv ID
    // byte 2: M_ message type
    // byte 3...: P_ parameters

    // parameter format
    // byte 0: param ID
    // byte 1-x: length (packed integer)
    // byte x...: parameter payload of exactly length bytes

    // client -> server

    // Add capabilities; server only replies with acknowledged capabilities (may be empty) (error not raised on unrecognized)
    public static final int M_CAPABILITY    = 0x00; // P_*

    // unused                               = 0x01
    // Roll back the transaction with the given XID
    public static final int M_XA_ROLLBACK   = 0x02; // P_XID(gtid) [ P_SEC_CONTEXT ]
    // Prepare the transaction with the given XID
    public static final int M_XA_PREPARE    = 0x03; // P_XID(gtid) [ P_SEC_CONTEXT ]
    // Commit the transaction with the given XID
    public static final int M_XA_COMMIT     = 0x04; // P_XID(gtid) [ P_SEC_CONTEXT ] [ P_ONE_PHASE ]
    // Forget the transaction with the given XID
    public static final int M_XA_FORGET     = 0x05; // P_XID(gtid) [ P_SEC_CONTEXT ]
    // Execute before-completion for the transaction with the given XID
    public static final int M_XA_BEFORE     = 0x06; // P_XID(gtid) [ P_SEC_CONTEXT ]
    // Get a list of XIDs to recover
    public static final int M_XA_RECOVER    = 0x07; // [ P_SEC_CONTEXT ] [ P_PARENT_NAME ]
    // Mark the XA transaction as rollback-only; used if the resource was called with TMFAIL
    public static final int M_XA_RB_ONLY    = 0x08; // P_XID(gtid) [ P_SEC_CONTEXT ]
    // Unused
    // unused                               = 0x09;
    // TXN_CONTEXT is released (even for error)
    public static final int M_UT_COMMIT     = 0x0A; // P_TXN_CONTEXT [ P_SEC_CONTEXT ]
    // TXN_CONTEXT is released (even for error)
    public static final int M_UT_ROLLBACK   = 0x0B; // P_TXN_CONTEXT [ P_SEC_CONTEXT ]

    // server -> client

    public static final int M_RESP_CAPABILITY   = 0x00; // P_*

    // unused                                   = 0x11;
    public static final int M_RESP_XA_ROLLBACK  = 0x12; // [ P_XA_ERROR | P_SEC_EXC ]
    public static final int M_RESP_XA_PREPARE   = 0x13; // [ P_XA_RDONLY | P_XA_ERROR | P_SEC_EXC ]
    public static final int M_RESP_XA_COMMIT    = 0x14; // [ P_XA_ERROR | P_SEC_EXC ]
    public static final int M_RESP_XA_FORGET    = 0x15; // [ P_XA_ERROR | P_SEC_EXC ]
    public static final int M_RESP_XA_BEFORE    = 0x16; // [ P_XA_ERROR | P_SEC_EXC ]

    public static final int M_RESP_XA_RECOVER   = 0x17; // P_XID... | P_XA_ERROR | P_SEC_EXC

    public static final int M_RESP_XA_RB_ONLY   = 0x18; // [ P_XA_ERROR | P_SEC_EXC ]

    public static final int M_RESP_UT_COMMIT    = 0x1A; // [ P_UT_RB_EXC | P_UT_HME_EXC | P_UT_HRE_EXC | P_UT_SYS_EXC | P_SEC_EXC ]
    public static final int M_RESP_UT_ROLLBACK  = 0x1B; // [ P_UT_SYS_EXC | P_SEC_EXC ]

    public static final int M_RESP_PARAM_ERROR  = 0xFE; // empty (missing required or found unknown parameter)
    public static final int M_RESP_ERROR        = 0xFF; // empty (unknown request code)

    // parameters

    // unused                                 0x00
    public static final int P_XID           = 0x01; // body = XID
    public static final int P_ONE_PHASE     = 0x02; // len=0
    public static final int P_PARENT_NAME   = 0x03; // body = utf8
    // unused                                 0x04
    // unused                                 0x05
    // unused                                 0x06
    public static final int P_XA_RDONLY     = 0x07; // len=0

    // Exception types format:
    //  byte 0..3 = error code (XA and sys exceptions only)
    //  byte 4..n = org.wildfly.common.rpc.RemoteExceptionCause cause info (byte 0..n for non-XA/sysex)

    public static final int P_UT_RB_EXC     = 0x10; // RollbackException
    public static final int P_UT_HME_EXC    = 0x11; // HeuristicMixedException
    public static final int P_UT_HRE_EXC    = 0x12; // HeuristicRollbackException
    public static final int P_UT_SYS_EXC    = 0x13; // SystemException
    public static final int P_UT_IS_EXC     = 0x14; // IllegalStateException

    public static final int P_SEC_EXC       = 0x20; // SecurityException

    public static final int P_XA_ERROR      = 0x30; // body = packed-int (signed) XA error code

    public static final int P_VERSION_ERROR = 0x40; // additional capabilities must be negotiated (s -> c)

    public static final int P_SEC_CONTEXT   = 0xF0; // uint32 security context association ID
    public static final int P_TXN_CONTEXT   = 0xF1; // uint32 transaction context association ID

    public static void writeParam(int param, OutputStream os, int val, boolean signed) throws IOException {
        writeInt8(os, param);
        final int len;
        if (signed && val < 0) {
            // always write one sign byte if needed
            len = 32 - Integer.numberOfLeadingZeros(~val) + 8 >> 3;
        } else {
            len = 32 - Integer.numberOfLeadingZeros(val) + 7 >> 3;
        }
        writeInt8(os, len);
        switch (len) {
            case 4: writeInt8(os, val >> 24);
            case 3: writeInt8(os, val >> 16);
            case 2: writeInt8(os, val >> 8);
            case 1: writeInt8(os, val >> 0);
        }
    }

    public static void writeParam(int param, OutputStream os, byte[] bytes) throws IOException {
        writeInt8(os, param);
        if (bytes == null || bytes.length == 0) {
            writeInt8(os, 0);
        } else {
            writePackedUnsignedInt32(os, bytes.length);
            os.write(bytes);
        }
    }

    public static void writeParam(int param, OutputStream os, String str) throws IOException {
        if (str == null || str.isEmpty()) {
            writeParam(param, os);
        } else {
            writeParam(param, os, str.getBytes(StandardCharsets.UTF_8));
        }
    }

    public static void writeParam(int param, OutputStream os) throws IOException {
        writeInt8(os, param);
        writeInt8(os, 0);
    }

    public static void writeParam(int param, OutputStream os, Xid xid) throws IOException {
        if (xid == null) {
            writeParam(param, os);
            return;
        }
        final int formatId = xid.getFormatId();
        final byte[] gtid = xid.getGlobalTransactionId();
        final byte[] bq = xid.getBranchQualifier();
        if (gtid.length > Xid.MAXGTRIDSIZE || bq.length > Xid.MAXBQUALSIZE) {
            throw new IOException("Cannot write invalid XID");
        }
        final int len = gtid.length + bq.length + 5;
        //noinspection PointlessBooleanExpression,ConstantConditions
        assert Xid.MAXGTRIDSIZE <= 64 && Xid.MAXBQUALSIZE <= 64 && len < 256;
        // might be > 127
        writeInt8(os, param);
        writePackedUnsignedInt32(os, len);
        writeInt32BE(os, formatId);
        writeInt8(os, gtid.length);
        os.write(gtid);
        os.write(bq);
    }

    public static int readIntParam(InputStream is, int len) throws IOException {
        int t = 0;
        for (int i = 0; i < len; i ++) {
            t = t << 8 | readInt8(is) & 0xff;
        }
        return t;
    }

    public static String readStringParam(InputStream is, int len) throws IOException {
        byte[] b = new byte[len];
        readFully(is, b);
        return new String(b, StandardCharsets.UTF_8);
    }

    public static SimpleXid readXid(InputStream is, int len) throws IOException {
        final int formatId = readInt32BE(is);
        len -= 4;
        int gtidLen = readInt8(is);
        len --;
        if (len < gtidLen) {
            throw new EOFException();
        }
        final byte[] gtid = gtidLen == 0 ? SimpleXid.NO_BYTES : new byte[gtidLen];
        readFully(is, gtid);
        len -= gtidLen;
        final byte[] bq = len == 0 ? SimpleXid.NO_BYTES : new byte[len];
        readFully(is, bq);
        return new SimpleXid(formatId, gtid, bq);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy