jSS7中的SendParameters怪异行为

问题描述

所以我有一个restcomm/jss7的分叉版本,其中我实现了为MAP v1定义的SendParameters SS7命令,因为我分叉的版本当时没有实现(不要认为它已实现)仍然)。这不是我在JSS7中实现的第一个命令。问题是,我非常确定自己的编码/解码遵循09.02规范,但是当我构造一个给定TMSI而不是IMAGESIDS的invokeSendParameters消息(在SubscriberId部分中)时,它在Wirehark中显示为msisdn且未正确解析。这是Wireshark的问题还是我的实现有错?我的SendParametersRequestImpl和SubscriberIdImpl供参考:

public class SendParameterRequestImp extends mobilityMessageImpl implements SendParametersRequest {

    private static final int _TAG_SUBSCRIBER_ID = 0;
    private static final int _TAG_REQUESTED_ParaMETER = 1;

    private SubscriberId subscriberId;
    private static final String _PrimitiveName = "SendParameterRequestImp";

    private ArrayList<RequestParameter> requestParameterList;

    public SendParameterRequestImp(SubscriberId subscriberId,ArrayList<RequestParameter> requestParameters) {
        this.subscriberId = subscriberId;
        this.requestParameterList = requestParameters;
    }

    public SendParameterRequestImp() {
    }

    @Override
    public ArrayList<RequestParameter> getRequestParameterList() {
        return requestParameterList;
    }

    @Override
    public SubscriberId getSubscriberId() {
        return subscriberId;
    }

    public void setSubscriberId(SubscriberId subscriberId) {
        this.subscriberId = subscriberId;
    }


    @Override
    public MAPMessageType getMessageType() {
        return MAPMessageType.sendParameter_Request;
    }

    @Override
    public int getoperationCode() {
        return MAPOperationCode.sendParameters;
    }

    @Override
    public int getTag() throws MAPException {
        return Tag.SEQUENCE;
    }

    @Override
    public int getTagClass() {
        return Tag.CLASS_UNIVERSAL;
    }

    @Override
    public boolean getIsPrimitive() {
        return false;
    }

    @Override
    public void decodeAll(AsnInputStream ansIS) throws MAPParsingComponentException {
        try {
            int length = ansIS.readLength();
            this._decode(ansIS,length);
        } catch (IOException e) {
            throw new MAPParsingComponentException("IOException when decoding " + _PrimitiveName + ": " + e.getMessage(),e,MAPParsingComponentExceptionReason.MistypedParameter);
        } catch (AsnException e) {
            throw new MAPParsingComponentException("AsnException when decoding " + _PrimitiveName + ": " + e.getMessage(),MAPParsingComponentExceptionReason.MistypedParameter);
        }
    }

    private void _decode(AsnInputStream ansIS,int length) throws IOException,AsnException,MAPParsingComponentException {
        AsnInputStream ais = ansIS.readSequenceStreamData(length);
        while (true) {
            if (ais.available() == 0)
                break;
            int tag = ais.readTag();
            switch (ais.getTagClass()) {
                case Tag.CLASS_CONTEXT_SPECIFIC:
                    this.subscriberId = new SubscriberIdImpl();
                    ((SubscriberIdImpl) this.subscriberId).decodeAll(ais);
                    break;
                case Tag.CLASS_UNIVERSAL:
                    switch (tag) {
                        case Tag.SEQUENCE:
                            this.requestParameterList = new ArrayList<RequestParameter>();
                            AsnInputStream ais3 = ais.readSequenceStream();

                            while (true) {
                                if (ais3.available() == 0)
                                    break;

                                int tag2 = ais3.readTag();

                                if (tag2 != Tag.ENUMERATED)
                                    throw new MAPParsingComponentException("Error while decoding " + _PrimitiveName
                                            + ": bad tag or tagClass or is not primitive when decoding plmnClientList",MAPParsingComponentExceptionReason.MistypedParameter);

                                int code = (int) ais3.readInteger();

                                RequestParameter elem = RequestParameter.getInstance(code);

                                this.requestParameterList.add(elem);
                            }
                            break;
                        default:
                            ais.advanceElement();
                            break;
                    }
                    break;
                default:
                    ais.advanceElement();
                    break;
            }
        }

    }

    @Override
    public void decodeData(AsnInputStream ansIS,int length) throws MAPParsingComponentException {
        try {
            this._decode(ansIS,MAPParsingComponentExceptionReason.MistypedParameter);
        }
    }

    @Override
    public void encodeAll(AsnOutputStream asnOs) throws MAPException {
        this.encodeAll(asnOs,this.getTagClass(),this.getTag());
    }

    @Override
    public void encodeAll(AsnOutputStream asnOs,int tagClass,int tag) throws MAPException {
        try {
            asnOs.writeTag(tagClass,this.getIsPrimitive(),tag);
            int pos = asnOs.StartContentDefiniteLength();
            this.encodeData(asnOs);
            asnOs.FinalizeContent(pos);
        } catch (AsnException e) {
            throw new MAPException("AsnException when encoding " + _PrimitiveName + ": " + e.getMessage(),e);

        }
    }

    @Override
    public void encodeData(AsnOutputStream asnOs) throws MAPException {
        if (this.subscriberId == null || this.requestParameterList == null) {
            throw new MAPException("Error while encoding " + _PrimitiveName
                    + " the mandatory parameter subscriberId and requestParameterList is not defined");
        }
        ((SubscriberIdImpl) this.subscriberId).encodeAll(asnOs);
        try {
            asnOs.writeTag(Tag.CLASS_UNIVERSAL,false,Tag.SEQUENCE);
            int pos = asnOs.StartContentDefiniteLength();
            for (RequestParameter requestParameter : this.requestParameterList)
                asnOs.writeInteger(Tag.CLASS_UNIVERSAL,Tag.ENUMERATED,requestParameter.getCode());
            asnOs.FinalizeContent(pos);

        } catch (IOException e) {
            e.printstacktrace();
        } catch (AsnException e) {
            e.printstacktrace();
        }
    }

    @Override
    public String toString() {
        return "SendParameterRequestImp{" +
                "subscriberId=" + subscriberId +
                ",requestParameterList=" + requestParameterList +
                '}';
    }
}
public class SubscriberIdImpl implements SubscriberId,MAPAsnPrimitive {
    private TMSI tmsi;
    private imsI imsi;

    private static final int _TAG_imsI = 0;
    private static final int _TAG_TMSI = 1;
    private static final String _PrimitiveName = "SubscriberId";

    public SubscriberIdImpl() {
    }

    public SubscriberIdImpl(TMSI tmsi) {
        this.tmsi = tmsi;
    }

    public SubscriberIdImpl(imsI imsi) {
        this.imsi = imsi;
    }

    @Override
    public TMSI getTmsi() {
        return tmsi;
    }

    @Override
    public imsI getimsi() {
        return imsi;
    }

    @Override
    public int getTag() throws MAPException {
        if (this.imsi != null) {
            return _TAG_imsI;
        } else {
            return _TAG_TMSI;
        }
    }

    @Override
    public int getTagClass() {
        return Tag.CLASS_CONTEXT_SPECIFIC;
    }

    @Override
    public boolean getIsPrimitive() {
        return true;
    }

    @Override
    public void decodeAll(AsnInputStream ansIS) throws MAPParsingComponentException {
        try {
            int length = ansIS.readLength();
            this._decode(ansIS,length);
        } catch (IOException e) {
            throw new MAPParsingComponentException("IOException when decoding " + _PrimitiveName + ": ",MAPParsingComponentExceptionReason.MistypedParameter);
        }
    }

    private void _decode(AsnInputStream asnIS,int length) throws MAPParsingComponentException {
        if (asnIS.getTagClass() != Tag.CLASS_CONTEXT_SPECIFIC || !asnIS.isTagPrimitive())
            throw new MAPParsingComponentException("Error while decoding " + _PrimitiveName
                    + ": bad tag class or is not primitive: TagClass=" + asnIS.getTagClass(),MAPParsingComponentExceptionReason.MistypedParameter);

        switch (asnIS.getTag()) {
            case _TAG_imsI:
                this.imsi = new imsIImpl();
                ((imsIImpl) this.imsi).decodeData(asnIS,length);
                break;
            case _TAG_TMSI:
                this.tmsi = new TMSIImpl();
                ((TMSIImpl) this.tmsi).decodeData(asnIS,length);
                break;
            default:
                throw new MAPParsingComponentException("Error while decoding " + _PrimitiveName
                        + ": Expexted imsi [0] imsI or msisdn [1] ISDN-Addressstring,but found " + asnIS.getTag(),MAPParsingComponentExceptionReason.MistypedParameter);
        }
    }

    @Override
    public void decodeData(AsnInputStream ansIS,int length) throws MAPParsingComponentException {
        this._decode(ansIS,length);
    }

    @Override
    public void encodeAll(AsnOutputStream asnOs) throws MAPException {
        this.encodeAll(asnOs,this.getTag());

    }

    @Override
    public void encodeAll(AsnOutputStream asnOs,e);
        }
    }

    @Override
    public void encodeData(AsnOutputStream asnOs) throws MAPException {
        if (this.imsi == null && this.tmsi == null)
            throw new MAPException("Error while encoding " + _PrimitiveName + ": all choices must not be null");
        if (this.imsi != null && this.tmsi != null)
            throw new MAPException("Error while encoding " + _PrimitiveName + ": all choices must not be not null");

        if (this.imsi != null) {
            ((imsIImpl) this.imsi).encodeData(asnOs);
        } else {
            ((TMSIImpl) this.tmsi).encodeData(asnOs);
        }
    }

    @Override
    public String toString() {
        return "SubscriberIdImpl{" +
                "tmsi=" + tmsi +
                ",imsi=" + imsi +
                '}';
    }
}

ASN.1规范如下:

MAP V1: SendParametersArg ::= SEQUENCE { subscriberId SubscriberId,requestParameterList RequestParameterList}
requestParameterList SEQUENCE SIZE (1..2) OF RequestParameter
SubscriberId ::= CHOICE { imsi [0] imsI,tmsi [1] TMSI}

Wireshark屏幕截图:

enter image description here

解决方法

在查看了asn.1的wireshark源代码分解器之后,它们似乎为SendParametersArg使用了SubscriberIdentity而不是SubscriberId。区别在于前者是IMSI和MSISDN之间的选择,而后者是IMSI和TMSI之间的选择。