Hi,
I will try to reproduce/understand the issue and then fix it soon. Thanks for 
the detailed report!
Best regards 
Frank

> Am 19.01.2016 um 01:18 schrieb Bruno Filipe Basilio <[email protected]>:
> 
> 
> Hi,
> 
> Thank you for all your work in snmp4j and related.
> We are using snmp4j to handle NTCIP-PMPP protocol which is based in SNMP over 
> TCP.
> 
> More details about NTCIP-PMPP specification, see:
> http://www.ntcip.org/library/documents/pdf/pmpp01.pdf
> 
> The problem is that using upstream DefaultTcpTransportMapping some data is 
> discarded when the message received has a fragmented header, resulting in 
> incoherent message.
> Some changes were made to work around the problem, but as you can see bellow, 
> it isn't the prettiest since we hadn't many experience coding in snmp4j.
> You can see an example of the data exchange and the test code we have used to 
> replicate the problem using only snmp4j example code.
> 
> All feedback is appreciated, but maybe you can suggest a better solution and 
> add it in upstream snmp4j.
> 
> Here follows an example of the data exchanged and the fragmented response.
> *Sent data*
> 7E 05 13 C1 30 31 02 01 00 04 06 50 75 62 6C 69 63 A0 24 02 04 28 BA 92 8B 02 
> 01 00 02 01 00 30 16 30 14 06 10 2B 06 01 04 01 89 36 04 02 03 05 08 01 03 05 
> 01 05 00 AE 11 7E
> 
> *Received data fragments*
> 1)
> 7E 05 13
> 
> 2)
> C1 30 70 02 01 00 04 06 50 75 62 6C 69 63 A2 63 02 04 28 BA 92 8B 02 01 00 02 
> 01 00 30 55 30 53 06 10 2B 06 01 04 01 89 36 04 02 03 05 08 01 03 05 01 04 3F 
> 44 52 49 56 45 5B 6E 6C 5D 57 49 54 48 5B 6E 6C 5D 43 41 52 45 5B 6E 70 5D 54 
> 48 41 4E 4B 20 59 4F 55 5B
> 
> 3)
> 6E 6C 5D 46 4F 52 20 44 52 49 56 49 4E 47 5B 6E 6C 5D 4E 57 20 50 41 52 4B 57 
> 41 59 47 34 7E
> 
> The test code is as follows:
>        String host="127.0.0.1";
>        int port=7000;
>        boolean isPmpp= true;
>        String oid="1.3.6.1.4.1.1206.4.2.3.6.5.0";
>        String communityName="Public";
> 
>        TcpTransportMapping transportMapping= new DefaultTcpTransportMapping();
>        transportMapping.setMessageLengthDecoder(new 
> PmppMessageLengthDecoder());
>        MessageDispatcher messageDispatcher = new PmppMessageDispatcher();
>        messageDispatcher.addMessageProcessingModel(new MPv1());
>        Snmp snmp= new Snmp(messageDispatcher, transportMapping);
> 
>        Address targetAddress = GenericAddress.parse("tcp:" + host + "/" + 
> port);
> 
>        // setting up target
>        CommunityTarget target = new CommunityTarget();
>        target.setCommunity(new OctetString(communityName));
>        target.setAddress(targetAddress);
>        target.setRetries(2);
>        target.setTimeout(1500);
>        target.setVersion(SnmpConstants.version1);
>        // creating PDU
>        PDU pdu = new PDU();
>        pdu.add(new VariableBinding(new OID(oid)));
>        pdu.setType(PDU.GET);
> 
>        snmp.listen();
> 
>        // send the PDU
>        ResponseEvent response = snmp.send(pdu, target);
>        // extract the response PDU (could be null if timed out)
>        PDU responsePDU = response.getResponse();
> 
>        if(responsePDU==null) {
>            System.out.println("response null");
>            System.exit(-1);
>        }
> 
>        Vector vbs = responsePDU.getVariableBindings();
>        Variable ret=null;
>        if (vbs.size() > 0) {
>            VariableBinding vb = (VariableBinding) vbs.get(0);
>            ret = vb.getVariable();
>        }
>        snmp.close();
> 
>        System.out.println("s=" + ret);
> 
> 
> 
> *Changes suggested to work around the problem*
> pt.brisa.pmv.ntcip_adapter.manager.PmppTcpTransportMapping.ServerThread.readMessage(SelectionKey,
>  SocketChannel, TcpAddress)
> 
> --- a/org/snmp4j/transport/DefaultTcpTransportMapping.java      2015-12-30 
> 02:54:34.000000000 +0000
> +++ b/org/snmp4j/transport/DefaultTcpTransportMapping.java      2016-01-18 
> 23:30:53.604959600 +0000
> @@ -953,12 +992,25 @@ public class DefaultTcpTransportMapping
>         // slow but in some cases needed:
>         entry = sockets.get(incomingAddress);
>       }
> +
> +      ByteBuffer readBuffer =null;
>       if (entry != null) {
>         // note that socket has been used
>         entry.used();
> -        ByteBuffer readBuffer = entry.getReadBuffer();
> +        readBuffer = entry.getReadBuffer();
>         if (readBuffer != null) {
>           readChannel.read(readBuffer);
> +
> +          if(logger.isDebugEnabled()) {
> +              logger.debug("readBuffer != null, readBuffer.position() != 
> messageLengthDecoder.getMinHeaderLength():"
> +                      + 
> (readBuffer.position()!=messageLengthDecoder.getMinHeaderLength())
> +                      + ", readBuffer.position(): "+ readBuffer.position()
> +                  + ", readBuffer.limit(): "+ readBuffer.limit()
> +                  +", readBuffer.array():" + new 
> OctetString(readBuffer.array(), 0, readBuffer.limit()).toHexString());
> +          }
> +
> +          // don't handle fragment less then header length
> +          if (readBuffer.position() != 
> messageLengthDecoder.getMinHeaderLength()) {
>           if (readBuffer.hasRemaining()) {
>             entry.addRegistration(selector, SelectionKey.OP_READ);
>           }
> @@ -968,8 +1020,17 @@ public class DefaultTcpTransportMapping
>           }
>           return;
>         }
> +          if(logger.isDebugEnabled()) {
> +              logger.debug("readBuffer.position() != 
> messageLengthDecoder.getMinHeaderLength(), readBuffer.position(): "+ 
> readBuffer.position());
> +          }
> +        }
>       }
> -      ByteBuffer byteBuffer = ByteBuffer.wrap(buf);
> +
> +      ByteBuffer byteBuffer =null;
> +      long bytesRead = 0;
> +      if (readBuffer == null) {
> +          // prepare a read fist fragment
> +          byteBuffer = ByteBuffer.wrap(buf);
>       byteBuffer.limit(messageLengthDecoder.getMinHeaderLength());
>       if (!readChannel.isOpen()) {
>         sk.cancel();
> @@ -979,12 +1040,14 @@ public class DefaultTcpTransportMapping
>         }
>         return;
>       }
> -      long bytesRead = 0;
>       try {
>         bytesRead = readChannel.read(byteBuffer);
>         if (logger.isDebugEnabled()) {
>           logger.debug("Reading header " + bytesRead + " bytes from " +
>                        incomingAddress);
> +              logger.debug("entry != null, byteBuffer read, 
> byteBuffer.position(): "+ byteBuffer.position()
> +                  + ", readBuffer.limit(): "+ byteBuffer.limit()
> +                  +", readBuffer.array():" + new 
> OctetString(byteBuffer.array(), 0, byteBuffer.limit()).toHexString());
>         }
>       }
>       catch (ClosedChannelException ccex) {
> @@ -995,6 +1058,29 @@ public class DefaultTcpTransportMapping
>         }
>         return;
>       }
> +      }
> +      else {
> +          // get buffer info from previous read saved in entry
> +          byteBuffer=readBuffer;
> +          bytesRead=readBuffer.position();
> +          ByteBuffer b = ByteBuffer.wrap(buf);
> +          b.put(readBuffer.array(), 0, (int) bytesRead);
> +      }
> +
> +      if (bytesRead> 0 && 
> bytesRead<messageLengthDecoder.getMinHeaderLength()) {
> +          // handle read fragment less than header length and save it in 
> entry
> +          byte[] message = new byte[byteBuffer.capacity()];
> +          int bufpos = byteBuffer.position();
> +          int buflim = byteBuffer.limit();
> +          byteBuffer.flip();
> +          byteBuffer.get(message, 0, bufpos);
> +          ByteBuffer newBuffer = ByteBuffer.wrap(message);
> +          newBuffer.position(bufpos);
> +          newBuffer.limit(buflim);
> +          if (entry != null) {
> +            entry.setReadBuffer(newBuffer);
> +          }
> +      }
>       if (bytesRead == messageLengthDecoder.getMinHeaderLength()) {
>         MessageLength messageLength =
>             messageLengthDecoder.getMessageLength(ByteBuffer.wrap(buf));
> @@ -1019,6 +1105,12 @@ public class DefaultTcpTransportMapping
>           byteBuffer.limit(messageLength.getMessageLength());
>           bytesRead += readChannel.read(byteBuffer);
>           if (bytesRead == messageLength.getMessageLength()) {
> +              if(entry!=null){
> +                  if(logger.isDebugEnabled()) {
> +                      logger.debug("bytesRead == 
> messageLength.getMessageLength(), bytesRead: "+ bytesRead);
> +                  }
> +                  entry.setReadBuffer(null); // <== set read buffer of entry 
> to null
> +              }
>             dispatchMessage(incomingAddress, byteBuffer, bytesRead, entry);
>           }
>           else {
> 
> 
> Best regards,
> Bruno
> 
> 
> Bruno Filipe Basílio
> Departamento de Investigação, Desenvolvimento e Inovação
> 
> Tel: (+351) 214233436
> 
> http://www.brisainovacao.pt
> 
> 
> 
> 
> 
> 
> 
> --------------------------------------------------------------------------------
> 
> Declaração:
> A informação contida nesta mensagem, e os ficheiros anexos, é privilegiada e 
> confidencial, destinando-se exclusivamente ao(s) destinatário(s).Se não é o 
> destinatário (ou o responsável pela sua entrega ao destinatário) e recebeu a 
> mesma por engano, fica notificado que é estritamente proibido reproduzir, 
> guardar ou distribuir toda ou qualquer parte desta mensagem e ficheiros 
> anexos. Por favor reencaminhe a mensagem para o responsável pelo seu envio ou 
> contacte-nos por telefone e elimine a mensagem e ficheiros anexos do seu 
> computador, sem os reproduzir.
> 
> Disclaimer:
> The information contained in this message, and any files attached, is 
> privileged and confidential, and intended exclusively for the included 
> addresses. If you are not the intended recipient (or the person responsible 
> for delivering to the intended recipient) and received this message by 
> mistake, be aware that copy, storage, distribution or any other use of all or 
> part of this message and the files attached is strictly prohibited. Please 
> notify the sender by reply e-mail or contact us by telephone and delete this 
> message and the files attached, without retaining a copy.
> 
> --------------------------------------------------------------------------------
> 
> _______________________________________________
> SNMP4J mailing list
> [email protected]
> https://oosnmp.net/mailman/listinfo/snmp4j
_______________________________________________
SNMP4J mailing list
[email protected]
https://oosnmp.net/mailman/listinfo/snmp4j

Reply via email to