SIP сервлеты, чатсервер - PullRequest
1 голос
/ 28 мая 2010

Я пытаюсь заставить сервер чата SIP сервлета работать, вместе с текстовым клиентом, найденным здесь .

Когда я использую 2 клиента для отправки сообщений друг другу (peer to peer), все идет хорошо. Но когда я использую один или несколько клиентов вместе с моим сервером, мне нужно подождать ровно 32 секунды, прежде чем сервер получит новые сообщения в методе doMessage(). Я использую Netbeans вместе с Sailfin в качестве SIP-сервера. Есть ли какое-то ограничение или настраиваемая задержка или тайм-аут между запросами или ответами в Sailfin, который я просматриваю?

При необходимости могу выложить код сервера.

Спасибо

Ответы [ 3 ]

2 голосов
/ 31 мая 2010

Вот код сервера, позже я попытаюсь выполнить трассировку Wireshark.

public class ChatroomSipServlet extends SipServlet {

    public final static String USER_LIST = "userList";

    public final static String CHATROOM_SERVER_NAME = "chatroomservername";

    public String serverAddress;
    public SipFactory factory;

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        super.init(servletConfig);
        System.out.println("Chatroom sip servlet is gestart!");
        try {
            factory = (SipFactory) getServletContext().getAttribute("javax.servlet.sip.SipFactory");
            System.out.println("Sip Factory: " + factory);
        } catch (Exception e) {
            throw new ServletException("Factory probleem!", e);
        }
        getServletContext().setAttribute(USER_LIST, new ArrayList<String>());
        serverAddress = getServletConfig().getInitParameter(CHATROOM_SERVER_NAME);
        System.out.println("serverAddress is: " + serverAddress);
    }

    @Override
    public void destroy() {
        try {
            sendToAll(serverAddress, "Server sluit af!");
        } catch (Throwable e) {

            e.printStackTrace();
        }
        super.destroy();
    }

    protected void doMessage(SipServletRequest request) throws ServletException, IOException {

        System.out.println(getDateTime() + " Bericht ontvangen");

        request.createResponse(SipServletResponse.SC_OK).send();

        String message = request.getContent().toString();
        String from = ((SipURI) request.getFrom().getURI()).toString();

        if (message.equalsIgnoreCase("/quit")) {
            sendToUser(from, "Bye");
            removeUser(from);
            return;
        }

        if (!containsUser(from)) {
            sendToUser(from, "Welkom in de chatroom. Typ '/quit' om af te sluiten.");
            addUser(from);
        }

        if (message.equalsIgnoreCase("/who")) {
            String users = "Lijst van de gebruikers:\n";
            List<String> list = (List<String>) getServletContext().getAttribute(USER_LIST);
            for (String user : list) {
                users += user + "\n";
            }
            sendToUser(from, users);
            return;
        }

        if (message.equalsIgnoreCase("/join")) {
            return;
        }

        sendToAll(from, message);
    }

    protected void doErrorResponse(SipServletResponse response) throws ServletException, IOException {

//      String receiver = response.getTo().toString();
        String receiver = ((SipURI) response.getTo().getURI()).toString();
        System.out.println(getDateTime() + " Errorresponse voor " + receiver);
        removeUser(receiver);
    }

    protected void doSuccessResponse(SipServletResponse response) throws ServletException, IOException {

        response.getApplicationSession().invalidate();
    }

    private void sendToAll(String from, String message) throws ServletParseException, IOException {

        List<String> list = (List<String>) getServletContext().getAttribute(USER_LIST);
        for (String user : list) {
            SipApplicationSession session = factory.createApplicationSession();
            System.out.println(getDateTime() + " Session created voor " + user);
            SipServletRequest request = factory.createRequest(session, "MESSAGE", serverAddress, user);
            String msg = from + " stuurt: \n" + message;
            request.setContent(msg.getBytes(), "text/plain");
            request.send();
        }
    }

    private void sendToUser(String to, String message) throws ServletParseException, IOException {

        SipApplicationSession session = factory.createApplicationSession();
        SipServletRequest request = factory.createRequest(session, "MESSAGE", serverAddress, to);
        request.setContent(message.getBytes(), "text/plain");
        request.send();
    }

    private boolean containsUser(String from) {
        List<String> list = (List<String>) getServletContext().getAttribute(USER_LIST);
        return list.contains(from);
    }

    private void addUser(String from) {
        List<String> list = (List<String>) getServletContext().getAttribute(USER_LIST);
        list.add(from);
    }

    private void removeUser(String from) {
        System.out.println(getDateTime() + " " + from + " wordt verwijderd uit de lijst.");
        List<String> list = (List<String>) getServletContext().getAttribute(USER_LIST);
        list.remove(from);

    }

    @Override
    protected void doRegister(SipServletRequest req) throws ServletException, IOException {
        System.out.println("Register request ontvangen: " + req.getTo());
        int response = SipServletResponse.SC_OK;
        SipServletResponse resp = req.createResponse(response);
        resp.send();
    }

    private String getDateTime() {
        DateFormat dateFormat = new SimpleDateFormat("[" + "HH:mm:ss" + "]");
        Date date = new Date();
        return dateFormat.format(date);
    }
}

и sip.xml

<sip-app>
    <app-name>sip.chatvoorbeeld.ChatServer</app-name>
    <display-name>Chatroom Sip Servlet</display-name>
    <description>Chatroom Sip Servlet</description>

    <servlet-selection>
        <main-servlet>
            ChatroomSipServlet
        </main-servlet>
    </servlet-selection>
    <session-config>
        <session-timeout>5</session-timeout>
    </session-config>

    <servlet>
        <servlet-name>ChatroomSipServlet</servlet-name>
        <display-name>ChatroomSipServlet</display-name>
        <description>Chatroom SIP servlet</description>
        <servlet-class>
            sip.chatvoorbeeld.ChatroomSipServlet
        </servlet-class>
        <init-param>
            <param-name>chatroomservername</param-name>
            <param-value>sip:chatserver@192.168.56.1:5060</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
</sip-app>

Я также попробовал пустой сервлет, просто с помощью метода doMessage(), который просто печатает «сообщение получено». Та же самая 32-секундная задержка ...

Wireshark дает мне:

Я отправляю сообщение «тест» на сервер:

MESSAGE sip:chatserver@192.168.56.1:5060;transport=udp SIP/2.0
Call-ID: aba00c2646a9b4e6df3b15df19dbf58d@192.168.56.101
CSeq: 1 MESSAGE
From: "bobby" <sip:bobby@192.168.56.101:5095>;tag=textclientv1.0
To: "chatserver" <sip:chatserver@192.168.56.1:5060>
Via: SIP/2.0/UDP 192.168.56.101:5095;branch=branch1
Max-Forwards: 70
Contact: "bobby" <sip:bobby@192.168.56.101:5095>
Content-Type: text/plain
Content-Length: 4

test

Сервер отправляет обратно:

SIP/2.0 200 OK
Content-Length: 0
To: "chatserver"<sip:chatserver@192.168.56.1:5060>;tag=g9vdns7u-e
Cseq: 1 MESSAGE
Via: SIP/2.0/UDP 192.168.56.101:5095;branch=branch1
From: "bobby"<sip:bobby@192.168.56.101:5095>;tag=textclientv1.0
Call-Id: aba00c2646a9b4e6df3b15df19dbf58d@192.168.56.101
Server: Glassfish_SIP_2.0.0

MESSAGE sip:bobby@192.168.56.101:5095 SIP/2.0
Max-Forwards: 69
Content-Length: 43
To: <sip:bobby@192.168.56.101:5095>
Cseq: 1 MESSAGE
Via: SIP/2.0/UDP 192.168.56.1:5060;branch=z9hG4bKdaacb7673c871796474ca951221a6643db6c
Content-Type: text/plain
Call-Id: 192.168.56.1_11_6595680936174578736
From: <sip:chatserver@192.168.56.1:5060>;tag=g9vdns7u-g

sip:bobby@192.168.56.101:5095 stuurt: 
test

Тогда мой клиент снова отвечает OK:

SIP/2.0 200 OK
To: <sip:bobby@192.168.56.101:5095>;tag=888
CSeq: 1 MESSAGE
Via: SIP/2.0/UDP 192.168.56.1:5060;branch=z9hG4bKdaacb7673c871796474ca951221a6643db6c;received=192.168.56.1
Call-ID: 192.168.56.1_11_6595680936174578736
From: <sip:chatserver@192.168.56.1:5060>;tag=g9vdns7u-g
Content-Length: 0

Пока все хорошо, все работает хорошо. Но теперь я отправляю второе сообщение на сервер «test2» и получаю следующее:

Клиент-сервер:

MESSAGE sip:chatserver@192.168.56.1:5060;transport=udp SIP/2.0
Call-ID: 95ad65365378b9b6b5bd7ad3629f7b02@192.168.56.101
CSeq: 1 MESSAGE
From: "bobby" <sip:bobby@192.168.56.101:5095>;tag=textclientv1.0
To: "chatserver" <sip:chatserver@192.168.56.1:5060>
Via: SIP/2.0/UDP 192.168.56.101:5095;branch=branch1
Max-Forwards: 70
Contact: "bobby" <sip:bobby@192.168.56.101:5095>
Content-Type: text/plain
Content-Length: 5

test2

Затем сервер отвечает:

SIP/2.0 200 OK
Content-Length: 0
To: "chatserver"<sip:chatserver@192.168.56.1:5060>;tag=g9vdns7u-e
Cseq: 1 MESSAGE
Via: SIP/2.0/UDP 192.168.56.101:5095;branch=branch1
From: "bobby"<sip:bobby@192.168.56.101:5095>;tag=textclientv1.0
Call-Id: aba00c2646a9b4e6df3b15df19dbf58d@192.168.56.101
Server: Glassfish_SIP_2.0.0

Но затем связь прекращается ... Я получаю 200 OK, но println() в моем doMessage() методе не передается.

1 голос
/ 30 мая 2010

32 секунды - это обычный тайм-аут для транзакций (обозначается 64 * T1 в RFC3261, где по умолчанию для T1 - 500 мс.)

Я не имею прямого представления о решении вашей проблемы, за исключением того, что тайм-аут, скорее всего, НЕ является неправильной конфигурацией в SailFin. Поэтому, пожалуйста, предоставьте трассировку Wireshark и код сервера!

0 голосов
/ 08 июня 2010

Чтобы ответить на мой собственный вопрос, если кто-то когда-либо сталкивался с той же проблемой, я обнаружил, что это ошибка в текстовом клиенте по отношению к следующему разделу 8.1.1.7 RFC 3261.

Значение параметра ветви ДОЛЖНО быть уникальный в пространстве и времени для всех запросы, отправленные UA. Исключениями из этого правила являются ОТМЕНА и ACK для не-2xx ответов. Как обсуждается ниже, запрос на отмену будет имеют одинаковое значение ветви Параметр как запрос он отменяет. Как обсуждено в Разделе 17.1.1.3, ACK для ответа не-2xx также иметь тот же идентификатор ветви, что и INVITE чей ответ он признает.

Свойство уникальности филиала Параметр ID, чтобы облегчить его использование в качестве идентификатор транзакции, не являющийся частью RFC 2543.

ID ветви, вставленный элементом в соответствии с этой спецификацией ДОЛЖНЫ всегда начинайте с символов "Z9hG4bK".

Следующая строка в SipLayer.java

ViaHeader viaHeader = headerFactory.createViaHeader(getHost(),
getPort(), "udp", "branch1");

Создает каждое сообщение с параметром "branch1". Создание этого параметра уникальным устраняет проблему.

...