Project

General

Profile

tigase custom Message Delivery Receipts question

Raylin lin
Added almost 5 years ago

hi,all:

  I added a custom Message Delivery Receipts,and still find masses of lose packets over mobile 3g devices.

after send a chat message to the client,the system will check whether the client has got the message, if not, send it again. but we still find lots of packets lost over mobile 3G. is there some smarter method to solve this problem? thank you.

in tigase.server.xmppclient.ClientConnectionManager.

public void processPacket(final Packet packet) {
        if (log.isLoggable(Level.FINEST)) {
            log.log(Level.FINEST, "Processing packet: {0}", packet.toStringSecure());
        }
        if (packet.isCommand() && (packet.getCommand() != Command.OTHER)) {
            processCommand(packet);
        } else {
            //added by ldy
            boolean isMessage = false;
            TigMessage tigMessage = null;
            if(packet instanceof  Message )
            {
                tigMessage = this.getMessage(packet);
                isMessage = true;
            }
            final String packetId = tigMessage!=null ? tigMessage.getPacketId():null;
            final String sender = tigMessage!=null ? tigMessage.getSender():null;
            final String receiver = tigMessage!=null ? tigMessage.getReceiver():null;
            //ended by ldy
            if (!writePacketToSocket(packet)) {
                log.log(Level.FINEST, "failed to send");
                restorePacket(packet);
                return;
            }
            if(isMessage)
            {
                             // start a new thread to do resending job.

                new Thread(){  
                    public void run(){  
                        try {
                                Thread.sleep(2000);
                                boolean sent = dbmessage_repo.getTigMessage(packetId,sender,receiver);
                                if(!sent)
                                {   
                                    for(int tryIndex=1;tryIndex<=120;tryIndex++)
                                    {
                                        Random ran = new Random();
                                        int sleepTime = ran.nextInt(101)+100;
                                        Thread.sleep(sleepTime);
                                        sent = dbmessage_repo.getTigMessage(packetId,sender,receiver);
                                        if(!sent)
                                        {   
                                            if(tryIndex%30!=0)
                                            {
                                                continue;
                                            }
                                            log.log(Level.FINEST, "failed to send message:"+packetId);
                                            if (!writePacketToSocket(packet)) {
                                                restorePacket(packet);
                                                return;
                                            }
                                        }
                                        else
                                        {
                                            //sent successfully
                                            return;
                                        }
                                    }

                                }
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                    }  
                }.start();  

            }
        }    // end of else
    }

private void restorePacket(final Packet packet)
    {
        // Connection closed or broken, send message back to the SM
        // if this is not IQ result...
        // Ignore also all presence packets with available, unavailble
        if ((packet.getType() != StanzaType.result) && (packet.getType() != StanzaType
                .available) && (packet.getType() != StanzaType.unavailable) && (packet
                .getType() != StanzaType.error) &&!((packet.getElemName() == "presence") &&
                (packet.getType() == null))) {
            try {
                Packet error = Authorization.ITEM_NOT_FOUND.getResponseMessage(packet,
                        "The user connection is no longer active.", true);

                addOutPacket(error);
            } catch (PacketErrorTypeException e) {
                if (log.isLoggable(Level.FINEST)) {
                    log.finest(
                            "Ups, already error packet. Dropping it to prevent infinite loop.");
                }
            }
        }

        // In case the SessionManager lost synchronization for any
        // reason, let's
        // notify it that the user connection no longer exists.
        // But in case of mass-disconnects we might have lot's of
        // presences
        // floating around, so just skip sending stream_close for all
        // the
        // offline presences
        if ((packet.getType() != StanzaType.unavailable) && (packet.getPacketFrom() !=
                null)) {
            if (packet.getStanzaTo() != null) {
                Packet command = Command.STREAM_CLOSED_UPDATE.getPacket(packet.getStanzaTo(),
                        packet.getPacketFrom(), StanzaType.set, UUID.randomUUID().toString());

                command.setPacketFrom(packet.getPacketTo());
                command.setPacketTo(packet.getPacketFrom());

                // Note! we don't want to receive response to this
                // request,
                // thus STREAM_CLOSED_UPDATE instead of STREAM_CLOSED
                addOutPacket(command);

                // addOutPacketWithTimeout(command, stoppedHandler, 15l,
                // TimeUnit.SECONDS);
                if (log.isLoggable(Level.FINE)) {
                    log.log(Level.FINE,
                            "Sending a command to close the remote session for non-existen {0} connection: {1}",
                            new Object[] { getName(),
                            command.toStringSecure() });
                }
            } else {
                if (log.isLoggable(Level.WARNING)) {
                    log.log(Level.FINE,
                            "Stream close update without an user JID, skipping for packet: {0}",
                            new Object[] { packet });
                }
            }//end of else
        } // end of if
    }

Replies (3)

Added by Wojciech Kapcia TigaseTeam almost 5 years ago

Which version do you use/modify? Can you check sources that implement #1933 ( f12d7d05527687398baa6301ff37e7c20f32c0f9 ) which in principle does something similar - if there is a problem with delivering packet to connection that gone missing then packet is sent back to session manager for processing (an given that the connection is gone, to offline storage and subsequently, after reconnect, back to delivery).

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam almost 5 years ago

Indeed, I do not think you need a custom message delivery receipts while there is a stream management support in the Tigase server.

Added by xiaotu ju almost 5 years ago

Wojciech Kapcia wrote:

Which version do you use/modify? Can you check sources that implement #1933 ( f12d7d05527687398baa6301ff37e7c20f32c0f9 ) which in principle does something similar - if there is a problem with delivering packet to connection that gone missing then packet is sent back to session manager for processing (an given that the connection is gone, to offline storage and subsequently, after reconnect, back to delivery).

i checkout the resource,but lost message when client disconnect from network

    (1-3/3)