zoukankan      html  css  js  c++  java
  • jDiameter介绍以及使用

    jDiameter是Diameter协议的开源实现(比较不幸的是AGPL 3.0协议),项目地址https://github.com/RestComm/jdiameter

    项目框架

    jDiameter由它自己和ha(主要是多个java实例如何进行数据共享)组成,各自又分为api和impl两部分,api定义了接口,而impl则是实现。ha部分不在本文讨论范围。

    图1

    图1是一个jDiameter框架主要部分的简单示意图,一个Diameter应用由两部分组成,即base部分和application部分(如Sh应用)。在jDiameter中,由Stack负责diameter base协议部分的初始化和启动工作,Application则通过注册监听函数的方式被调用。

    在Diameter协议中,各个应用即Peer是对等的,没有主从的区分,也不区分客户端和服务器。jDiameter实现中Peer表示一个对等的远端Diameter应用,PeerFSM负责Peer的状态机,TransportLayer则是负责维持一个本Peer到对等Peer的长连接。注意jDiameter中有server和client代码包,而且server代码是继承自client的,这只是实现上逻辑的划分,不表示可以只用client部分启动jDiameter。Router则表示如何在多个Peer中选择路由。AppSession包含BaseSession,表示一个会话,数据存于SessionData Store中(本地或者ha),注意有的应用如Gx/Gy有状态,而有的如Sh是无状态的。

    启动

    下面我们来看一个例子如何使用jDiameter实现一个Sh应用:

     1 public class testServer extends ShSessionFactoryImpl implements NetworkReqListener {
     2 
     3     private static final Logger logger = Logger.getLogger(testServer.class);
     4     public static StackImpl stack;
     5     public static ISessionFactory sessionFactory;
     6 
     7     public static void main(String args[]) throws Exception {
     8         PropertyConfigurator.configure("log4j.properties");
     9         testServer t = testServer.init("config.xml");
    10         t.start();
    11         while (true) {
    12             Thread.sleep(10000);
    13         }
    14     }
    15 
    16     public testServer(SessionFactory sessionFactory) {
    17         super(sessionFactory);
    18     }
    19 
    20     public static testServer init(String fileName) {
    21         try {
    22             XMLConfiguration config = new XMLConfiguration(fileName);
    23             stack = new StackImpl();
    24             sessionFactory = (ISessionFactory) stack.init(config);
    25             testServer t = new testServer(sessionFactory);
    26             Network network = stack.unwrap(Network.class);
    27             network.addNetworkReqListener(t, ApplicationId.createByAuthAppId(10415, 16777217));
    28             sessionFactory.registerAppFacory(ServerShSession.class, t);
    29             sessionFactory.registerAppFacory(ClientShSession.class, t);
    30             return t;
    31         } catch (Exception e) {
    32             logger.error("Failed:", e);
    33             System.exit(-1);
    34         }
    35         return null;
    36     }
    37 
    38     public void start() throws IllegalDiameterStateException, InternalException {
    39         stack.start();
    40     }

    例1

    例1展示了如何初始化并启动一个Sh应用服务器(模拟HSS)。主要步骤为:

    1. 通过xml配置初始化Stack,得到session factory.
    2. 初始化app session factory,这里是ShSessionFactoryImpl,testServer继承自它。
    3. 注册app session listener,这里由于继承关系没有体现,可以使用如下代码:
    ((ShSessionFactoryImpl) appSessionFactory).setClientShSessionContext(this);
    ((ShSessionFactoryImpl) appSessionFactory).setClientShSessionListener(this);
    ((ShSessionFactoryImpl) appSessionFactory).setStateChangeListener(this);
    1. 注册network request listener,监听app request。
    2. 注册app session factory到session factory。
    3. 启动Stack。

    配置文件

    下面是上例所需的配置文件:

    <?xml version="1.0"?>
    <Configuration xmlns="http://www.jdiameter.org/jdiameter-server">
        <LocalPeer>
            <URI value="aaa://hss1.server.test.com:3868" />
            <IPAddresses>
                <IPAddress value="1.1.1.1" />
            </IPAddresses>
            <Realm value="server.test.com" />
            <VendorID value="0" />
            <ProductName value="hssServer" />
            <FirmwareRevision value="1" />
        </LocalPeer>
        <Parameters>
            <AcceptUndefinedPeer value="true" />
            <DuplicateProtection value="true" />
            <DuplicateTimer value="240000" />
            <UseUriAsFqdn value="false" />
            <QueueSize value="10000" />
            <MessageTimeOut value="60000" />
            <StopTimeOut value="10000" />
            <CeaTimeOut value="10000" />
            <IacTimeOut value="30000" />
            <DwaTimeOut value="10000" />
            <DpaTimeOut value="5000" />
            <RecTimeOut value="10000" />
            <Concurrent>
                <Entity name="ThreadGroup" size="64" />
                <Entity name="ProcessingMessageTimer" size="16" />
                <Entity name="DuplicationMessageTimer" size="16" />
                <Entity name="RedirectMessageTimer" size="16" />
                <Entity name="PeerOverloadTimer" size="16" />
                <Entity name="ConnectionTimer" size="16" />
                <Entity name="StatisticTimer" size="16" />
                <Entity name="ApplicationSession" size="32"/>
            </Concurrent>
        </Parameters>
        <Network>
            <Peers>
                <Peer name="aaa://sh.client.test.com:3868" ip="2.2.2.2" attempt_connect="false"    rating="1" />
            </Peers>
            <Realms>
                <Realm name="client.test.com" peers="sh.client.test.com" local_action="LOCAL" dynamic="false" exp_time="10000">
                    <ApplicationID>
                        <VendorId value="10415" />
                        <AuthApplId value="16777217" />
                        <AcctApplId value="0" />
                    </ApplicationID>
                </Realm>
            </Realms>
        </Network>
        <Extensions />
    </Configuration>

    config.xml

    LocalPeer 配置自己的相关信息。

    Parameters 配置的是jDiameter相关参数。

    Network 配置的是其他Peer的信息。

    详细结构可以参考jDiameter源码中的src/main/resources/jdiameter-server.xsd。

    实现App回调

    接上例我们来实现Sh应用服务器,主要有如下方法需要实现:

    图2

    下例是其中的一部分处理UserDataRequest:

     1     @Override
     2     public Answer processRequest(Request request) {
     3         int code = request.getCommandCode();
     4         if (code != ProfileUpdateRequest.code && code != UserDataRequest.code && code != SubscribeNotificationsRequest.code) {
     5             logger.error("Received Request with code not used by Sh!. Code[" + request.getCommandCode() + "]");
     6             return null;
     7         }
     8         try {
     9             AppSession serverShSession = ((ISessionFactory) sessionFactory).getNewAppSession(request.getSessionId(), appId, ServerShSession.class, (Object) null);
    10             ((NetworkReqListener) serverShSession).processRequest(request);
    11         } catch (Exception e) {
    12             logger.error("Fail to creat serverShSession", e);
    13         }
    14         return null;
    15     }
    16 
    17     @Override
    18     public void doUserDataRequestEvent(ServerShSession session, UserDataRequest request)
    19             throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
    20         UserDataAnswer answer = new UserDataAnswerImpl((Request) request.getMessage(), 2001);
    21         AvpSet set = answer.getMessage().getAvps();
    22         set.removeAvp(Avp.DESTINATION_HOST);
    23         set.removeAvp(Avp.DESTINATION_REALM);
    24         set.addAvp(Avp.USER_DATA_SH, "testdata", appId.getVendorId(), true, false, true);
    25         session.sendUserDataAnswer(answer);
    26         session.release();
    27     }

    例2

    其他回调方法类似。

    jDiameter负责连接对等的Peer,接受发送消息并解析,然后通过ApplicationId往上抛到回调函数处理Application业务逻辑。

    待续…

  • 相关阅读:
    sip
    GDB+GdbServer: ARM程序调试
    Wireshark Lua: 一个从RTP抓包里导出H.264 Payload,变成264裸码流文件(xxx.264)的Wireshark插件
    ffplay播放rtsp视频流花屏问题(含rtsp播放流程图)
    RTP 时间戳的处理
    RTSP
    RTP Tools
    图像编码中的小白问题sps ,pps ,nalu ,frame ,silce ect....
    H264中的SPS、PPS提取与作用
    VLC播放RTSP视频延迟问题
  • 原文地址:https://www.cnblogs.com/seasonsluo/p/jdiameter-intro.html
Copyright © 2011-2022 走看看