title: SSLEngine giving NEED_UNWRAP after unwrapping server hello done
body: <p>I am using <code>DTLS1.0</code> provided by java 9. It successfully generate <code>Client Hello</code> and server response back with </p>
  
  <pre><code> 1. Server Hello
   2. Certificate
   3. Server Key Exchange
   4. Certificate Request
   5. Server Hello Done   
  </code></pre>
  
  <p>Then SSLEngine gives <code>NEED_UNWRAP</code>. After unwrapping the packets containing the <code>Server Hello Done</code> it again gives <code>NEED_UNWRAP</code>. After unwrapping the next re transmitted <code>Server Hello Done</code> it again gives <code>NEED_UNWRAP</code>. It goes again and again.  But i think it should generate the next handshaking signal by giving <code>NEED_WRAP</code>.  </p>
  
  <p>If i am wrong, please correct me. Otherwise Why it is happening?  </p>
  
  <p><strong>Trust Manager:</strong></p>
  
  <pre><code>    final TrustManager[] trustAllCerts = new TrustManager[] {
          new X509TrustManager() {
  
              public X509Certificate[] getAcceptedIssuers() {
                  // TODO Auto-generated method stub
                  return null;
              }
  
              public void checkServerTrusted(X509Certificate[] arg0, String arg1)
                      throws CertificateException {
                  // TODO Auto-generated method stub
  
              }
  
              public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                      throws CertificateException {
                  // TODO Auto-generated method stub
  
              }
          }
      };  
  </code></pre>
  
  <p><strong>SSLEngine:</strong>  </p>
  
  <pre><code>        char[] passphrase = "123456".toCharArray();//This is the password
  
          // First initialize the key and trust material
          KeyStore ksKeys = KeyStore.getInstance("JKS");
          ksKeys.load(new FileInputStream("keystore"), passphrase);
  
          // KeyManagers decide which key material to use
          KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
          kmf.init(ksKeys, passphrase);
  
  
          SSLContext sslContext = SSLContext.getInstance("DTLSv1.0");
          sslContext.init(kmf.getKeyManagers(), trustAllCerts, null);
  
  
          int port2 = Queuemanager.switchMediaHandler.get("192.168.19.148").realPort;
          // Create the engine
          engine = sslContext.createSSLEngine("192.168.19.148", port2);
  
          // Use as client
          engine.setUseClientMode(true);
          engine.setEnableSessionCreation(true);
  </code></pre>
  
  <p><strong>Handshake:</strong></p>
  
  <pre><code>    void doHandshake(){
      engine.beginHandshake();        
      SSLEngineResult result; 
      HandshakeStatus handshakeStatus;        
      int appBufferSize = engine.getSession().getApplicationBufferSize();
      ByteBuffer myAppData = ByteBuffer.allocate(appBufferSize);
      ByteBuffer peerAppData = ByteBuffer.allocate(appBufferSize);
      myNetData.clear();
      peerNetData.clear();
  
      handshakeStatus = engine.getHandshakeStatus();
      while (handshakeStatus != SSLEngineResult.HandshakeStatus.FINISHED &amp;&amp; handshakeStatus != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {             
          switch (handshakeStatus) {
          case NEED_UNWRAP_AGAIN:
              logger.debug("NEED_UNWRAP_AGAIN");
          case NEED_UNWRAP:
              logger.debug("NEED_UNWRAP");
              DatagramPacket packet = null;
             if(handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP ) {
              try {
                  byte[] buf = new byte[1024];
                  packet = new DatagramPacket(buf, buf.length);
                  socket.receive(packet);
                  peerNetData = ByteBuffer.wrap(buf, 0, packet.getLength());
                  peerAppData =  ByteBuffer.allocate(appBufferSize);
              } catch (IOException e1) {
                  // TODO Auto-generated catch block
                  e1.printStackTrace();
              }
            }else{
                 peerNetData = ByteBuffer.allocate(0);
                 peerAppData =  ByteBuffer.allocate(appBufferSize);
             }
  
  
              SSLEngineResult.Status rs;
              result = null;
              try {
  
                  handshakeStatus = engine.getHandshakeStatus();
                  while(handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP || handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP_AGAIN) {
                      result = engine.unwrap(peerNetData, peerAppData);
                      peerNetData.compact();  
                      handshakeStatus = result.getHandshakeStatus();
                   }
  
                  handshakeStatus = result.getHandshakeStatus();
  
                  rs = result.getStatus();
  
              } catch (SSLException sslException) {
                  engine.closeOutbound();                    
                  break;
              }
              switch (rs) {
              case OK:
                  break;
              case BUFFER_OVERFLOW:
                  break;
              case BUFFER_UNDERFLOW:
                  break;
              case CLOSED:
              default:
                  throw new IllegalStateException("Invalid SSL status: " + result.getStatus());
              }
              break;
          case NEED_WRAP:
              logger.debug("NEED_WRAP");
              myNetData.clear();
              try {
                  result = engine.wrap(myAppData, myNetData);
                  handshakeStatus = result.getHandshakeStatus();
              } catch (SSLException sslException) {
                  engine.closeOutbound();
                  handshakeStatus = engine.getHandshakeStatus();
                  break;
              }
              switch (result.getStatus()) {
              case OK :                                       
  
                  while (myNetData.hasRemaining()) {
                      //String str = myNetData.toString();
                      byte[] arr = new byte[myNetData.remaining()];
                      myNetData.get(arr);
                      recvPacket = new DatagramPacket(arr, arr.length);
                      recvPacket.setData(arr);
  
                      try {
                          int port2 = Queuemanager.switchMediaHandler.get("192.168.19.148").realPort;
  
                          InetAddress ip = InetAddress.getByName("192.168.19.148");       
  
                          recvPacket.setAddress(ip);
                          recvPacket.setPort(port2);     
  
                          socket.send(recvPacket);
  
                      } catch (IOException e) {
                          // TODO Auto-generated catch block
                          e.printStackTrace();
                      }
                      //socketChannel.write(myNetData);
                  }
  
              case BUFFER_OVERFLOW:
              case BUFFER_UNDERFLOW:
              case CLOSED:
              case NEED_TASK:
                   Runnable task;
                   while ((task = engine.getDelegatedTask()) != null) {
                        new Thread(task).start();
                   }
                   handshakeStatus = engine.getHandshakeStatus();
                   break;
      }           
  }
  </code></pre>